926b4dfbea7bda66f5311230298926a8cacac2b3
[mono.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Asn1 / Asn1Identifier.cs
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc.  www.novell.com
4
5 * Permission is hereby granted, free of charge, to any person obtaining  a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including  without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
9 * copies of the Software, and to  permit persons to whom the Software is 
10 * furnished to do so, subject to the following conditions:
11
12 * The above copyright notice and this permission notice shall be included in 
13 * all copies or substantial portions of the Software.
14
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
23 //
24 // Novell.Directory.Ldap.Asn1.Asn1Identifier.cs
25 //
26 // Author:
27 //   Sunil Kumar (Sunilk@novell.com)
28 //
29 // (C) 2003 Novell, Inc (http://www.novell.com)
30 //
31
32 using System;
33
34 namespace Novell.Directory.Ldap.Asn1
35 {
36         
37         /// <summary> This class is used to encapsulate an ASN.1 Identifier.
38         /// 
39         /// An Asn1Identifier is composed of three parts:
40         /// <li> a class type,</li>
41         /// <li> a form, and</li>
42         /// <li> a tag.</li>
43         /// 
44         /// The class type is defined as:
45         /// <pre>
46         /// bit 8 7 TAG CLASS
47         /// ------- -----------
48         /// 0 0 UNIVERSAL
49         /// 0 1 APPLICATION
50         /// 1 0 CONTEXT
51         /// 1 1 PRIVATE
52         /// </pre>
53         ///  The form is defined as:
54         /// <pre>
55         /// bit 6 FORM
56         /// ----- --------
57         /// 0 PRIMITIVE
58         /// 1 CONSTRUCTED
59         /// </pre>
60         /// 
61         ///  Note: CONSTRUCTED types are made up of other CONSTRUCTED or PRIMITIVE
62         /// types.
63         /// 
64         ///  The tag is defined as:
65         /// <pre>
66         /// bit 5 4 3 2 1 TAG
67         /// ------------- ---------------------------------------------
68         /// 0 0 0 0 0
69         /// . . . . .
70         /// 1 1 1 1 0 (0-30) single octet tag
71         /// 
72         /// 1 1 1 1 1 (> 30) multiple octet tag, more octets follow
73         /// </pre>
74         /// </summary>
75         [CLSCompliantAttribute(true)]
76         public class Asn1Identifier:System.Object, System.ICloneable
77         {
78                 /// <summary> Returns the CLASS of this Asn1Identifier as an int value.
79                 /// 
80                 /// </summary>
81                 /// <seealso cref="UNIVERSAL">
82                 /// </seealso>
83                 /// <seealso cref="APPLICATION">
84                 /// </seealso>
85                 /// <seealso cref="CONTEXT">
86                 /// </seealso>
87                 /// <seealso cref="PRIVATE">
88                 /// </seealso>
89                 virtual public int Asn1Class
90                 {
91                         get
92                         {
93                                 return tagClass;
94                         }
95                         
96                 }
97                 /// <summary> Return a boolean indicating if the constructed bit is set.
98                 /// 
99                 /// </summary>
100                 /// <returns> true if constructed and false if primitive.
101                 /// </returns>
102                 virtual public bool Constructed
103                 {
104                         get
105                         {
106                                 return constructed;
107                         }
108                         
109                 }
110                 /// <summary> Returns the TAG of this Asn1Identifier.</summary>
111                 virtual public int Tag
112                 {
113                         get
114                         {
115                                 return tag;
116                         }
117                         
118                 }
119                 /// <summary> Returns the encoded length of this Asn1Identifier.</summary>
120                 virtual public int EncodedLength
121                 {
122                         get
123                         {
124                                 return encodedLength;
125                         }
126                         
127                 }
128                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
129                 /// has a TAG CLASS of UNIVERSAL.
130                 /// 
131                 /// </summary>
132                 /// <seealso cref="UNIVERSAL">
133                 /// </seealso>
134                 [CLSCompliantAttribute(false)]
135                 virtual public bool Universal
136                 {
137                         get
138                         {
139                                 return tagClass == UNIVERSAL;
140                         }
141                         
142                 }
143                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
144                 /// has a TAG CLASS of APPLICATION.
145                 /// 
146                 /// </summary>
147                 /// <seealso cref="APPLICATION">
148                 /// </seealso>
149                 [CLSCompliantAttribute(false)]
150                 virtual public bool Application
151                 {
152                         get
153                         {
154                                 return tagClass == APPLICATION;
155                         }
156                         
157                 }
158                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
159                 /// has a TAG CLASS of CONTEXT-SPECIFIC.
160                 /// 
161                 /// </summary>
162                 /// <seealso cref="CONTEXT">
163                 /// </seealso>
164                 [CLSCompliantAttribute(false)]
165                 virtual public bool Context
166                 {
167                         get
168                         {
169                                 return tagClass == CONTEXT;
170                         }
171                         
172                 }
173                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
174                 /// has a TAG CLASS of PRIVATE.
175                 /// 
176                 /// </summary>
177                 /// <seealso cref="PRIVATE"></seealso>
178                 [CLSCompliantAttribute(false)]
179                 virtual public bool Private
180                 {
181                         get
182                         {
183                                 return tagClass == PRIVATE;
184                         }
185                         
186                 }
187                 
188                 /// <summary> Universal tag class.
189                 /// 
190                 ///  UNIVERSAL = 0 
191                 /// </summary>
192                 public const int UNIVERSAL = 0;
193                 
194                 /// <summary> Application-wide tag class.
195                 /// 
196                 ///  APPLICATION = 1 
197                 /// </summary>
198                 public const int APPLICATION = 1;
199                 
200                 /// <summary> Context-specific tag class.
201                 /// 
202                 ///  CONTEXT = 2 
203                 /// </summary>
204                 public const int CONTEXT = 2;
205                 
206                 /// <summary> Private-use tag class.
207                 /// 
208                 ///  PRIVATE = 3 
209                 /// </summary>
210                 public const int PRIVATE = 3;
211                 
212                 
213                 /* Private variables
214                 */
215                 
216                 private int tagClass;
217                 private bool constructed;
218                 private int tag;
219                 private int encodedLength;
220                 
221                 /* Constructors for Asn1Identifier
222                 */
223                 
224                 /// <summary> Constructs an Asn1Identifier using the classtype, form and tag.
225                 /// 
226                 /// </summary>
227                 /// <param name="tagClass">As defined above.
228                 /// 
229                 /// </param>
230                 /// <param name="constructed">Set to true if constructed and false if primitive.
231                 /// 
232                 /// </param>
233                 /// <param name="tag">The tag of this identifier
234                 /// </param>
235                 public Asn1Identifier(int tagClass, bool constructed, int tag)
236                 {
237                         this.tagClass = tagClass;
238                         this.constructed = constructed;
239                         this.tag = tag;
240                 }
241                 
242                 /// <summary> Decode an Asn1Identifier directly from an InputStream and
243                 /// save the encoded length of the Asn1Identifier.
244                 /// 
245                 /// </summary>
246                 /// <param name="in">The input stream to decode from.
247                 /// </param>
248                 public Asn1Identifier(System.IO.Stream in_Renamed)
249                 {
250                         int r = in_Renamed.ReadByte();
251                         encodedLength++;
252                         if (r < 0)
253                                 throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in Identifier");
254                         tagClass = r >> 6;
255                         constructed = (r & 0x20) != 0;
256                         tag = r & 0x1F; // if tag < 30 then its a single octet identifier.
257                         if (tag == 0x1F)
258                         // if true, its a multiple octet identifier.
259                                 tag = decodeTagNumber(in_Renamed);
260                         return ;
261                 }
262                 
263                 public Asn1Identifier()
264                 {
265                         return ;
266                 }
267                 
268                 /// <summary> Decode an Asn1Identifier directly from an InputStream and
269                 /// save the encoded length of the Asn1Identifier, but reuse the object.
270                 /// 
271                 /// </summary>
272                 /// <param name="in">The input stream to decode from.
273                 /// </param>
274                 public void  reset(System.IO.Stream in_Renamed)
275                 {
276                         encodedLength = 0;
277                         int r = in_Renamed.ReadByte();
278                         encodedLength++;
279                         if (r < 0)
280                                 throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in Identifier");
281                         tagClass = r >> 6;
282                         constructed = (r & 0x20) != 0;
283                         tag = r & 0x1F; // if tag < 30 then its a single octet identifier.
284                         if (tag == 0x1F)
285                         // if true, its a multiple octet identifier.
286                                 tag = decodeTagNumber(in_Renamed);
287                 }
288                 
289                 /// <summary> In the case that we have a tag number that is greater than 30, we need
290                 /// to decode a multiple octet tag number.
291                 /// </summary>
292                 private int decodeTagNumber(System.IO.Stream in_Renamed)
293                 {
294                         int n = 0;
295                         while (true)
296                         {
297                                 int r = in_Renamed.ReadByte();
298                                 encodedLength++;
299                                 if (r < 0)
300                                         throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in tag number");
301                                 n = (n << 7) + (r & 0x7F);
302                                 if ((r & 0x80) == 0)
303                                         break;
304                         }
305                         return n;
306                 }
307                 
308                 /* Convenience methods
309                 */
310                 
311                 /// <summary> Creates a duplicate, not a true clone, of this object and returns
312                 /// a reference to the duplicate.
313                 /// 
314                 /// </summary>
315                 public System.Object Clone()
316                 {
317                         try
318                         {
319                                 return base.MemberwiseClone();
320                         }
321                         catch (System.Exception ce)
322                         {
323                                 throw new System.SystemException("Internal error, cannot create clone");
324                         }
325                 }
326         }
327 }