**** Merged from MCS ****
[mono-project.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Asn1 / LBEREncoder.cs
blobc7e50c0acf9ec21c9571c8c8ac8fa20ba88b4c27
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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 *******************************************************************************/
24 // Novell.Directory.Ldap.Asn1.LBEREncoder.cs
26 // Author:
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
32 using System;
34 namespace Novell.Directory.Ldap.Asn1
37 /// <summary> This class provides LBER encoding routines for ASN.1 Types. LBER is a
38 /// subset of BER as described in the following taken from 5.1 of RFC 2251:
39 ///
40 /// 5.1. Mapping Onto BER-based Transport Services
41 ///
42 /// The protocol elements of Ldap are encoded for exchange using the
43 /// Basic Encoding Rules (BER) [11] of ASN.1 [3]. However, due to the
44 /// high overhead involved in using certain elements of the BER, the
45 /// following additional restrictions are placed on BER-encodings of Ldap
46 /// protocol elements:
47 ///
48 /// <li>(1) Only the definite form of length encoding will be used.</li>
49 ///
50 /// <li>(2) OCTET STRING values will be encoded in the primitive form only.</li>
51 ///
52 /// <li>(3) If the value of a BOOLEAN type is true, the encoding MUST have
53 /// its contents octets set to hex "FF".</li>
54 ///
55 /// <li>(4) If a value of a type is its default value, it MUST be absent.
56 /// Only some BOOLEAN and INTEGER types have default values in this
57 /// protocol definition.
58 ///
59 /// These restrictions do not apply to ASN.1 types encapsulated inside of
60 /// OCTET STRING values, such as attribute values, unless otherwise
61 /// noted.</li>
62 ///
63 /// [3] ITU-T Rec. X.680, "Abstract Syntax Notation One (ASN.1) -
64 /// Specification of Basic Notation", 1994.
65 ///
66 /// [11] ITU-T Rec. X.690, "Specification of ASN.1 encoding rules: Basic,
67 /// Canonical, and Distinguished Encoding Rules", 1994.
68 ///
69 /// </summary>
70 [CLSCompliantAttribute(true)]
71 public class LBEREncoder : Asn1Encoder
74 /* Encoders for ASN.1 simple type Contents
76 public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
79 /// <summary> BER Encode an Asn1Boolean directly into the specified output stream.</summary>
80 public virtual void encode(Asn1Boolean b, System.IO.Stream out_Renamed)
82 /* Encode the id */
83 encode(b.getIdentifier(), out_Renamed);
85 /* Encode the length */
86 out_Renamed.WriteByte((System.Byte) 0x01);
88 /* Encode the boolean content*/
89 out_Renamed.WriteByte((byte) (b.booleanValue()?(sbyte) SupportClass.Identity(0xff):(sbyte) 0x00));
91 return ;
94 /// <summary> Encode an Asn1Numeric directly into the specified outputstream.
95 ///
96 /// Use a two's complement representation in the fewest number of octets
97 /// possible.
98 ///
99 /// Can be used to encode INTEGER and ENUMERATED values.
100 /// </summary>
101 public void encode(Asn1Numeric n, System.IO.Stream out_Renamed)
103 sbyte[] octets = new sbyte[8];
104 sbyte len;
105 long value_Renamed = n.longValue();
106 long endValue = (value_Renamed < 0)?- 1:0;
107 long endSign = endValue & 0x80;
109 for (len = 0; len == 0 || value_Renamed != endValue || (octets[len - 1] & 0x80) != endSign; len++)
111 octets[len] = (sbyte) (value_Renamed & 0xFF);
112 value_Renamed >>= 8;
115 encode(n.getIdentifier(), out_Renamed);
116 out_Renamed.WriteByte((byte) len); // Length
117 for (int i = len - 1; i >= 0; i--)
118 // Content
119 out_Renamed.WriteByte((byte) octets[i]);
120 return ;
123 /* Asn1 TYPE NOT YET SUPPORTED
124 * Encode an Asn1Real directly to a stream.
125 public void encode(Asn1Real r, OutputStream out)
126 throws IOException
128 throw new IOException("LBEREncoder: Encode to a stream not implemented");
132 /// <summary> Encode an Asn1Null directly into the specified outputstream.</summary>
133 public void encode(Asn1Null n, System.IO.Stream out_Renamed)
135 encode(n.getIdentifier(), out_Renamed);
136 out_Renamed.WriteByte((System.Byte) 0x00); // Length (with no Content)
137 return ;
140 /* Asn1 TYPE NOT YET SUPPORTED
141 * Encode an Asn1BitString directly to a stream.
142 public void encode(Asn1BitString bs, OutputStream out)
143 throws IOException
145 throw new IOException("LBEREncoder: Encode to a stream not implemented");
149 /// <summary> Encode an Asn1OctetString directly into the specified outputstream.</summary>
150 public void encode(Asn1OctetString os, System.IO.Stream out_Renamed)
152 encode(os.getIdentifier(), out_Renamed);
153 encodeLength(os.byteValue().Length, out_Renamed);
154 sbyte[] temp_sbyteArray;
155 temp_sbyteArray = os.byteValue();
156 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;
157 return ;
160 /* Asn1 TYPE NOT YET SUPPORTED
161 * Encode an Asn1ObjectIdentifier directly to a stream.
162 * public void encode(Asn1ObjectIdentifier oi, OutputStream out)
163 * throws IOException
165 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
169 /* Asn1 TYPE NOT YET SUPPORTED
170 * Encode an Asn1CharacterString directly to a stream.
171 * public void encode(Asn1CharacterString cs, OutputStream out)
172 * throws IOException
174 * throw new IOException("LBEREncoder: Encode to a stream not implemented");
178 /* Encoders for ASN.1 structured types
181 /// <summary> Encode an Asn1Structured into the specified outputstream. This method
182 /// can be used to encode SET, SET_OF, SEQUENCE, SEQUENCE_OF
183 /// </summary>
184 public void encode(Asn1Structured c, System.IO.Stream out_Renamed)
186 encode(c.getIdentifier(), out_Renamed);
188 Asn1Object[] value_Renamed = c.toArray();
190 System.IO.MemoryStream output = new System.IO.MemoryStream();
192 /* Cycle through each element encoding each element */
193 for (int i = 0; i < value_Renamed.Length; i++)
195 (value_Renamed[i]).encode(this, output);
198 /* Encode the length */
199 encodeLength((int)output.Length, out_Renamed);
201 /* Add each encoded element into the output stream */
202 sbyte[] temp_sbyteArray;
203 temp_sbyteArray = SupportClass.ToSByteArray(output.ToArray());
204 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;
205 return ;
208 /// <summary> Encode an Asn1Tagged directly into the specified outputstream.</summary>
209 public void encode(Asn1Tagged t, System.IO.Stream out_Renamed)
211 if (t.Explicit)
213 encode(t.getIdentifier(), out_Renamed);
215 /* determine the encoded length of the base type. */
216 System.IO.MemoryStream encodedContent = new System.IO.MemoryStream();
217 t.taggedValue().encode(this, encodedContent);
219 encodeLength((int)encodedContent.Length, out_Renamed);
220 sbyte[] temp_sbyteArray;
221 temp_sbyteArray = SupportClass.ToSByteArray(encodedContent.ToArray());
222 out_Renamed.Write(SupportClass.ToByteArray(temp_sbyteArray), 0, temp_sbyteArray.Length);;;;
224 else
226 t.taggedValue().encode(this, out_Renamed);
228 return ;
231 /* Encoders for ASN.1 useful types
233 /* Encoder for ASN.1 Identifier
236 /// <summary> Encode an Asn1Identifier directly into the specified outputstream.</summary>
237 public void encode(Asn1Identifier id, System.IO.Stream out_Renamed)
239 int c = id.Asn1Class;
240 int t = id.Tag;
241 sbyte ccf = (sbyte) ((c << 6) | (id.Constructed?0x20:0));
243 if (t < 30)
245 /* single octet */
246 out_Renamed.WriteByte((System.Byte) (ccf | t));
248 else
250 /* multiple octet */
251 out_Renamed.WriteByte((System.Byte) (ccf | 0x1F));
252 encodeTagInteger(t, out_Renamed);
254 return ;
257 /* Private helper methods
261 * Encodes the specified length into the the outputstream
263 private void encodeLength(int length, System.IO.Stream out_Renamed)
265 if (length < 0x80)
267 out_Renamed.WriteByte((System.Byte) length);
269 else
271 sbyte[] octets = new sbyte[4]; // 4 bytes sufficient for 32 bit int.
272 sbyte n;
273 for (n = 0; length != 0; n++)
275 octets[n] = (sbyte) (length & 0xFF);
276 length >>= 8;
279 out_Renamed.WriteByte((System.Byte) (0x80 | n));
281 for (int i = n - 1; i >= 0; i--)
282 out_Renamed.WriteByte((byte) octets[i]);
284 return ;
287 /// <summary> Encodes the provided tag into the outputstream.</summary>
288 private void encodeTagInteger(int value_Renamed, System.IO.Stream out_Renamed)
290 sbyte[] octets = new sbyte[5];
291 int n;
292 for (n = 0; value_Renamed != 0; n++)
294 octets[n] = (sbyte) (value_Renamed & 0x7F);
295 value_Renamed = value_Renamed >> 7;
297 for (int i = n - 1; i > 0; i--)
299 out_Renamed.WriteByte((System.Byte) (octets[i] | 0x80));
301 out_Renamed.WriteByte((byte) octets[0]);
302 return ;