New test.
[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         public class Asn1Identifier:System.Object, System.ICloneable
76         {
77                 /// <summary> Returns the CLASS of this Asn1Identifier as an int value.
78                 /// 
79                 /// </summary>
80                 /// <seealso cref="UNIVERSAL">
81                 /// </seealso>
82                 /// <seealso cref="APPLICATION">
83                 /// </seealso>
84                 /// <seealso cref="CONTEXT">
85                 /// </seealso>
86                 /// <seealso cref="PRIVATE">
87                 /// </seealso>
88                 virtual public int Asn1Class
89                 {
90                         get
91                         {
92                                 return tagClass;
93                         }
94                         
95                 }
96                 /// <summary> Return a boolean indicating if the constructed bit is set.
97                 /// 
98                 /// </summary>
99                 /// <returns> true if constructed and false if primitive.
100                 /// </returns>
101                 virtual public bool Constructed
102                 {
103                         get
104                         {
105                                 return constructed;
106                         }
107                         
108                 }
109                 /// <summary> Returns the TAG of this Asn1Identifier.</summary>
110                 virtual public int Tag
111                 {
112                         get
113                         {
114                                 return tag;
115                         }
116                         
117                 }
118                 /// <summary> Returns the encoded length of this Asn1Identifier.</summary>
119                 virtual public int EncodedLength
120                 {
121                         get
122                         {
123                                 return encodedLength;
124                         }
125                         
126                 }
127                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
128                 /// has a TAG CLASS of UNIVERSAL.
129                 /// 
130                 /// </summary>
131                 /// <seealso cref="UNIVERSAL">
132                 /// </seealso>
133                 [CLSCompliantAttribute(false)]
134                 virtual public bool Universal
135                 {
136                         get
137                         {
138                                 return tagClass == UNIVERSAL;
139                         }
140                         
141                 }
142                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
143                 /// has a TAG CLASS of APPLICATION.
144                 /// 
145                 /// </summary>
146                 /// <seealso cref="APPLICATION">
147                 /// </seealso>
148                 [CLSCompliantAttribute(false)]
149                 virtual public bool Application
150                 {
151                         get
152                         {
153                                 return tagClass == APPLICATION;
154                         }
155                         
156                 }
157                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
158                 /// has a TAG CLASS of CONTEXT-SPECIFIC.
159                 /// 
160                 /// </summary>
161                 /// <seealso cref="CONTEXT">
162                 /// </seealso>
163                 [CLSCompliantAttribute(false)]
164                 virtual public bool Context
165                 {
166                         get
167                         {
168                                 return tagClass == CONTEXT;
169                         }
170                         
171                 }
172                 /// <summary> Returns a boolean value indicating whether or not this Asn1Identifier
173                 /// has a TAG CLASS of PRIVATE.
174                 /// 
175                 /// </summary>
176                 /// <seealso cref="PRIVATE"></seealso>
177                 [CLSCompliantAttribute(false)]
178                 virtual public bool Private
179                 {
180                         get
181                         {
182                                 return tagClass == PRIVATE;
183                         }
184                         
185                 }
186                 
187                 /// <summary> Universal tag class.
188                 /// 
189                 ///  UNIVERSAL = 0 
190                 /// </summary>
191                 public const int UNIVERSAL = 0;
192                 
193                 /// <summary> Application-wide tag class.
194                 /// 
195                 ///  APPLICATION = 1 
196                 /// </summary>
197                 public const int APPLICATION = 1;
198                 
199                 /// <summary> Context-specific tag class.
200                 /// 
201                 ///  CONTEXT = 2 
202                 /// </summary>
203                 public const int CONTEXT = 2;
204                 
205                 /// <summary> Private-use tag class.
206                 /// 
207                 ///  PRIVATE = 3 
208                 /// </summary>
209                 public const int PRIVATE = 3;
210                 
211                 
212                 /* Private variables
213                 */
214                 
215                 private int tagClass;
216                 private bool constructed;
217                 private int tag;
218                 private int encodedLength;
219                 
220                 /* Constructors for Asn1Identifier
221                 */
222                 
223                 /// <summary> Constructs an Asn1Identifier using the classtype, form and tag.
224                 /// 
225                 /// </summary>
226                 /// <param name="tagClass">As defined above.
227                 /// 
228                 /// </param>
229                 /// <param name="constructed">Set to true if constructed and false if primitive.
230                 /// 
231                 /// </param>
232                 /// <param name="tag">The tag of this identifier
233                 /// </param>
234                 public Asn1Identifier(int tagClass, bool constructed, int tag)
235                 {
236                         this.tagClass = tagClass;
237                         this.constructed = constructed;
238                         this.tag = tag;
239                 }
240                 
241                 /// <summary> Decode an Asn1Identifier directly from an InputStream and
242                 /// save the encoded length of the Asn1Identifier.
243                 /// 
244                 /// </summary>
245                 /// <param name="in">The input stream to decode from.
246                 /// </param>
247                 public Asn1Identifier(System.IO.Stream in_Renamed)
248                 {
249                         int r = in_Renamed.ReadByte();
250                         encodedLength++;
251                         if (r < 0)
252                                 throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in Identifier");
253                         tagClass = r >> 6;
254                         constructed = (r & 0x20) != 0;
255                         tag = r & 0x1F; // if tag < 30 then its a single octet identifier.
256                         if (tag == 0x1F)
257                         // if true, its a multiple octet identifier.
258                                 tag = decodeTagNumber(in_Renamed);
259                         return ;
260                 }
261                 
262                 public Asn1Identifier()
263                 {
264                         return ;
265                 }
266                 
267                 /// <summary> Decode an Asn1Identifier directly from an InputStream and
268                 /// save the encoded length of the Asn1Identifier, but reuse the object.
269                 /// 
270                 /// </summary>
271                 /// <param name="in">The input stream to decode from.
272                 /// </param>
273                 public void  reset(System.IO.Stream in_Renamed)
274                 {
275                         encodedLength = 0;
276                         int r = in_Renamed.ReadByte();
277                         encodedLength++;
278                         if (r < 0)
279                                 throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in Identifier");
280                         tagClass = r >> 6;
281                         constructed = (r & 0x20) != 0;
282                         tag = r & 0x1F; // if tag < 30 then its a single octet identifier.
283                         if (tag == 0x1F)
284                         // if true, its a multiple octet identifier.
285                                 tag = decodeTagNumber(in_Renamed);
286                 }
287                 
288                 /// <summary> In the case that we have a tag number that is greater than 30, we need
289                 /// to decode a multiple octet tag number.
290                 /// </summary>
291                 private int decodeTagNumber(System.IO.Stream in_Renamed)
292                 {
293                         int n = 0;
294                         while (true)
295                         {
296                                 int r = in_Renamed.ReadByte();
297                                 encodedLength++;
298                                 if (r < 0)
299                                         throw new System.IO.EndOfStreamException("BERDecoder: decode: EOF in tag number");
300                                 n = (n << 7) + (r & 0x7F);
301                                 if ((r & 0x80) == 0)
302                                         break;
303                         }
304                         return n;
305                 }
306                 
307                 /* Convenience methods
308                 */
309                 
310                 /// <summary> Creates a duplicate, not a true clone, of this object and returns
311                 /// a reference to the duplicate.
312                 /// 
313                 /// </summary>
314                 public System.Object Clone()
315                 {
316                         try
317                         {
318                                 return base.MemberwiseClone();
319                         }
320                         catch (System.Exception ce)
321                         {
322                                 throw new System.SystemException("Internal error, cannot create clone");
323                         }
324                 }
325         }
326 }