Class files Implementing various utility classes used by LDAP C# Libraray
authorSunil Kumar <sunilk@mono-cvs.ximian.com>
Mon, 24 Nov 2003 03:59:43 +0000 (03:59 -0000)
committerSunil Kumar <sunilk@mono-cvs.ximian.com>
Mon, 24 Nov 2003 03:59:43 +0000 (03:59 -0000)
svn path=/trunk/mcs/; revision=20367

13 files changed:
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ArrayEnumeration.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/AttributeQualifier.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/Base64.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/BindProperties.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/DN.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/EnumeratedIterator.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExceptionMessages.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExtResponseFactory.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RDN.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ReferralInfo.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResourcesHandler.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RespControlVector.cs [new file with mode: 0755]
mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResultCodeMessages.cs [new file with mode: 0755]

diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ArrayEnumeration.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ArrayEnumeration.cs
new file mode 100755 (executable)
index 0000000..95fee05
--- /dev/null
@@ -0,0 +1,89 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ArrayEnumeration.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       public class ArrayEnumeration : System.Collections.IEnumerator
+       {
+               private System.Object tempAuxObj;
+               public virtual bool MoveNext()
+               {
+                       bool result = hasMoreElements();
+                       if (result)
+                       {
+                               tempAuxObj = nextElement();
+                       }
+                       return result;
+               }
+               public virtual void  Reset()
+               {
+                       tempAuxObj = null;
+               }
+               public virtual System.Object Current
+               {
+                       get
+                       {
+                               return tempAuxObj;
+                       }
+                       
+               }
+               private System.Object[] eArray;
+               private int index = 0;
+               /// <summary> Constructor to create the Enumeration
+               /// 
+               /// </summary>
+               /// <param name="eArray">the array to use for the Enumeration
+               /// </param>
+               public ArrayEnumeration(System.Object[] eArray)
+               {
+                       this.eArray = eArray;
+               }
+               
+               public bool hasMoreElements()
+               {
+                       if (eArray == null)
+                               return false;
+                       return (index < eArray.Length);
+               }
+               
+               public System.Object nextElement()
+               {
+                       if ((eArray == null) || (index >= eArray.Length))
+                       {
+                               throw new System.ArgumentOutOfRangeException();
+                       }
+                       return eArray[index++];
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/AttributeQualifier.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/AttributeQualifier.cs
new file mode 100755 (executable)
index 0000000..d111009
--- /dev/null
@@ -0,0 +1,93 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.AttributeQualifier.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> Encapsulates a qualifier in a Schema definition.  Definitions that are not
+       /// in rfc2252.  Begins with 'X-'
+       /// </summary>
+       public class AttributeQualifier
+       {
+               virtual public System.String Name
+               {
+                       /*
+                       public void addValue( String value )
+                       {
+                       values.add( value );
+                       return;
+                       }
+                       */
+                       
+                       get
+                       {
+                               return name;
+                       }
+                       
+               }
+               virtual public System.String[] Values
+               {
+                       get
+                       {
+                               System.String[] strValues = null;
+                               if (values.Count > 0)
+                               {
+                                       strValues = new System.String[values.Count];
+                                       for (int i = 0; i < values.Count; i++)
+                                       {
+                                               strValues[i] = ((System.String) values[i]);
+                                       }
+                               }
+                               return strValues;
+                       }
+                       
+               }
+               internal System.String name;
+               internal System.Collections.ArrayList values;
+               
+               public AttributeQualifier(System.String name, System.String[] value_Renamed)
+               {
+                       if ((System.Object) name == null || value_Renamed == null)
+                       {
+                               throw new System.ArgumentException("A null name or value " + "was passed in for a schema definition qualifier");
+                       }
+                       this.name = name;
+                       values = new System.Collections.ArrayList(5);
+                       for (int i = 0; i < value_Renamed.Length; i++)
+                       {
+                               values.Add(value_Renamed[i]);
+                       }
+                       return ;
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/Base64.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/Base64.cs
new file mode 100755 (executable)
index 0000000..0d648fb
--- /dev/null
@@ -0,0 +1,722 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.Base64.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> The Base64 utility class performs base64 encoding and decoding.
+       /// 
+       /// The Base64 Content-Transfer-Encoding is designed to represent
+       /// arbitrary sequences of octets in a form that need not be humanly
+       /// readable.  The encoding and decoding algorithms are simple, but the
+       /// encoded data are consistently only about 33 percent larger than the
+       /// unencoded data.  The base64 encoding algorithm is defined by
+       /// RFC 2045.
+       /// </summary>
+       public class Base64
+       {
+               /// <summary>Conversion table for encoding to base64.
+               /// 
+               /// emap is a six-bit value to base64 (8-bit) converstion table.
+               /// For example, the value of the 6-bit value 15
+               /// is mapped to 0x50 which is the ASCII letter 'P', i.e. the letter P
+               /// is the base64 encoded character that represents the 6-bit value 15.
+               /// </summary>
+               /*
+               * 8-bit base64 encoded character                 base64       6-bit
+               *                                                encoded      original
+               *                                                character    binary value
+               */
+               private static readonly char[] emap = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'}; // 4-9, + /;  56-63
+               
+               /// <summary>conversion table for decoding from base64.
+               /// 
+               /// dmap is a base64 (8-bit) to six-bit value converstion table.
+               /// For example the ASCII character 'P' has a value of 80.
+               /// The value in the 80th position of the table is 0x0f or 15.
+               /// 15 is the original 6-bit value that the letter 'P' represents.
+               /// </summary>
+               /*
+               * 6-bit decoded value                            base64    base64
+               *                                                encoded   character
+               *                                                value
+               *
+               * Note: about half of the values in the table are only place holders
+               */
+               private static readonly sbyte[] dmap = new sbyte[]{(sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x3e), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x3f), (sbyte) (0x34), (sbyte) (0x35), (sbyte) (0x36), (sbyte) (0x37), (sbyte) (0x38), (sbyte) (0x39), (sbyte) (0x3a), (sbyte) (0x3b), (sbyte) (0x3c), (sbyte) (0x3d), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x01), (sbyte) (0x02), (sbyte) (0x03), (sbyte) (0x04), (sbyte) (0x05), (sbyte) (0x06), (sbyte) (0x07), (sbyte) (0x08), (sbyte) (0x09), (sbyte) (0x0a), (sbyte) (0x0b), (sbyte) (0x0c), (sbyte) (0x0d), (sbyte) (0x0e), (sbyte) (0x0f), (sbyte) (0x10), (sbyte) (0x11), (sbyte) (0x12), (sbyte) (0x13), (sbyte) (0x14), (sbyte) (0x15), (sbyte) (0x16), (sbyte) (0x17), (sbyte) (0x18), (sbyte) (0x19), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x1a), (sbyte) (0x1b), (sbyte) (0x1c), (sbyte) (0x1d), (sbyte) (0x1e), (sbyte) (0x1f), (sbyte) (0x20), (sbyte) (0x21), (sbyte) (0x22), (sbyte) (0x23), (sbyte) (0x24), (sbyte) (0x25), (sbyte) (0x26), (sbyte) (0x27), (sbyte) (0x28), (sbyte) (0x29), (sbyte) (0x2a), (sbyte) (0x2b), (sbyte) (0x2c), (sbyte) (0x2d), (sbyte) (0x2e), (sbyte) (0x2f), (sbyte) (0x30), (sbyte) (0x31), (sbyte) (0x32), (sbyte) (0x33), (sbyte) (0x00), (
+                       sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00), (sbyte) (0x00)}; // 120-127 'xyz     '
+               
+               /// <summary> Default constructor, don't allow instances of the
+               /// utility class to be created.
+               /// </summary>
+               private Base64()
+               {
+                       return ;
+               }
+               
+               
+               /// <summary> Encodes the specified String into a base64 encoded String object.
+               /// 
+               /// </summary>
+               /// <param name="inputString"> The String object to be encoded.
+               /// 
+               /// </param>
+               /// <returns> a String containing the encoded value of the input.
+               /// </returns>
+               public static System.String encode(System.String inputString)
+               {
+                       try
+                       {
+                               System.Text.Encoding encoder = System.Text.Encoding.GetEncoding("utf-8"); 
+                               byte[] ibytes = encoder.GetBytes(inputString);
+                               sbyte[] sbytes=SupportClass.ToSByteArray(ibytes);
+                               return encode(sbytes);
+                       }
+                       catch (System.IO.IOException ue)
+                       {
+                               throw new System.SystemException("US-ASCII String encoding not supported by JVM");
+                       }
+               }
+               
+               /// <summary> Encodes the specified bytes into a base64 array of bytes.
+               /// Each byte in the return array represents a base64 character.
+               /// 
+               /// </summary>
+               /// <param name="inputBytes"> the byte array to be encoded.
+               /// 
+               /// </param>
+               /// <returns>            a String containing the base64 encoded data
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static System.String encode(sbyte[] inputBytes)
+               {
+                       int i, j, k;
+                       int t, t1, t2;
+                       int ntb; // number of three-bytes in inputBytes
+                       bool onePadding = false, twoPaddings = false;
+                       char[] encodedChars; // base64 encoded chars
+                       int len = inputBytes.Length;
+                       
+                       if (len == 0)
+                       {
+                               // No data, return no data.
+                               return new System.Text.StringBuilder("").ToString();
+                       }
+                       
+                       // every three bytes will be encoded into four bytes
+                       if (len % 3 == 0)
+                       {
+                               ntb = len / 3;
+                       }
+                       // the last one or two bytes will be encoded into
+                       // four bytes with one or two paddings
+                       else
+                       {
+                               ntb = len / 3 + 1;
+                       }
+                       
+                       // need two paddings
+                       if ((len % 3) == 1)
+                       {
+                               twoPaddings = true;
+                       }
+                       // need one padding
+                       else if ((len % 3) == 2)
+                       {
+                               onePadding = true;
+                       }
+                       
+                       encodedChars = new char[ntb * 4];
+                       
+                       // map of decoded and encoded bits
+                       //     bits in 3 decoded bytes:   765432  107654  321076  543210
+                       //     bits in 4 encoded bytes: 76543210765432107654321076543210
+                       //       plain           "AAA":   010000  010100  000101  000001
+                       //       base64 encoded "QUFB": 00010000000101000000010100000001
+                       // one padding:
+                       //     bits in 2 decoded bytes:   765432  10 7654  3210
+                       //     bits in 4 encoded bytes: 765432107654 321076543210 '='
+                       //       plain            "AA":   010000  010100  0001
+                       //       base64 encoded "QUE=": 00010000000101000000010000111101
+                       // two paddings:
+                       //     bits in 1 decoded bytes:   765432  10
+                       //     bits in 4 encoded bytes: 7654321076543210 '=' '='
+                       //       plain             "A":   010000  01
+                       //       base64 encoded "QQ==": 00010000000100000011110100111101
+                       //
+                       // note: the encoded bits which have no corresponding decoded bits
+                       // are filled with zeros; '=' = 00111101.
+                       for (i = 0, j = 0, k = 1; i < len; i += 3, j += 4, k++)
+                       {
+                               
+                               // build encodedChars[j]
+                               t = 0x00ff & inputBytes[i];
+                               encodedChars[j] = emap[t >> 2];
+                               
+                               // build encodedChars[j+1]
+                               if ((k == ntb) && twoPaddings)
+                               {
+                                       encodedChars[j + 1] = emap[(t & 0x03) << 4];
+                                       encodedChars[j + 2] = '=';
+                                       encodedChars[j + 3] = '=';
+                                       break;
+                               }
+                               else
+                               {
+                                       t1 = 0x00ff & inputBytes[i + 1];
+                                       encodedChars[j + 1] = emap[((t & 0x03) << 4) + ((t1 & 0xf0) >> 4)];
+                               }
+                               
+                               // build encodedChars[j+2]
+                               if ((k == ntb) && onePadding)
+                               {
+                                       encodedChars[j + 2] = emap[(t1 & 0x0f) << 2];
+                                       encodedChars[j + 3] = '=';
+                                       break;
+                               }
+                               else
+                               {
+                                       t2 = 0x00ff & inputBytes[i + 2];
+                                       encodedChars[j + 2] = (emap[(t1 & 0x0f) << 2 | (t2 & 0xc0) >> 6]);
+                               }
+                               
+                               // build encodedChars[j+3]
+                               encodedChars[j + 3] = (emap[(t2 & 0x3f)]);
+                       }
+                       return new System.String(encodedChars);
+               }
+               
+               
+               /// <summary> Decodes the input base64 encoded String.
+               /// The resulting binary data is returned as an array of bytes.
+               /// 
+               /// </summary>
+               /// <param name="encodedString">The base64 encoded String object.
+               /// 
+               /// </param>
+               /// <returns> The decoded byte array.
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static sbyte[] decode(System.String encodedString)
+               {
+                       char[] c = new char[encodedString.Length];
+                       SupportClass.GetCharsFromString(encodedString, 0, encodedString.Length, ref c, 0);
+                       return decode(c);
+               }
+               
+               /// <summary> Decodes the input base64 encoded array of characters.
+               /// The resulting binary data is returned as an array of bytes.
+               /// 
+               /// </summary>
+               /// <param name="encodedChars">The character array containing the base64 encoded data.
+               /// 
+               /// </param>
+               /// <returns> A byte array object containing decoded bytes.
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static sbyte[] decode(char[] encodedChars)
+               {
+                       int i, j, k;
+                       int ecLen = encodedChars.Length; // length of encodedChars
+                       int gn = ecLen / 4; // number of four-byte groups in encodedChars
+                       int dByteLen; // length of decoded bytes, default is '0'
+                       bool onePad = false, twoPads = false;
+                       sbyte[] decodedBytes; // decoded bytes
+                       
+                       if (encodedChars.Length == 0)
+                       {
+                               return new sbyte[0];
+                       }
+                       // the number of encoded bytes should be multiple of 4
+                       if ((ecLen % 4) != 0)
+                       {
+                               throw new System.SystemException("com.novell.ldap.ldif_dsml." + "Base64Decoder: decode: mal-formatted encode value");
+                       }
+                       
+                       // every four-bytes in encodedString, except the last one if it in the
+                       // form of '**==' or '***=' ( can't be '*===' or '===='), will be
+                       // decoded into three bytes.
+                       if ((encodedChars[ecLen - 1] == (int) '=') && (encodedChars[ecLen - 2] == (int) '='))
+                       {
+                               // the last four bytes of encodedChars is in the form of '**=='
+                               twoPads = true;
+                               // the first two bytes of the last four-bytes of encodedChars will
+                               // be decoded into one byte.
+                               dByteLen = gn * 3 - 2;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       else if (encodedChars[ecLen - 1] == '=')
+                       {
+                               // the last four bytes of encodedChars is in the form of '***='
+                               onePad = true;
+                               // the first two bytes of the last four-bytes of encodedChars will
+                               // be decoded into two bytes.
+                               dByteLen = gn * 3 - 1;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       else
+                       {
+                               // the last four bytes of encodedChars is in the form of '****',
+                               // e.g. no pad.
+                               dByteLen = gn * 3;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       
+                       // map of encoded and decoded bits
+                       // no padding:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 3 decoded bytes:   765432   107654   321076   543210
+                       //        base64  string "QUFB":00010000 00010100 000001010 0000001
+                       //          plain string  "AAA":   010000  010100  000101  000001
+                       // one padding:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 2 decoded bytes:   765432   107654   3210
+                       //       base64  string "QUE=": 00010000 000101000 0000100 00111101
+                       //         plain string   "AA":   010000  010100  0001
+                       // two paddings:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 1 decoded bytes:   765432   10
+                       //       base64  string "QQ==": 00010000 00010000 00111101 00111101
+                       //         plain string    "A":   010000  01
+                       for (i = 0, j = 0, k = 1; i < ecLen; i += 4, j += 3, k++)
+                       {
+                               // build decodedBytes[j].
+                               decodedBytes[j] = (sbyte) (dmap[encodedChars[i]] << 2 | (dmap[encodedChars[i + 1]] & 0x30) >> 4);
+                               
+                               // build decodedBytes[j+1]
+                               if ((k == gn) && twoPads)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       decodedBytes[j + 1] = (sbyte) ((dmap[encodedChars[i + 1]] & 0x0f) << 4 | (dmap[encodedChars[i + 2]] & 0x3c) >> 2);
+                               }
+                               
+                               // build decodedBytes[j+2]
+                               if ((k == gn) && onePad)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       decodedBytes[j + 2] = (sbyte) ((dmap[encodedChars[i + 2]] & 0x03) << 6 | dmap[encodedChars[i + 3]] & 0x3f);
+                               }
+                       }
+                       return decodedBytes;
+               }
+               
+               /// <summary> Decodes a base64 encoded StringBuffer.
+               /// Decodes all or part of the input base64 encoded StringBuffer, each
+               /// Character value representing a base64 character. The resulting
+               /// binary data is returned as an array of bytes.
+               /// 
+               /// </summary>
+               /// <param name="encodedSBuf">The StringBuffer object that contains base64
+               /// encoded data.
+               /// </param>
+               /// <param name="start"> The start index of the base64 encoded data.
+               /// </param>
+               /// <param name="end"> The end index + 1 of the base64 encoded data.
+               /// 
+               /// </param>
+               /// <returns> The decoded byte array
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static sbyte[] decode(System.Text.StringBuilder encodedSBuf, int start, int end)
+               {
+                       int i, j, k;
+                       int esbLen = end - start; // length of the encoded part
+                       int gn = esbLen / 4; // number of four-bytes group in ebs
+                       int dByteLen; // length of dbs, default is '0'
+                       bool onePad = false, twoPads = false;
+                       sbyte[] decodedBytes; // decoded bytes
+                       
+                       if (encodedSBuf.Length == 0)
+                       {
+                               return new sbyte[0];
+                       }
+                       // the number of encoded bytes should be multiple of number 4
+                       if ((esbLen % 4) != 0)
+                       {
+                               throw new System.SystemException("com.novell.ldap.ldif_dsml." + "Base64Decoder: decode error: mal-formatted encode value");
+                       }
+                       
+                       // every four-bytes in ebs, except the last one if it in the form of
+                       // '**==' or '***=' ( can't be '*===' or '===='), will be decoded into
+                       // three bytes.
+                       if ((encodedSBuf[end - 1] == (int) '=') && (encodedSBuf[end - 2] == (int) '='))
+                       {
+                               // the last four bytes of ebs is in the form of '**=='
+                               twoPads = true;
+                               // the first two bytes of the last four-bytes of ebs will be
+                               // decoded into one byte.
+                               dByteLen = gn * 3 - 2;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       else if (encodedSBuf[end - 1] == (int) '=')
+                       {
+                               // the last four bytes of ebs is in the form of '***='
+                               onePad = true;
+                               // the first two bytes of the last four-bytes of ebs will be
+                               // decoded into two bytes.
+                               dByteLen = gn * 3 - 1;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       else
+                       {
+                               // the last four bytes of ebs is in the form of '****', eg. no pad.
+                               dByteLen = gn * 3;
+                               decodedBytes = new sbyte[dByteLen];
+                       }
+                       
+                       // map of encoded and decoded bits
+                       // no padding:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 3 decoded bytes:   765432   107654   321076   543210
+                       //        base64  string "QUFB":00010000 00010100 000001010 0000001
+                       //          plain string  "AAA":   010000  010100  000101  000001
+                       // one padding:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 2 decoded bytes:   765432   107654   3210
+                       //       base64  string "QUE=": 00010000 000101000 0000100 00111101
+                       //         plain string   "AA":   010000  010100  0001
+                       // two paddings:
+                       //     bits in 4 encoded bytes: 76543210 76543210 76543210 76543210
+                       //     bits in 1 decoded bytes:   765432   10
+                       //       base64  string "QQ==": 00010000 00010000 00111101 00111101
+                       //         plain string    "A":   010000  01
+                       for (i = 0, j = 0, k = 1; i < esbLen; i += 4, j += 3, k++)
+                       {
+                               // build decodedBytes[j].
+                               decodedBytes[j] = (sbyte) (dmap[encodedSBuf[start + i]] << 2 | (dmap[encodedSBuf[start + i + 1]] & 0x30) >> 4);
+                               
+                               // build decodedBytes[j+1]
+                               if ((k == gn) && twoPads)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       decodedBytes[j + 1] = (sbyte) ((dmap[encodedSBuf[start + i + 1]] & 0x0f) << 4 | (dmap[encodedSBuf[start + i + 2]] & 0x3c) >> 2);
+                               }
+                               
+                               // build decodedBytes[j+2]
+                               if ((k == gn) && onePad)
+                               {
+                                       break;
+                               }
+                               else
+                               {
+                                       decodedBytes[j + 2] = (sbyte) ((dmap[encodedSBuf[start + i + 2]] & 0x03) << 6 | dmap[encodedSBuf[start + i + 3]] & 0x3f);
+                               }
+                       }
+                       return decodedBytes;
+               }
+               
+               /// <summary> Checks if the input byte array contains only safe values, that is,
+               /// the data does not need to be encoded for use with LDIF.
+               /// The rules for checking safety are based on the rules for LDIF
+               /// (Ldap Data Interchange Format) per RFC 2849.  The data does
+               /// not need to be encoded if all the following are true:
+               /// <br>
+               /// <p>The data cannot start with the following byte values:</p>
+               /// <pre>
+               /// 00 (NUL)
+               /// 10 (LF)
+               /// 13 (CR)
+               /// 32 (SPACE)
+               /// 58 (:)
+               /// 60 (<)
+               /// Any character with value greater than 127
+               /// (Negative for a byte value)
+               /// </pre>
+               /// <p>The data cannot contain any of the following byte values:</p>
+               /// <pre>
+               /// 00 (NUL)
+               /// 10 (LF)
+               /// 13 (CR)
+               /// Any character with value greater than 127
+               /// (Negative for a byte value)
+               /// </pre>
+               /// <p>The data cannot end with a space.</p>
+               /// 
+               /// </summary>
+               /// <param name="bytes">the bytes to be checked.
+               /// 
+               /// </param>
+               /// <returns> true if encoding not required for LDIF
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static bool isLDIFSafe(sbyte[] bytes)
+               {
+                       int len = bytes.Length;
+                       if (len > 0)
+                       {
+                               int testChar = bytes[0];
+                               // unsafe if first character is a NON-SAFE-INIT-CHAR
+                               if ((testChar == 0x00) || (testChar == 0x0A) || (testChar == 0x0D) || (testChar == 0x20) || (testChar == 0x3A) || (testChar == 0x3C) || (testChar < 0))
+                               {
+                                       // non ascii (>127 is negative)
+                                       return false;
+                               }
+                               // unsafe if last character is a space
+                               if (bytes[len - 1] == ' ')
+                               {
+                                       return false;
+                               }
+                               // unsafe if contains any non safe character
+                               if (len > 1)
+                               {
+                                       for (int i = 1; i < bytes.Length; i++)
+                                       {
+                                               testChar = bytes[i];
+                                               if ((testChar == 0x00) || (testChar == 0x0A) || (testChar == 0x0D) || (testChar < 0))
+                                               {
+                                                       // non ascii (>127 is negative)
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
+                       return true;
+               }
+               /// <summary> Checks if the input String contains only safe values, that is,
+               /// the data does not need to be encoded for use with LDIF.
+               /// The rules for checking safety are based on the rules for LDIF
+               /// (Ldap Data Interchange Format) per RFC 2849.  The data does
+               /// not need to be encoded if all the following are true:
+               /// <br>
+               /// <p>The data cannot start with the following char values:</p>
+               /// <pre>
+               /// 00 (NUL)
+               /// 10 (LF)
+               /// 13 (CR)
+               /// 32 (SPACE)
+               /// 58 (:)
+               /// 60 (<)
+               /// Any character with value greater than 127
+               /// </pre>
+               /// <p>The data cannot contain any of the following char values:</p>
+               /// <pre>
+               /// 00 (NUL)
+               /// 10 (LF)
+               /// 13 (CR)
+               /// Any character with value greater than 127
+               /// </pre>
+               /// <p>The data cannot end with a space.</p>
+               /// 
+               /// </summary>
+               /// <param name="str">the String to be checked.
+               /// 
+               /// </param>
+               /// <returns> true if encoding not required for LDIF
+               /// </returns>
+               public static bool isLDIFSafe(System.String str)
+               {
+                       try
+                       {
+                               System.Text.Encoding encoder = System.Text.Encoding.GetEncoding("utf-8"); 
+                               byte[] ibytes = encoder.GetBytes(str);
+                               sbyte[] sbytes=SupportClass.ToSByteArray(ibytes);                               return (isLDIFSafe(sbytes));
+                       }
+                       catch (System.IO.IOException ue)
+                       {
+                               throw new System.SystemException("UTF-8 String encoding not supported by JVM");
+                       }
+               }
+               
+               /* **************UTF-8 Validation methods and members*******************
+               * The following text is taken from draft-yergeau-rfc2279bis-02 and explains
+               * UTF-8 encoding:
+               *
+               *<p>In UTF-8, characters are encoded using sequences of 1 to 6 octets.
+               * If the range of character numbers is restricted to U+0000..U+10FFFF
+               * (the UTF-16 accessible range), then only sequences of one to four
+               * octets will occur.  The only octet of a "sequence" of one has the
+               * higher-order bit set to 0, the remaining 7 bits being used to encode
+               * the character number.  In a sequence of n octets, n>1, the initial
+               * octet has the n higher-order bits set to 1, followed by a bit set to
+               * 0.  The remaining bit(s) of that octet contain bits from the number
+               * of the character to be encoded.  The following octet(s) all have the
+               * higher-order bit set to 1 and the following bit set to 0, leaving 6
+               * bits in each to contain bits from the character to be encoded.</p>
+               *
+               * <p>The table below summarizes the format of these different octet types.
+               * The letter x indicates bits available for encoding bits of the
+               * character number.</p>
+               *
+               * <pre>
+               * Char. number range  |        UTF-8 octet sequence
+               *    (hexadecimal)    |              (binary)
+               * --------------------+---------------------------------------------
+               * 0000 0000-0000 007F | 0xxxxxxx
+               * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
+               * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+               * 0001 0000-001F FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+               * 0020 0000-03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+               * 0400 0000-7FFF FFFF | 1111110x 10xxxxxx ... 10xxxxxx
+               * </pre>
+               */
+               
+               /// <summary> Given the first byte in a sequence, getByteCount returns the number of
+               /// additional bytes in a UTF-8 character sequence (not including the first
+               /// byte).
+               /// 
+               /// </summary>
+               /// <param name="b"> The first byte in a UTF-8 character sequence.
+               /// 
+               /// </param>
+               /// <returns> the number of additional bytes in a UTF-8 character sequence.
+               /// </returns>
+               private static int getByteCount(sbyte b)
+               {
+                       if (b > 0)
+                               return 0;
+                       if ((b & 0xE0) == 0xC0)
+                       {
+                               return 1; //one additional byte (2 bytes total)
+                       }
+                       if ((b & 0xF0) == 0xE0)
+                       {
+                               return 2; //two additional bytes (3 bytes total)
+                       }
+                       if ((b & 0xF8) == 0xF0)
+                       {
+                               return 3; //three additional bytes (4 bytes total)
+                       }
+                       if ((b & 0xFC) == 0xF8)
+                       {
+                               return 4; //four additional bytes (5 bytes total)
+                       }
+                       if ((b & 0xFF) == 0xFC)
+                       {
+                               return 5; //five additional bytes (6 bytes total)
+                       }
+                       return - 1;
+               }
+               
+               /// <summary> Bit masks used to determine if a the value of UTF-8 byte sequence
+               /// is less than the minimum value.
+               /// 
+               /// <p>If the value of a byte sequence is less than the minimum value then
+               /// the number should be encoded in fewer bytes and is invalid.  For example
+               /// If the first byte indicates that a sequence has three bytes in a
+               /// sequence. Then the top five bits cannot be zero.  Notice the index into
+               /// the array is one less than the number of bytes in a sequence.
+               /// A validity test for this could be:
+               /// <pre>
+               /// if ((lowerBoundMask[1][0] & byte[0] != 0) ||
+               /// (lowerBoundMask[1][1] & byte[1] != 0)) {
+               /// then the value is above the minimum and is valid.
+               /// }
+               /// </pre>
+               /// </summary>
+               private static readonly sbyte[][] lowerBoundMask = {new sbyte[]{0, 0}, new sbyte[]{(sbyte) (0x1E), (sbyte) (0x00)}, new sbyte[]{(sbyte) (0x0F), (sbyte) (0x20)}, new sbyte[]{(sbyte) (0x07), (sbyte) (0x30)}, new sbyte[]{(sbyte) (0x02), (sbyte) (0x38)}, new sbyte[]{(sbyte) (0x01), (sbyte) (0x3C)}};
+               
+               /// <summary>mask to AND with a continuation byte: should equal continuationResult </summary>
+               private static sbyte continuationMask = (sbyte) SupportClass.Identity(0xC0);
+               
+               /// <summary>expected result of ANDing a continuation byte with continuationMask </summary>
+               private static sbyte continuationResult = (sbyte) SupportClass.Identity(0x80);
+               
+               /// <summary> Determines if an array of bytes contains only valid UTF-8 characters.
+               /// <p>
+               /// UTF-8 is the standard encoding for Ldap strings.  If a value contains
+               /// data that is not valid UTF-8 then data is lost converting the
+               /// value to a Java String.
+               /// </p>
+               /// 
+               /// <p>In addition, Java Strings currently use UCS2 (Unicode Code Standard
+               /// 2-byte characters). UTF-8 can be encoded as USC2 and UCS4 (4-byte
+               /// characters).  Some valid UTF-8 characters cannot be represented as UCS2
+               /// characters. To determine if all UTF-8 sequences can be encoded into
+               /// UCS2 characters (a Java String), specify the <code>isUCS2Only</code>
+               /// parameter as <code>true</code>.<p>
+               /// 
+               /// </summary>
+               /// <param name="array"> An array of bytes that are to be tested for valid UTF-8
+               /// encoding.
+               /// <br><br>
+               /// </param>
+               /// <param name="isUCS2Only">true if the UTF-8 values must be restricted to fit
+               /// within UCS2 encoding (2 bytes)
+               /// </param>
+               /// <returns> true if all values in the byte array are valid UTF-8
+               /// sequences.  If <code>isUCS2Only</code> is
+               /// <code>true</code>, the method returns false if a UTF-8
+               /// sequence generates any character that cannot be
+               /// represented as a UCS2 character (Java String)
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public static bool isValidUTF8(sbyte[] array, bool isUCS2Only)
+               {
+                       int index = 0;
+                       while (index < array.Length)
+                       {
+                               int count = getByteCount(array[index]);
+                               if (count == 0)
+                               {
+                                       //anything that qualifies as count=0 is valid UTF-8
+                                       index++;
+                                       continue;
+                               }
+                               
+                               if (count == - 1 || index + count >= array.Length || (isUCS2Only && count >= 3))
+                               {
+                                       /* Any count that puts us out of bounds for the index is
+                                       * invalid.  Valid UCS2 characters can only have 2 additional
+                                       * bytes. (three total) */
+                                       return false;
+                               }
+                               
+                               /* Tests if the first and second byte are below the minimum bound */
+                               if ((lowerBoundMask[count][0] & array[index]) == 0 && (lowerBoundMask[count][1] & array[index + 1]) == 0)
+                               {
+                                       return false;
+                               }
+                               
+                               /* testing continuation on the second and following bytes */
+                               for (int i = 1; i <= count; i++)
+                               {
+                                       if ((array[index + i] & continuationMask) != continuationResult)
+                                       {
+                                               return false;
+                                       }
+                               }
+                               index += count + 1;
+                       }
+                       return true;
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/BindProperties.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/BindProperties.cs
new file mode 100755 (executable)
index 0000000..3d25553
--- /dev/null
@@ -0,0 +1,134 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.BindProperties.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> Encapsulates an Ldap Bind properties</summary>
+       public class BindProperties
+       {
+               /// <summary> gets the protocol version</summary>
+               virtual public int ProtocolVersion
+               {
+                       get
+                       {
+                               return version;
+                       }
+                       
+               }
+               /// <summary> Gets the authentication dn
+               /// 
+               /// </summary>
+               /// <returns> the authentication dn for this connection
+               /// </returns>
+               virtual public System.String AuthenticationDN
+               {
+                       get
+                       {
+                               return dn;
+                       }
+                       
+               }
+               /// <summary> Gets the authentication method
+               /// 
+               /// </summary>
+               /// <returns> the authentication method for this connection
+               /// </returns>
+               virtual public System.String AuthenticationMethod
+               {
+                       get
+                       {
+                               return method;
+                       }
+                       
+               }
+               /// <summary> Gets the SASL Bind properties
+               /// 
+               /// </summary>
+               /// <returns> the sasl bind properties for this connection
+               /// </returns>
+               virtual public System.Collections.Hashtable SaslBindProperties
+               {
+                       get
+                       {
+                               return bindProperties;
+                       }
+                       
+               }
+               
+               /// <summary> Gets the SASL callback handler
+               /// 
+               /// </summary>
+               /// <returns> the sasl callback handler for this connection
+               /// </returns>
+               virtual public System.Object SaslCallbackHandler
+               {
+                       get
+                       {
+                               return bindCallbackHandler;
+                       }
+                       
+               }
+               
+               /// <summary> Indicates whether or not the bind properties specify an anonymous bind
+               /// 
+               /// </summary>
+               /// <returns> true if the bind properties specify an anonymous bind
+               /// </returns>
+               virtual public bool Anonymous
+               {
+                       get
+                       {
+                               return anonymous;
+                       }
+                       
+               }
+               
+               private int version = 3;
+               private System.String dn = null;
+               private System.String method = null;
+               private bool anonymous;
+               private System.Collections.Hashtable bindProperties = null;
+               private System.Object bindCallbackHandler = null;
+               
+               public BindProperties(int version, System.String dn, System.String method, bool anonymous, System.Collections.Hashtable bindProperties, System.Object bindCallbackHandler)
+               {
+                       this.version = version;
+                       this.dn = dn;
+                       this.method = method;
+                       this.anonymous = anonymous;
+                       this.bindProperties = bindProperties;
+                       this.bindCallbackHandler = bindCallbackHandler;
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/DN.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/DN.cs
new file mode 100755 (executable)
index 0000000..6db86f7
--- /dev/null
@@ -0,0 +1,743 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.DN.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> <P>A DN encapsulates a Distinguished Name (an ldap name with context). A DN
+       /// does not need to be fully distinguished, or extend to the Root of a
+       /// directory.  It provides methods to get information about the DN and to
+       /// manipulate the DN.  </P>
+       /// 
+       /// <P> The following are examples of valid DN:
+       /// <ul>
+       /// <li>cn=admin,ou=marketing,o=corporation</li>
+       /// <li>cn=admin,ou=marketing</li>
+       /// <li>2.5.4.3=admin,ou=marketing</li>
+       /// <li>oid.2.5.4.3=admin,ou=marketing</li>
+       /// </ul>
+       /// 
+       /// <P>Note: Multivalued attributes are all considered to be one
+       /// component and are represented in one RDN (see RDN)
+       /// </P>
+       /// 
+       /// </summary>
+       /// <seealso cref="RDN">
+       /// </seealso>
+       
+       public class DN : System.Object
+       {
+               private void  InitBlock()
+               {
+                       rdnList = new System.Collections.ArrayList();
+               }
+               /// <summary> Retrieves a list of RDN Objects, or individual names of the DN</summary>
+               /// <returns> list of RDNs
+               /// </returns>
+               virtual public System.Collections.ArrayList RDNs
+               {
+                       get
+                       {
+                               int size = rdnList.Count;
+                               System.Collections.ArrayList v = new System.Collections.ArrayList(size);
+                               for (int i = 0; i < size; i++)
+                               {
+                                       v.Add(rdnList[i]);
+                               }
+                               return v;
+                       }
+                       
+               }
+               /// <summary> Returns the Parent of this DN</summary>
+               /// <returns> Parent DN
+               /// </returns>
+               virtual public DN Parent
+               {
+                       get
+                       {
+                               DN parent = new DN();
+                               parent.rdnList = (System.Collections.ArrayList) this.rdnList.Clone();
+                               if (parent.rdnList.Count >= 1)
+                                       parent.rdnList.Remove(rdnList[0]); //remove first object
+                               return parent;
+                       }
+                       
+               }
+               
+               //parser state identifiers.
+               private const int LOOK_FOR_RDN_ATTR_TYPE = 1;
+               private const int ALPHA_ATTR_TYPE = 2;
+               private const int OID_ATTR_TYPE = 3;
+               private const int LOOK_FOR_RDN_VALUE = 4;
+               private const int QUOTED_RDN_VALUE = 5;
+               private const int HEX_RDN_VALUE = 6;
+               private const int UNQUOTED_RDN_VALUE = 7;
+               
+               /* State transition table:  Parsing starts in state 1.
+               
+               State   COMMA   DIGIT   "Oid."  ALPHA   EQUAL   QUOTE   SHARP   HEX
+               --------------------------------------------------------------------
+               1       Err     3       3       2       Err     Err     Err     Err
+               2       Err     Err     Err     2       4       Err     Err     Err
+               3       Err     3       Err     Err     4       Err     Err     Err
+               4       Err     7       Err     7       Err     5       6       7
+               5       1       5       Err     5       Err     1       Err     7
+               6       1       6       Err     Err     Err     Err     Err     6
+               7       1       7       Err     7       Err     Err     Err     7
+               
+               */
+               
+               
+               private System.Collections.ArrayList rdnList;
+               
+               public DN()
+               {
+                       InitBlock();
+                       return ;
+               }
+               /// <summary> Constructs a new DN based on the specified string representation of a
+               /// distinguished name. The syntax of the DN must conform to that specified
+               /// in RFC 2253.
+               /// 
+               /// </summary>
+               /// <param name="dnString">a string representation of the distinguished name
+               /// </param>
+               /// <exception cref="">  IllegalArgumentException  if the the value of the dnString
+               /// parameter does not adhere to the syntax described in
+               /// RFC 2253
+               /// </exception>
+               public DN(System.String dnString)
+               {
+                       InitBlock();
+                       /* the empty string is a valid DN */
+                       if (dnString.Length == 0)
+                               return ;
+                       
+                       char currChar;
+                       char nextChar;
+                       int currIndex;
+                       char[] tokenBuf = new char[dnString.Length];
+                       int tokenIndex;
+                       int lastIndex;
+                       int valueStart;
+                       int state;
+                       int trailingSpaceCount = 0;
+                       System.String attrType = "";
+                       System.String attrValue = "";
+                       System.String rawValue = "";
+                       int hexDigitCount = 0;
+                       RDN currRDN = new RDN();
+                       
+                       //indicates whether an OID number has a first digit of ZERO
+                       bool firstDigitZero = false;
+                       
+                       tokenIndex = 0;
+                       currIndex = 0;
+                       valueStart = 0;
+                       state = LOOK_FOR_RDN_ATTR_TYPE;
+                       lastIndex = dnString.Length - 1;
+                       while (currIndex <= lastIndex)
+                       {
+                               currChar = dnString[currIndex];
+                               switch (state)
+                               {
+                                       
+                                       case LOOK_FOR_RDN_ATTR_TYPE: 
+                                               while (currChar == ' ' && (currIndex < lastIndex))
+                                                       currChar = dnString[++currIndex];
+                                               if (isAlpha(currChar))
+                                               {
+                                                       if (dnString.Substring(currIndex).StartsWith("oid.") || dnString.Substring(currIndex).StartsWith("OID."))
+                                                       {
+                                                               //form is "oid.###.##.###... or OID.###.##.###...
+                                                               currIndex += 4; //skip oid. prefix and get to actual oid
+                                                               if (currIndex > lastIndex)
+                                                                       throw new System.ArgumentException(dnString);
+                                                               currChar = dnString[currIndex];
+                                                               if (isDigit(currChar))
+                                                               {
+                                                                       tokenBuf[tokenIndex++] = currChar;
+                                                                       state = OID_ATTR_TYPE;
+                                                               }
+                                                               else
+                                                                       throw new System.ArgumentException(dnString);
+                                                       }
+                                                       else
+                                                       {
+                                                               tokenBuf[tokenIndex++] = currChar;
+                                                               state = ALPHA_ATTR_TYPE;
+                                                       }
+                                               }
+                                               else if (isDigit(currChar))
+                                               {
+                                                       --currIndex;
+                                                       state = OID_ATTR_TYPE;
+                                               }
+                                               else if (!(System.Char.GetUnicodeCategory(currChar) == System.Globalization.UnicodeCategory.SpaceSeparator))
+                                                       throw new System.ArgumentException(dnString);
+                                               break;
+                                       
+                                       
+                                       case ALPHA_ATTR_TYPE: 
+                                               if (isAlpha(currChar) || isDigit(currChar) || (currChar == '-'))
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                               else
+                                               {
+                                                       //skip any spaces
+                                                       while ((currChar == ' ') && (currIndex < lastIndex))
+                                                               currChar = dnString[++currIndex];
+                                                       if (currChar == '=')
+                                                       {
+                                                               attrType = new System.String(tokenBuf, 0, tokenIndex);
+                                                               tokenIndex = 0;
+                                                               state = LOOK_FOR_RDN_VALUE;
+                                                       }
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               break;
+                                       
+                                       
+                                       case OID_ATTR_TYPE: 
+                                               if (!isDigit(currChar))
+                                                       throw new System.ArgumentException(dnString);
+                                               firstDigitZero = (currChar == '0')?true:false;
+                                               tokenBuf[tokenIndex++] = currChar;
+                                               currChar = dnString[++currIndex];
+                                               
+                                               if ((isDigit(currChar) && firstDigitZero) || (currChar == '.' && firstDigitZero))
+                                               {
+                                                       throw new System.ArgumentException(dnString);
+                                               }
+                                               
+                                               //consume all numbers.
+                                               while (isDigit(currChar) && (currIndex < lastIndex))
+                                               {
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                                       currChar = dnString[++currIndex];
+                                               }
+                                               if (currChar == '.')
+                                               {
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                                       //The state remains at OID_ATTR_TYPE
+                                               }
+                                               else
+                                               {
+                                                       //skip any spaces
+                                                       while (currChar == ' ' && (currIndex < lastIndex))
+                                                               currChar = dnString[++currIndex];
+                                                       if (currChar == '=')
+                                                       {
+                                                               attrType = new System.String(tokenBuf, 0, tokenIndex);
+                                                               tokenIndex = 0;
+                                                               state = LOOK_FOR_RDN_VALUE;
+                                                       }
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               break;
+                                       
+                                       
+                                       case LOOK_FOR_RDN_VALUE: 
+                                               while (currChar == ' ')
+                                               {
+                                                       if (currIndex < lastIndex)
+                                                               currChar = dnString[++currIndex];
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               if (currChar == '"')
+                                               {
+                                                       state = QUOTED_RDN_VALUE;
+                                                       valueStart = currIndex;
+                                               }
+                                               else if (currChar == '#')
+                                               {
+                                                       hexDigitCount = 0;
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                                       valueStart = currIndex;
+                                                       state = HEX_RDN_VALUE;
+                                               }
+                                               else
+                                               {
+                                                       valueStart = currIndex;
+                                                       //check this character again in the UNQUOTED_RDN_VALUE state
+                                                       currIndex--;
+                                                       state = UNQUOTED_RDN_VALUE;
+                                               }
+                                               break;
+                                       
+                                       
+                                       case UNQUOTED_RDN_VALUE: 
+                                               if (currChar == '\\')
+                                               {
+                                                       if (!(currIndex < lastIndex))
+                                                               throw new System.ArgumentException(dnString);
+                                                       currChar = dnString[++currIndex];
+                                                       if (isHexDigit(currChar))
+                                                       {
+                                                               if (!(currIndex < lastIndex))
+                                                                       throw new System.ArgumentException(dnString);
+                                                               nextChar = dnString[++currIndex];
+                                                               if (isHexDigit(nextChar))
+                                                               {
+                                                                       tokenBuf[tokenIndex++] = hexToChar(currChar, nextChar);
+                                                                       trailingSpaceCount = 0;
+                                                               }
+                                                               else
+                                                                       throw new System.ArgumentException(dnString);
+                                                       }
+                                                       else if (needsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ')
+                                                       {
+                                                               tokenBuf[tokenIndex++] = currChar;
+                                                               trailingSpaceCount = 0;
+                                                       }
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               else if (currChar == ' ')
+                                               {
+                                                       trailingSpaceCount++;
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                               }
+                                               else if ((currChar == ',') || (currChar == ';') || (currChar == '+'))
+                                               {
+                                                       attrValue = new System.String(tokenBuf, 0, tokenIndex - trailingSpaceCount);
+                                                       rawValue = dnString.Substring(valueStart, (currIndex - trailingSpaceCount) - (valueStart));
+                                                       
+                                                       currRDN.add(attrType, attrValue, rawValue);
+                                                       if (currChar != '+')
+                                                       {
+                                                               rdnList.Add(currRDN);
+                                                               currRDN = new RDN();
+                                                       }
+                                                       
+                                                       trailingSpaceCount = 0;
+                                                       tokenIndex = 0;
+                                                       state = LOOK_FOR_RDN_ATTR_TYPE;
+                                               }
+                                               else if (needsEscape(currChar))
+                                               {
+                                                       throw new System.ArgumentException(dnString);
+                                               }
+                                               else
+                                               {
+                                                       trailingSpaceCount = 0;
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                               }
+                                               break; //end UNQUOTED RDN VALUE
+                                       
+                                       
+                                       case QUOTED_RDN_VALUE: 
+                                               if (currChar == '"')
+                                               {
+                                                       rawValue = dnString.Substring(valueStart, (currIndex + 1) - (valueStart));
+                                                       if (currIndex < lastIndex)
+                                                               currChar = dnString[++currIndex];
+                                                       //skip any spaces
+                                                       while ((currChar == ' ') && (currIndex < lastIndex))
+                                                               currChar = dnString[++currIndex];
+                                                       if ((currChar == ',') || (currChar == ';') || (currChar == '+') || (currIndex == lastIndex))
+                                                       {
+                                                               attrValue = new System.String(tokenBuf, 0, tokenIndex);
+                                                               
+                                                               currRDN.add(attrType, attrValue, rawValue);
+                                                               if (currChar != '+')
+                                                               {
+                                                                       rdnList.Add(currRDN);
+                                                                       currRDN = new RDN();
+                                                               }
+                                                               trailingSpaceCount = 0;
+                                                               tokenIndex = 0;
+                                                               state = LOOK_FOR_RDN_ATTR_TYPE;
+                                                       }
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               else if (currChar == '\\')
+                                               {
+                                                       currChar = dnString[++currIndex];
+                                                       if (isHexDigit(currChar))
+                                                       {
+                                                               nextChar = dnString[++currIndex];
+                                                               if (isHexDigit(nextChar))
+                                                               {
+                                                                       tokenBuf[tokenIndex++] = hexToChar(currChar, nextChar);
+                                                                       trailingSpaceCount = 0;
+                                                               }
+                                                               else
+                                                                       throw new System.ArgumentException(dnString);
+                                                       }
+                                                       else if (needsEscape(currChar) || currChar == '#' || currChar == '=' || currChar == ' ')
+                                                       {
+                                                               tokenBuf[tokenIndex++] = currChar;
+                                                               trailingSpaceCount = 0;
+                                                       }
+                                                       else
+                                                               throw new System.ArgumentException(dnString);
+                                               }
+                                               else
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                               break; //end QUOTED RDN VALUE
+                                       
+                                       
+                                       case HEX_RDN_VALUE: 
+                                               if ((!isHexDigit(currChar)) || (currIndex > lastIndex))
+                                               {
+                                                       //check for odd number of hex digits
+                                                       if ((hexDigitCount % 2) != 0 || hexDigitCount == 0)
+                                                               throw new System.ArgumentException(dnString);
+                                                       else
+                                                       {
+                                                               rawValue = dnString.Substring(valueStart, (currIndex) - (valueStart));
+                                                               //skip any spaces
+                                                               while ((currChar == ' ') && (currIndex < lastIndex))
+                                                                       currChar = dnString[++currIndex];
+                                                               if ((currChar == ',') || (currChar == ';') || (currChar == '+') || (currIndex == lastIndex))
+                                                               {
+                                                                       attrValue = new System.String(tokenBuf, 0, tokenIndex);
+                                                                       
+                                                                       //added by cameron
+                                                                       currRDN.add(attrType, attrValue, rawValue);
+                                                                       if (currChar != '+')
+                                                                       {
+                                                                               rdnList.Add(currRDN);
+                                                                               currRDN = new RDN();
+                                                                       }
+                                                                       tokenIndex = 0;
+                                                                       state = LOOK_FOR_RDN_ATTR_TYPE;
+                                                               }
+                                                               else
+                                                               {
+                                                                       throw new System.ArgumentException(dnString);
+                                                               }
+                                                       }
+                                               }
+                                               else
+                                               {
+                                                       tokenBuf[tokenIndex++] = currChar;
+                                                       hexDigitCount++;
+                                               }
+                                               break; //end HEX RDN VALUE
+                                       } //end switch
+                               currIndex++;
+                       } //end while
+                       
+                       //check ending state
+                       if (state == UNQUOTED_RDN_VALUE || (state == HEX_RDN_VALUE && (hexDigitCount % 2) == 0) && hexDigitCount != 0)
+                       {
+                               attrValue = new System.String(tokenBuf, 0, tokenIndex - trailingSpaceCount);
+                               rawValue = dnString.Substring(valueStart, (currIndex - trailingSpaceCount) - (valueStart));
+                               currRDN.add(attrType, attrValue, rawValue);
+                               rdnList.Add(currRDN);
+                       }
+                       else if (state == LOOK_FOR_RDN_VALUE)
+                       {
+                               //empty value is valid
+                               attrValue = "";
+                               rawValue = dnString.Substring(valueStart);
+                               currRDN.add(attrType, attrValue, rawValue);
+                               rdnList.Add(currRDN);
+                       }
+                       else
+                       {
+                               throw new System.ArgumentException(dnString);
+                       }
+               } //end DN constructor (string dn)
+               
+               
+               /// <summary> Checks a character to see if it is an ascii alphabetic character in
+               /// ranges 65-90 or 97-122.
+               /// 
+               /// </summary>
+               /// <param name="ch">the character to be tested.
+               /// </param>
+               /// <returns>  <code>true</code> if the character is an ascii alphabetic
+               /// character
+               /// </returns>
+               private bool isAlpha(char ch)
+               {
+                       if (((ch < 91) && (ch > 64)) || ((ch < 123) && (ch > 96)))
+                       //ASCII A-Z
+                               return true;
+                       else
+                               return false;
+               }
+               
+               
+               /// <summary> Checks a character to see if it is an ascii digit (0-9) character in
+               /// the ascii value range 48-57.
+               /// 
+               /// </summary>
+               /// <param name="ch">the character to be tested.
+               /// </param>
+               /// <returns>  <code>true</code> if the character is an ascii alphabetic
+               /// character
+               /// </returns>
+               private bool isDigit(char ch)
+               {
+                       if ((ch < 58) && (ch > 47))
+                       //ASCII 0-9
+                               return true;
+                       else
+                               return false;
+               }
+               
+               /// <summary> Checks a character to see if it is valid hex digit 0-9, a-f, or
+               /// A-F (ASCII value ranges 48-47, 65-70, 97-102).
+               /// 
+               /// </summary>
+               /// <param name="ch">the character to be tested.
+               /// </param>
+               /// <returns>  <code>true</code> if the character is a valid hex digit
+               /// </returns>
+               
+               private static bool isHexDigit(char ch)
+               {
+                       if (((ch < 58) && (ch > 47)) || ((ch < 71) && (ch > 64)) || ((ch < 103) && (ch > 96)))
+                       //ASCII A-F
+                               return true;
+                       else
+                               return false;
+               }
+               
+               /// <summary> Checks a character to see if it must always be escaped in the
+               /// string representation of a DN.  We must tests for space, sharp, and
+               /// equals individually.
+               /// 
+               /// </summary>
+               /// <param name="ch">the character to be tested.
+               /// </param>
+               /// <returns>  <code>true</code> if the character needs to be escaped in at
+               /// least some instances.
+               /// </returns>
+               private bool needsEscape(char ch)
+               {
+                       if ((ch == ',') || (ch == '+') || (ch == '\"') || (ch == ';') || (ch == '<') || (ch == '>') || (ch == '\\'))
+                               return true;
+                       else
+                               return false;
+               }
+               
+               /// <summary> Converts two valid hex digit characters that form the string
+               /// representation of an ascii character value to the actual ascii
+               /// character.
+               /// 
+               /// </summary>
+               /// <param name="hex1">the hex digit for the high order byte.
+               /// </param>
+               /// <param name="hex0">the hex digit for the low order byte.
+               /// </param>
+               /// <returns>  the character whose value is represented by the parameters.
+               /// </returns>
+               
+               private static char hexToChar(char hex1, char hex0)
+               {
+                       int result;
+                       
+                       if ((hex1 < 58) && (hex1 > 47))
+                       //ASCII 0-9
+                               result = (hex1 - 48) * 16;
+                       else if ((hex1 < 71) && (hex1 > 64))
+                       //ASCII a-f
+                               result = (hex1 - 55) * 16;
+                       else if ((hex1 < 103) && (hex1 > 96))
+                       //ASCII A-F
+                               result = (hex1 - 87) * 16;
+                       else
+                               throw new System.ArgumentException("Not hex digit");
+                       
+                       if ((hex0 < 58) && (hex0 > 47))
+                       //ASCII 0-9
+                               result += (hex0 - 48);
+                       else if ((hex0 < 71) && (hex0 > 64))
+                       //ASCII a-f
+                               result += (hex0 - 55);
+                       else if ((hex0 < 103) && (hex0 > 96))
+                       //ASCII A-F
+                               result += (hex0 - 87);
+                       else
+                               throw new System.ArgumentException("Not hex digit");
+                       
+                       return (char) result;
+               }
+               
+               /// <summary> Creates and returns a string that represents this DN.  The string
+               /// follows RFC 2253, which describes String representation of DN's and
+               /// RDN's
+               /// 
+               /// </summary>
+               /// <returns> A DN string.
+               /// </returns>
+               public override System.String ToString()
+               {
+                       int length = rdnList.Count;
+                       System.String dn = "";
+                       if (length < 1)
+                               return null;
+                       dn = rdnList[0].ToString();
+                       for (int i = 1; i < length; i++)
+                       {
+                               dn += ("," + rdnList[i].ToString());
+                       }
+                       return dn;
+               }
+               
+               
+               /// <summary> Compares this DN to the specified DN to determine if they are equal.
+               /// 
+               /// </summary>
+               /// <param name="toDN">the DN to compare to
+               /// </param>
+               /// <returns>  <code>true</code> if the DNs are equal; otherwise
+               /// <code>false</code>
+               /// </returns>
+
+               public System.Collections.ArrayList getrdnList()
+               {
+                       return this.rdnList;
+               }
+               public  override bool Equals(System.Object toDN)
+               {
+                       return Equals((DN) toDN);
+               }
+               public   bool Equals(DN toDN)
+               {
+                       System.Collections.ArrayList aList=toDN.getrdnList();
+                       int length = aList.Count;
+                       
+                       if (this.rdnList.Count != length)
+                               return false;
+                       
+                       for (int i = 0; i < length; i++)
+                       {
+                               if (!((RDN) rdnList[i]).equals((RDN) toDN.getrdnList()[i]))
+                                       return false;
+                       }
+                       return true;
+               }
+               
+               /// <summary> return a string array of the individual RDNs contained in the DN
+               /// 
+               /// </summary>
+               /// <param name="noTypes">  If true, returns only the values of the
+               /// components, and not the names, e.g. "Babs
+               /// Jensen", "Accounting", "Acme", "us" - instead of
+               /// "cn=Babs Jensen", "ou=Accounting", "o=Acme", and
+               /// "c=us".
+               /// </param>
+               /// <returns>  <code>String[]</code> containing the rdns in the DN with
+               /// the leftmost rdn in the first element of the array
+               /// 
+               /// </returns>
+               public virtual System.String[] explodeDN(bool noTypes)
+               {
+                       int length = rdnList.Count;
+                       System.String[] rdns = new System.String[length];
+                       for (int i = 0; i < length; i++)
+                               rdns[i] = ((RDN) rdnList[i]).toString(noTypes);
+                       return rdns;
+               }
+               
+               /// <summary> Retrieves the count of RDNs, or individule names, in the Distinguished name</summary>
+               /// <returns> the count of RDN
+               /// </returns>
+               public virtual int countRDNs()
+               {
+                       return rdnList.Count;
+               }
+               
+               /// <summary>Determines if this DN is <I>contained</I> by the DN passed in.  For
+               /// example:  "cn=admin, ou=marketing, o=corporation" is contained by
+               /// "o=corporation", "ou=marketing, o=corporation", and "ou=marketing"
+               /// but <B>not</B> by "cn=admin" or "cn=admin,ou=marketing,o=corporation"
+               /// Note: For users of Netscape's SDK this method is comparable to contains
+               /// 
+               /// </summary>
+               /// <param name="containerDN">of a container
+               /// </param>
+               /// <returns> true if containerDN contains this DN
+               /// </returns>
+               public virtual bool isDescendantOf(DN containerDN)
+               {
+                       int i = containerDN.rdnList.Count - 1; //index to an RDN of the ContainerDN
+                       int j = this.rdnList.Count - 1; //index to an RDN of the ContainedDN
+                       //Search from the end of the DN for an RDN that matches the end RDN of
+                       //containerDN.
+                       while (!((RDN) this.rdnList[j--]).equals((RDN) containerDN.rdnList[i]))
+                       {
+                               if (j <= 0)
+                                       return false;
+                               //if the end RDN of containerDN does not have any equal
+                               //RDN in rdnList, then containerDN does not contain this DN
+                       }
+                       i--; //avoid a redundant compare
+                       j--;
+                       //step backwards to verify that all RDNs in containerDN exist in this DN
+                       for (; i >= 0 && j >= 0; i--, j--)
+                       {
+                               if (!((RDN) this.rdnList[j]).equals((RDN) containerDN.rdnList[i]))
+                                       return false;
+                       }
+                       if (j == 0 && i == 0)
+                       //the DNs are identical and thus not contained
+                               return false;
+                       
+                       return true;
+               }
+               
+               /// <summary> Adds the RDN to the beginning of the current DN.</summary>
+               /// <param name="rdn">an RDN to be added
+               /// </param>
+               public virtual void  addRDN(RDN rdn)
+               {
+                       rdnList.Insert(0, rdn);
+               }
+               
+               /// <summary> Adds the RDN to the beginning of the current DN.</summary>
+               /// <param name="rdn">an RDN to be added
+               /// </param>
+               public virtual void  addRDNToFront(RDN rdn)
+               {
+                       rdnList.Insert(0, rdn);
+               }
+               
+               /// <summary> Adds the RDN to the end of the current DN</summary>
+               /// <param name="rdn">an RDN to be added
+               /// </param>
+               public virtual void  addRDNToBack(RDN rdn)
+               {
+                       rdnList.Add(rdn);
+               }
+       } //end class DN
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/EnumeratedIterator.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/EnumeratedIterator.cs
new file mode 100755 (executable)
index 0000000..beecaf4
--- /dev/null
@@ -0,0 +1,91 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.EnumeratedIterator.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       /// <summary> wrappers a class of type Iterator and makes it act as an Enumerator.  This
+       /// is used when the API requires enumerations be used but we may be using
+       /// JDK1.2 collections, which return iterators instead of enumerators.  Used by
+       /// LdapSchema and LdapSchemaElement
+       /// 
+       /// </summary>
+       /// <seealso cref="com.novell.ldap.LdapSchema#getAttributeSchemas">
+       /// </seealso>
+       /// <seealso cref="com.novell.ldap.LdapSchemaElement#getQualifierNames">
+       /// </seealso>
+       
+       public class EnumeratedIterator : System.Collections.IEnumerator
+       {
+               private System.Object tempAuxObj;
+               public virtual bool MoveNext()
+               {
+                       bool result = hasMoreElements();
+                       if (result)
+                       {
+                               tempAuxObj = nextElement();
+                       }
+                       return result;
+               }
+               public virtual void  Reset()
+               {
+                       tempAuxObj = null;
+               }
+               public virtual System.Object Current
+               {
+                       get
+                       {
+                               return tempAuxObj;
+                       }
+                       
+               }
+               private System.Collections.IEnumerator i;
+               
+               public EnumeratedIterator(System.Collections.IEnumerator iterator)
+               {
+                       i = iterator;
+                       return ;
+               }
+               
+               /// <summary> Enumeration method that maps to Iterator.hasNext()</summary>
+               public bool hasMoreElements()
+               {
+                       return i.MoveNext();
+               }
+               
+               /// <summary> Enumeration method that maps to Iterator.next()</summary>
+               public System.Object nextElement()
+               {
+                       return i.Current;
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExceptionMessages.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExceptionMessages.cs
new file mode 100755 (executable)
index 0000000..ace778e
--- /dev/null
@@ -0,0 +1,120 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ExceptionMessages.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> This class contains strings that may be associated with Exceptions generated
+       /// by the Ldap API libraries.
+       /// Two entries are made for each message, a String identifier, and the
+       /// actual error string.  Parameters are identified as {0}, {1}, etc.
+       /// </summary>
+       public class ExceptionMessages:System.Resources.ResourceManager
+       {
+               public System.Object[][] getContents()
+               {
+                       return contents;
+               }
+               //static strings to aide lookup and guarantee accuracy:
+               //DO NOT include these strings in other Locales
+               [CLSCompliantAttribute(false)]
+               public const System.String TOSTRING = "TOSTRING";
+               public const System.String SERVER_MSG = "SERVER_MSG";
+               public const System.String MATCHED_DN = "MATCHED_DN";
+               public const System.String FAILED_REFERRAL = "FAILED_REFERRAL";
+               public const System.String REFERRAL_ITEM = "REFERRAL_ITEM";
+               public const System.String CONNECTION_ERROR = "CONNECTION_ERROR";
+               public const System.String CONNECTION_IMPOSSIBLE = "CONNECTION_IMPOSSIBLE";
+               public const System.String CONNECTION_WAIT = "CONNECTION_WAIT";
+               public const System.String CONNECTION_FINALIZED = "CONNECTION_FINALIZED";
+               public const System.String CONNECTION_CLOSED = "CONNECTION_CLOSED";
+               public const System.String CONNECTION_READER = "CONNECTION_READER";
+               public const System.String DUP_ERROR = "DUP_ERROR";
+               public const System.String REFERRAL_ERROR = "REFERRAL_ERROR";
+               public const System.String REFERRAL_LOCAL = "REFERRAL_LOCAL";
+               public const System.String REFERENCE_ERROR = "REFERENCE_ERROR";
+               public const System.String REFERRAL_SEND = "REFERRAL_SEND";
+               public const System.String REFERENCE_NOFOLLOW = "REFERENCE_NOFOLLOW";
+               public const System.String REFERRAL_BIND = "REFERRAL_BIND";
+               public const System.String REFERRAL_BIND_MATCH = "REFERRAL_BIND_MATCH";
+               public const System.String NO_DUP_REQUEST = "NO_DUP_REQUEST";
+               public const System.String SERVER_CONNECT_ERROR = "SERVER_CONNECT_ERROR";
+               public const System.String NO_SUP_PROPERTY = "NO_SUP_PROPERTY";
+               public const System.String ENTRY_PARAM_ERROR = "ENTRY_PARAM_ERROR";
+               public const System.String DN_PARAM_ERROR = "DN_PARAM_ERROR";
+               public const System.String RDN_PARAM_ERROR = "RDN_PARAM_ERROR";
+               public const System.String OP_PARAM_ERROR = "OP_PARAM_ERROR";
+               public const System.String PARAM_ERROR = "PARAM_ERROR";
+               public const System.String DECODING_ERROR = "DECODING_ERROR";
+               public const System.String ENCODING_ERROR = "ENCODING_ERROR";
+               public const System.String IO_EXCEPTION = "IO_EXCEPTION";
+               public const System.String INVALID_ESCAPE = "INVALID_ESCAPE";
+               public const System.String SHORT_ESCAPE = "SHORT_ESCAPE";
+               public const System.String INVALID_CHAR_IN_FILTER = "INVALID_CHAR_IN_FILTER";
+               public const System.String INVALID_CHAR_IN_DESCR = "INVALID_CHAR_IN_DESCR";
+               public const System.String INVALID_ESC_IN_DESCR = "INVALID_ESC_IN_DESCR";
+               public const System.String UNEXPECTED_END = "UNEXPECTED_END";
+               public const System.String MISSING_LEFT_PAREN = "MISSING_LEFT_PAREN";
+               public const System.String MISSING_RIGHT_PAREN = "MISSING_RIGHT_PAREN";
+               public const System.String EXPECTING_RIGHT_PAREN = "EXPECTING_RIGHT_PAREN";
+               public const System.String EXPECTING_LEFT_PAREN = "EXPECTING_LEFT_PAREN";
+               public const System.String NO_OPTION = "NO_OPTION";
+               public const System.String INVALID_FILTER_COMPARISON = "INVALID_FILTER_COMPARISON";
+               public const System.String NO_MATCHING_RULE = "NO_MATCHING_RULE";
+               public const System.String NO_ATTRIBUTE_NAME = "NO_ATTRIBUTE_NAME";
+               public const System.String NO_DN_NOR_MATCHING_RULE = "NO_DN_NOR_MATCHING_RULE";
+               public const System.String NOT_AN_ATTRIBUTE = "NOT_AN_ATTRIBUTE";
+               public const System.String UNEQUAL_LENGTHS = "UNEQUAL_LENGTHS";
+               public const System.String IMPROPER_REFERRAL = "IMPROPER_REFERRAL";
+               public const System.String NOT_IMPLEMENTED = "NOT_IMPLEMENTED";
+               public const System.String NO_MEMORY = "NO_MEMORY";
+               public const System.String SERVER_SHUTDOWN_REQ = "SERVER_SHUTDOWN_REQ";
+               public const System.String INVALID_ADDRESS = "INVALID_ADDRESS";
+               public const System.String UNKNOWN_RESULT = "UNKNOWN_RESULT";
+               public const System.String OUTSTANDING_OPERATIONS = "OUTSTANDING_OPERATIONS";
+               public const System.String WRONG_FACTORY = "WRONG_FACTORY";
+               public const System.String NO_TLS_FACTORY = "NO_TLS_FACTORY";
+               public const System.String NO_STARTTLS = "NO_STARTTLS";
+               public const System.String STOPTLS_ERROR = "STOPTLS_ERROR";
+               public const System.String MULTIPLE_SCHEMA = "MULTIPLE_SCHEMA";
+               public const System.String NO_SCHEMA = "NO_SCHEMA";
+               public const System.String READ_MULTIPLE = "READ_MULTIPLE";
+               public const System.String CANNOT_BIND = "CANNOT_BIND";
+               
+               //End constants
+               
+               internal static readonly System.Object[][] contents = {new System.Object[]{"TOSTRING", "{0}: {1} ({2}) {3}"}, new System.Object[]{"SERVER_MSG", "{0}: Server Message: {1}"}, new System.Object[]{"MATCHED_DN", "{0}: Matched DN: {1}"}, new System.Object[]{"FAILED_REFERRAL", "{0}: Failed Referral: {1}"}, new System.Object[]{"REFERRAL_ITEM", "{0}: Referral: {1}"}, new System.Object[]{"CONNECTION_ERROR", "Unable to connect to server {0}:{1}"}, new System.Object[]{"CONNECTION_IMPOSSIBLE", "Unable to reconnect to server, application has never called connect()"}, new System.Object[]{"CONNECTION_WAIT", "Connection lost waiting for results from {0}:{1}"}, new System.Object[]{"CONNECTION_FINALIZED", "Connection closed by the application finalizing the object"}, new System.Object[]{"CONNECTION_CLOSED", "Connection closed by the application disconnecting"}, new System.Object[]{"CONNECTION_READER", "Reader thread terminated"}, new System.Object[]{"DUP_ERROR", "RfcLdapMessage: Cannot duplicate message built from the input stream"}, new System.Object[]{"REFERENCE_ERROR", "Error attempting to follow a search continuation reference"}, new System.Object[]{"REFERRAL_ERROR", "Error attempting to follow a referral"}, new System.Object[]{"REFERRAL_LOCAL", "LdapSearchResults.{0}(): No entry found & request is not complete"}, new System.Object[]{"REFERRAL_SEND", "Error sending request to referred server"}, new System.Object[]{"REFERENCE_NOFOLLOW", "Search result reference received, and referral following is off"}, new System.Object[]{"REFERRAL_BIND", "LdapBind.bind() function returned null"}, new System.Object[]{"REFERRAL_BIND_MATCH", "Could not match LdapBind.bind() connection with Server Referral URL list"}, new System.Object[]{"NO_DUP_REQUEST", "Cannot duplicate message to follow referral for {0} request, not allowed"}, new System.Object[]{"SERVER_CONNECT_ERROR", "Error connecting to server {0} while attempting to follow a referral"}, new System.Object[]{"NO_SUP_PROPERTY", "Requested property is not supported."}, new 
+                       System.Object[]{"ENTRY_PARAM_ERROR", "Invalid Entry parameter"}, new System.Object[]{"DN_PARAM_ERROR", "Invalid DN parameter"}, new System.Object[]{"RDN_PARAM_ERROR", "Invalid DN or RDN parameter"}, new System.Object[]{"OP_PARAM_ERROR", "Invalid extended operation parameter, no OID specified"}, new System.Object[]{"PARAM_ERROR", "Invalid parameter"}, new System.Object[]{"DECODING_ERROR", "Error Decoding responseValue"}, new System.Object[]{"ENCODING_ERROR", "Encoding Error"}, new System.Object[]{"IO_EXCEPTION", "I/O Exception on host {0}, port {1}"}, new System.Object[]{"INVALID_ESCAPE", "Invalid value in escape sequence \"{0}\""}, new System.Object[]{"SHORT_ESCAPE", "Incomplete escape sequence"}, new System.Object[]{"UNEXPECTED_END", "Unexpected end of filter"}, new System.Object[]{"MISSING_LEFT_PAREN", "Unmatched parentheses, left parenthesis missing"}, new System.Object[]{"NO_OPTION", "Semicolon present, but no option specified"}, new System.Object[]{"MISSING_RIGHT_PAREN", "Unmatched parentheses, right parenthesis missing"}, new System.Object[]{"EXPECTING_RIGHT_PAREN", "Expecting right parenthesis, found \"{0}\""}, new System.Object[]{"EXPECTING_LEFT_PAREN", "Expecting left parenthesis, found \"{0}\""}, new System.Object[]{"NO_ATTRIBUTE_NAME", "Missing attribute description"}, new System.Object[]{"NO_DN_NOR_MATCHING_RULE", "DN and matching rule not specified"}, new System.Object[]{"NO_MATCHING_RULE", "Missing matching rule"}, new System.Object[]{"INVALID_FILTER_COMPARISON", "Invalid comparison operator"}, new System.Object[]{"INVALID_CHAR_IN_FILTER", "The invalid character \"{0}\" needs to be escaped as \"{1}\""}, new System.Object[]{"INVALID_ESC_IN_DESCR", "Escape sequence not allowed in attribute description"}, new System.Object[]{"INVALID_CHAR_IN_DESCR", "Invalid character \"{0}\" in attribute description"}, new System.Object[]{"NOT_AN_ATTRIBUTE", "Schema element is not an LdapAttributeSchema object"}, new System.Object[]{"UNEQUAL_LENGTHS", 
+                       "Length of attribute Name array does not equal length of Flags array"}, new System.Object[]{"IMPROPER_REFERRAL", "Referral not supported for command {0}"}, new System.Object[]{"NOT_IMPLEMENTED", "Method LdapConnection.startTLS not implemented"}, new System.Object[]{"NO_MEMORY", "All results could not be stored in memory, sort failed"}, new System.Object[]{"SERVER_SHUTDOWN_REQ", "Received unsolicited notification from server {0}:{1} to shutdown"}, new System.Object[]{"INVALID_ADDRESS", "Invalid syntax for address with port; {0}"}, new System.Object[]{"UNKNOWN_RESULT", "Unknown Ldap result code {0}"}, new System.Object[]{"OUTSTANDING_OPERATIONS", "Cannot start or stop TLS because outstanding Ldap operations exist on this connection"}, new System.Object[]{"WRONG_FACTORY", "StartTLS cannot use the set socket factory because it does not implement LdapTLSSocketFactory"}, new System.Object[]{"NO_TLS_FACTORY", "StartTLS failed because no LdapTLSSocketFactory has been set for this Connection"}, new System.Object[]{"NO_STARTTLS", "An attempt to stopTLS on a connection where startTLS had not been called"}, new System.Object[]{"STOPTLS_ERROR", "Error stopping TLS: Error getting input & output streams from the original socket"}, new System.Object[]{"MULTIPLE_SCHEMA", "Multiple schema found when reading the subschemaSubentry for {0}"}, new System.Object[]{"NO_SCHEMA", "No schema found when reading the subschemaSubentry for {0}"}, new System.Object[]{"READ_MULTIPLE", "Read response is ambiguous, multiple entries returned"}, new System.Object[]{"CANNOT_BIND", "Cannot bind. Use PoolManager.getBoundConnection()"}};
+       } //End ExceptionMessages
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExtResponseFactory.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ExtResponseFactory.cs
new file mode 100755 (executable)
index 0000000..dfd668d
--- /dev/null
@@ -0,0 +1,117 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ExtResponseFactory.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+using Novell.Directory.Ldap;
+using Novell.Directory.Ldap.Extensions;
+using Novell.Directory.Ldap.Rfc2251;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       /// <summary> 
+       /// Takes an LdapExtendedResponse and returns an object
+       /// (that implements the base class ParsedExtendedResponse)
+       /// based on the OID.
+       /// 
+       /// <p>You can then call methods defined in the child
+       /// class to parse the contents of the response.  The methods available
+       /// depend on the child class. All child classes inherit from the
+       /// ParsedExtendedResponse.
+       /// 
+       /// </summary>
+       public class ExtResponseFactory
+       {
+               
+               /// <summary> Used to Convert an RfcLdapMessage object to the appropriate
+               /// LdapExtendedResponse object depending on the operation being performed.
+               /// 
+               /// </summary>
+               /// <param name="inResponse">  The LdapExtendedReponse object as returned by the
+               /// extendedOperation method in the LdapConnection object.
+               /// <br><br>
+               /// </param>
+               /// <returns> An object of base class LdapExtendedResponse.  The actual child
+               /// class of this returned object depends on the operation being
+               /// performed.
+               /// 
+               /// </returns>
+               /// <exception cref=""> LdapException A general exception which includes an error message
+               /// and an Ldap error code.
+               /// </exception>
+               
+               static public LdapExtendedResponse convertToExtendedResponse(RfcLdapMessage inResponse)
+               {
+                       
+                       LdapExtendedResponse tempResponse = new LdapExtendedResponse(inResponse);
+                       
+                       // Get the oid stored in the Extended response
+                       System.String inOID = tempResponse.ID;
+                       
+                       if ((System.Object) inOID == null)
+                               return tempResponse;
+                       // Is this an OID we support, if yes then build the
+                       // detailed LdapExtendedResponse object
+                       try
+                       {
+                               if (inOID.Equals(ReplicationConstants.NAMING_CONTEXT_COUNT_RES))
+                               {
+                                       return new PartitionEntryCountResponse(inResponse);
+                               }
+                               if (inOID.Equals(ReplicationConstants.GET_IDENTITY_NAME_RES))
+                               {
+                                       return new GetBindDNResponse(inResponse);
+                               }
+                               if (inOID.Equals(ReplicationConstants.GET_EFFECTIVE_PRIVILEGES_RES))
+                               {
+                                       return new GetEffectivePrivilegesResponse(inResponse);
+                               }
+                               if (inOID.Equals(ReplicationConstants.GET_REPLICA_INFO_RES))
+                               {
+                                       return new GetReplicaInfoResponse(inResponse);
+                               }
+                               if (inOID.Equals(ReplicationConstants.LIST_REPLICAS_RES))
+                               {
+                                       return new ListReplicasResponse(inResponse);
+                               }
+                               if (inOID.Equals(ReplicationConstants.GET_REPLICATION_FILTER_RES))
+                               {
+                                       return new GetReplicationFilterResponse(inResponse);
+                               }
+                               else
+                                       return tempResponse;
+                       }
+                       catch (System.IO.IOException ioe)
+                       {
+                               throw new LdapException(ExceptionMessages.DECODING_ERROR, LdapException.DECODING_ERROR, (System.String) null);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RDN.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RDN.cs
new file mode 100755 (executable)
index 0000000..b3e780f
--- /dev/null
@@ -0,0 +1,315 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.RDN.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> <P>A RDN encapsulates a single object's name of a Distinguished Name(DN).
+       /// The object name represented by this class contains no context.  Thus a
+       /// Relative Distinguished Name (RDN) could be relative to anywhere in the
+       /// Directories tree.</P>
+       /// 
+       /// <P>For example, of following DN, 'cn=admin, ou=marketing, o=corporation', all
+       /// possible RDNs are 'cn=admin', 'ou=marketing', and 'o=corporation'.</P>
+       /// 
+       /// <P>Multivalued attributes are encapsulated in this class.  For example the
+       /// following could be represented by an RDN: 'cn=john + l=US', or
+       /// 'cn=juan + l=ES' </P>
+       /// 
+       /// </summary>
+       /// <seealso cref="DN">
+       /// </seealso>
+       
+       
+       public class RDN:System.Object
+       {
+               /// <summary> Returns the actually Raw String before Normalization
+               /// 
+               /// </summary>
+               /// <returns> The raw string
+               /// </returns>
+               virtual protected internal System.String RawValue
+               {
+                       get
+                       {
+                               return rawValue;
+                       }
+                       
+               }
+               /// <summary> Returns the type of this RDN.  This method assumes that only one value
+               /// is used, If multivalues attributes are used only the first Type is
+               /// returned.  Use GetTypes.
+               /// </summary>
+               /// <returns> Type of attribute
+               /// </returns>
+               virtual public System.String Type
+               {
+                       get
+                       {
+                               return (System.String) types[0];
+                       }
+                       
+               }
+               /// <summary> Returns all the types for this RDN.</summary>
+               /// <returns> list of types
+               /// </returns>
+               virtual public System.String[] Types
+               {
+                       get
+                       {
+                               System.String[] toReturn = new System.String[types.Count];
+                               for (int i = 0; i < types.Count; i++)
+                                       toReturn[i] = ((System.String) types[i]);
+                               return toReturn;
+                       }
+                       
+               }
+               /// <summary> Returns the values of this RDN.  If multivalues attributes are used only
+               /// the first Type is returned.  Use GetTypes.
+               /// 
+               /// </summary>
+               /// <returns> Type of attribute
+               /// </returns>
+               virtual public System.String Value
+               {
+                       get
+                       {
+                               return (System.String) values[0];
+                       }
+                       
+               }
+               /// <summary> Returns all the types for this RDN.</summary>
+               /// <returns> list of types
+               /// </returns>
+               virtual public System.String[] Values
+               {
+                       get
+                       {
+                               System.String[] toReturn = new System.String[values.Count];
+                               for (int i = 0; i < values.Count; i++)
+                                       toReturn[i] = ((System.String) values[i]);
+                               return toReturn;
+                       }
+                       
+               }
+               /// <summary> Determines if this RDN is multivalued or not</summary>
+               /// <returns> true if this RDN is multivalued
+               /// </returns>
+               virtual public bool Multivalued
+               {
+                       get
+                       {
+                               return (values.Count > 1)?true:false;
+                       }
+                       
+               }
+               private System.Collections.ArrayList types; //list of Type strings
+               private System.Collections.ArrayList values; //list of Value strings
+               private System.String rawValue; //the unnormalized value
+               
+               /// <summary> Creates an RDN object from the DN component specified in the string RDN
+               /// 
+               /// </summary>
+               /// <param name="rdn">the DN component
+               /// </param>
+               public RDN(System.String rdn)
+               {
+                       rawValue = rdn;
+                       DN dn = new DN(rdn);
+                       System.Collections.ArrayList rdns = dn.RDNs;
+                       //there should only be one rdn
+                       if (rdns.Count != 1)
+                               throw new System.ArgumentException("Invalid RDN: see API " + "documentation");
+                       RDN thisRDN = (RDN) (rdns[0]);
+                       this.types = thisRDN.types;
+                       this.values = thisRDN.values;
+                       this.rawValue = thisRDN.rawValue;
+                       return ;
+               }
+               
+               public RDN()
+               {
+                       types = new System.Collections.ArrayList();
+                       values = new System.Collections.ArrayList();
+                       rawValue = "";
+                       return ;
+               }
+               
+               /// <summary> Compares the RDN to the rdn passed.  Note: If an there exist any
+               /// mulivalues in one RDN they must all be present in the other.
+               /// 
+               /// </summary>
+               /// <param name="rdn">the RDN to compare to
+               /// 
+               /// @throws IllegalArgumentException if the application compares a name
+               /// with an OID.
+               /// </param>
+               [CLSCompliantAttribute(false)]
+               public virtual bool equals(RDN rdn)
+               {
+                       if (this.values.Count != rdn.values.Count)
+                       {
+                               return false;
+                       }
+                       int j, i;
+                       for (i = 0; i < this.values.Count; i++)
+                       {
+                               //verify that the current value and type exists in the other list
+                               j = 0;
+                               //May need a more intellegent compare
+                               while (j < values.Count && (!((System.String) this.values[i]).ToUpper().Equals(((System.String) rdn.values[j]).ToUpper()) || !equalAttrType((System.String) this.types[i], (System.String) rdn.types[j])))
+                               {
+                                       j++;
+                               }
+                               if (j >= rdn.values.Count)
+                               //couldn't find first value
+                                       return false;
+                       }
+                       return true;
+               }
+               
+               /// <summary> Internal function used by equal to compare Attribute types.  Because
+               /// attribute types could either be an OID or a name.  There needs to be a
+               /// Translation mechanism.  This function will absract this functionality.
+               /// 
+               /// Currently if types differ (Oid and number) then UnsupportedOperation is
+               /// thrown, either one or the other must used.  In the future an OID to name
+               /// translation can be used.
+               /// 
+               /// 
+               /// </summary>
+               private bool equalAttrType(System.String attr1, System.String attr2)
+               {
+                       if (System.Char.IsDigit(attr1[0]) ^ System.Char.IsDigit(attr2[0]))
+                       //isDigit tests if it is an OID
+                               throw new System.ArgumentException("OID numbers are not " + "currently compared to attribute names");
+                       
+                       return attr1.ToUpper().Equals(attr2.ToUpper());
+               }
+               
+               /// <summary> Adds another value to the RDN.  Only one attribute type is allowed for
+               /// the RDN.
+               /// </summary>
+               /// <param name="attrType">Attribute type, could be an OID or String
+               /// </param>
+               /// <param name="attrValue">Attribute Value, must be normalized and escaped
+               /// </param>
+               /// <param name="rawValue">or text before normalization, can be Null
+               /// </param>
+               public virtual void  add(System.String attrType, System.String attrValue, System.String rawValue)
+               {
+                       types.Add(attrType);
+                       values.Add(attrValue);
+                       this.rawValue += rawValue;
+               }
+               
+               /// <summary> Creates a string that represents this RDN, according to RFC 2253
+               /// 
+               /// </summary>
+               /// <returns> An RDN string
+               /// </returns>
+               public override System.String ToString()
+               {
+                       return toString(false);
+               }
+               
+               /// <summary> Creates a string that represents this RDN.
+               /// 
+               /// If noTypes is true then Atribute types will be ommited.
+               /// 
+               /// </summary>
+               /// <param name="noTypes">true if attribute types will be omitted.
+               /// 
+               /// </param>
+               /// <returns> An RDN string
+               /// </returns>
+               [CLSCompliantAttribute(false)]
+               public virtual System.String toString(bool noTypes)
+               {
+                       int length = types.Count;
+                       System.String toReturn = "";
+                       if (length < 1)
+                               return null;
+                       if (!noTypes)
+                       {
+                               toReturn = types[0] + "=";
+                       }
+                       toReturn += values[0];
+                       
+                       for (int i = 1; i < length; i++)
+                       {
+                               toReturn += "+";
+                               if (!noTypes)
+                               {
+                                       toReturn += (types[i] + "=");
+                               }
+                               toReturn += values[i];
+                       }
+                       return toReturn;
+               }
+               
+               /// <summary> Returns each multivalued name in the current RDN as an array of Strings.
+               /// 
+               /// </summary>
+               /// <param name="noTypes">Specifies whether Attribute types are included. The attribute
+               /// type names will be ommitted if the parameter noTypes is true.
+               /// 
+               /// </param>
+               /// <returns> List of multivalued Attributes
+               /// </returns>
+               public virtual System.String[] explodeRDN(bool noTypes)
+               {
+                       int length = types.Count;
+                       if (length < 1)
+                               return null;
+                       System.String[] toReturn = new System.String[types.Count];
+                       
+                       if (!noTypes)
+                       {
+                               toReturn[0] = types[0] + "=";
+                       }
+                       toReturn[0] += values[0];
+                       
+                       for (int i = 1; i < length; i++)
+                       {
+                               if (!noTypes)
+                               {
+                                       toReturn[i] += (types[i] + "=");
+                               }
+                               toReturn[i] += values[i];
+                       }
+                       
+                       return toReturn;
+               }
+       } //end class RDN
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ReferralInfo.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ReferralInfo.cs
new file mode 100755 (executable)
index 0000000..4cf83a6
--- /dev/null
@@ -0,0 +1,104 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ReferralInfo.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+using Novell.Directory.Ldap;
+using LdapUrl = Novell.Directory.Ldap.LdapUrl;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> This class encapsulates the combination of LdapReferral URL and
+       /// the connection opened to service this URL
+       /// </summary>
+       public class ReferralInfo
+       {
+               /// <summary>Returns the referral URL
+               /// 
+               /// </summary>
+               /// <returns> the Referral URL
+               /// </returns>
+               virtual public LdapUrl ReferralUrl
+               {
+                       get
+                       {
+                               return referralUrl;
+                       }
+                       
+               }
+               /// <summary>Returns the referral Connection
+               /// 
+               /// </summary>
+               /// <returns> the Referral Connection
+               /// </returns>
+               virtual public LdapConnection ReferralConnection
+               {
+                       get
+                       {
+                               return conn;
+                       }
+                       
+               }
+               /// <summary>Returns the referral list
+               /// 
+               /// </summary>
+               /// <returns> the Referral list
+               /// </returns>
+               virtual public System.String[] ReferralList
+               {
+                       get
+                       {
+                               return referralList;
+                       }
+                       
+               }
+//             private DirectoryEntry conn;
+               private LdapConnection conn;
+               private LdapUrl referralUrl;
+               private System.String[] referralList;
+               
+               /// <summary> Construct the ReferralInfo class
+               /// 
+               /// </summary>
+               /// <param name="lc">The DirectoryEntry opened to process this referral
+               /// 
+               /// </param>
+               /// <param name="refUrl">The URL string associated with this connection
+               /// </param>
+               public ReferralInfo(LdapConnection lc, System.String[] refList, LdapUrl refUrl)
+               {
+                       conn = lc;
+                       referralUrl = refUrl;
+                       referralList = refList;
+                       return ;
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResourcesHandler.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResourcesHandler.cs
new file mode 100755 (executable)
index 0000000..b552576
--- /dev/null
@@ -0,0 +1,217 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ResourcesHandler.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary>  A utility class to get strings from the ExceptionMessages and
+       /// ResultCodeMessages resources.
+       /// </summary>
+       public class ResourcesHandler
+       {
+               // Cannot create an instance of this class
+               private ResourcesHandler()
+               {
+                       return ;
+               }
+               
+               /*
+               *  Initialized when the first result string is requested
+               */
+               private static System.Resources.ResourceManager defaultResultCodes = null;
+               
+               /// <summary>  Initialized when the first Exception message string is requested</summary>
+               private static System.Resources.ResourceManager defaultMessages = null;
+               
+               
+               /// <summary> Package where resources are found</summary>
+               private static System.String pkg = "Novell.Directory.Ldap.Utilclass.";
+               
+               /// <summary> The default Locale</summary>
+               private static System.Globalization.CultureInfo defaultLocale;
+               
+               /// <summary> Returns a string using the MessageOrKey as a key into
+               /// ExceptionMessages or, if the Key does not exist, returns the
+               /// string messageOrKey.  In addition it formats the arguments into the message
+               /// according to MessageFormat.
+               /// 
+               /// </summary>
+               /// <param name="messageOrKey">   Key string for the resource.
+               /// <br><br>
+               /// </param>
+               /// <param name="">arguments
+               /// 
+               /// </param>
+               /// <returns> the text for the message specified by the MessageKey or the Key
+               /// if it there is no message for that key.
+               /// </returns>
+               public static System.String getMessage(System.String messageOrKey, System.Object[] arguments)
+               {
+                       return getMessage(messageOrKey, arguments, null);
+               }
+               
+               /// <summary> Returns the message stored in the ExceptionMessages resource for the
+               /// specified locale using messageOrKey and argments passed into the
+               /// constructor.  If no string exists in the resource then this returns
+               /// the string stored in message.  (This method is identical to
+               /// getLdapErrorMessage(Locale locale).)
+               /// 
+               /// </summary>
+               /// <param name="messageOrKey">   Key string for the resource.
+               /// <br><br>
+               /// </param>
+               /// <param name="">arguments
+               /// <br><br>
+               /// </param>
+               /// <param name="locale">         The Locale that should be used to pull message
+               /// strings out of ExceptionMessages.
+               /// 
+               /// </param>
+               /// <returns> the text for the message specified by the MessageKey or the Key
+               /// if it there is no message for that key.
+               /// </returns>
+               public static System.String getMessage(System.String messageOrKey, System.Object[] arguments, System.Globalization.CultureInfo locale)
+               {
+                       System.String pattern;
+                       System.Resources.ResourceManager messages = null;
+                       
+                       if ((System.Object) messageOrKey == null)
+                       {
+                               messageOrKey = "";
+                       }
+                       
+                       try
+                       {
+                               if ((locale == null) || defaultLocale.Equals(locale))
+                               {
+                                       locale = defaultLocale;
+                                       // Default Locale
+                                       if (defaultMessages == null)
+                                       {
+                                               System.Threading.Thread.CurrentThread.CurrentUICulture = defaultLocale;
+                                               defaultMessages = System.Resources.ResourceManager.CreateFileBasedResourceManager(pkg + "ExceptionMessages", "", null);
+                                       }
+                                       messages = defaultMessages;
+                               }
+                               else
+                               {
+                                       System.Threading.Thread.CurrentThread.CurrentUICulture = locale;
+                                       messages = System.Resources.ResourceManager.CreateFileBasedResourceManager(pkg + "ExceptionMessages", "", null);
+                               }
+                               pattern = messages.GetString(messageOrKey);
+                       }
+                       catch (System.Resources.MissingManifestResourceException mre)
+                       {
+                               pattern = messageOrKey;
+                       }
+                       
+                       // Format the message if arguments were passed
+                       if (arguments != null)
+                       {
+//                             MessageFormat mf = new MessageFormat(pattern);
+                               pattern=System.String.Format(locale,pattern,arguments);
+//                             mf.setLocale(locale);
+                               //this needs to be reset with the new local - i18n defect in java
+//                             mf.applyPattern(pattern);
+//                             pattern = mf.format(arguments);
+                       }
+                       return pattern;
+               }
+               
+               /// <summary> Returns a string representing the Ldap result code from the 
+               /// default ResultCodeMessages resource.
+               /// 
+               /// </summary>
+               /// <param name="code">   the result code 
+               /// <br><br>
+               /// </param>
+               /// <returns>        the String representing the result code.
+               /// </returns>
+               public static System.String getResultString(int code)
+               {
+                       return getResultString(code, null);
+               }
+               
+               /// <summary> Returns a string representing the Ldap result code.  The message
+               /// is obtained from the locale specific ResultCodeMessage resource.
+               /// 
+               /// </summary>
+               /// <param name="code">   the result code 
+               /// <br><br>
+               /// </param>
+               /// <param name="locale">         The Locale that should be used to pull message
+               /// strings out of ResultMessages.
+               /// 
+               /// </param>
+               /// <returns>        the String representing the result code.
+               /// </returns>
+               public static System.String getResultString(int code, System.Globalization.CultureInfo locale)
+               {
+                       System.Resources.ResourceManager messages;
+                       System.String result;
+                       try
+                       {
+                               if ((locale == null) || defaultLocale.Equals(locale))
+                               {
+                                       locale = defaultLocale;
+                                       // Default Locale
+                                       if (defaultResultCodes == null)
+                                       {
+                                               System.Threading.Thread.CurrentThread.CurrentUICulture = defaultLocale;
+                                               defaultResultCodes = System.Resources.ResourceManager.CreateFileBasedResourceManager(pkg + "ResultCodeMessages", "", null);
+                                       }
+                                       messages = defaultResultCodes;
+//                                     Console.WriteLine("Test Message.." + pkg + "ResultCodeMessages" );
+                               }
+                               else
+                               {
+                                       System.Threading.Thread.CurrentThread.CurrentUICulture = locale;
+                                       messages = System.Resources.ResourceManager.CreateFileBasedResourceManager(pkg + "ResultCodeMessages", "", null);
+                               }
+//                             result = messages.GetString(System.Convert.ToString(code));
+                               result = Convert.ToString(code);
+                       }
+                       catch (System.Resources.MissingManifestResourceException mre)
+                       {
+                               result = getMessage(ExceptionMessages.UNKNOWN_RESULT, new System.Object[]{code}, locale);
+                       }
+                       return result;
+               }
+               static ResourcesHandler()
+               {
+//                     defaultLocale = System.Globalization.CultureInfo.CurrentCulture;
+                       defaultLocale=new System.Globalization.CultureInfo("en-US");
+
+               }
+       } //end class ResourcesHandler
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RespControlVector.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/RespControlVector.cs
new file mode 100755 (executable)
index 0000000..1732bd4
--- /dev/null
@@ -0,0 +1,124 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.RespControlVector.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> The <code>MessageVector</code> class implements extends the
+       /// existing Vector class so that it can be used to maintain a
+       /// list of currently registered control responses.
+       /// </summary>
+       public class RespControlVector:System.Collections.ArrayList
+       {
+               public RespControlVector(int cap, int incr):base(cap)
+               {
+                       return ;
+               }
+               
+               /// <summary>Inner class defined to create a temporary object to encapsulate
+               /// all registration information about a response control.  This class
+               /// cannot be used outside this class 
+               /// </summary>
+               private class RegisteredControl
+               {
+                       private void  InitBlock(RespControlVector enclosingInstance)
+                       {
+                               this.enclosingInstance = enclosingInstance;
+                       }
+                       private RespControlVector enclosingInstance;
+                       public RespControlVector Enclosing_Instance
+                       {
+                               get
+                               {
+                                       return enclosingInstance;
+                               }
+                               
+                       }
+                       public System.String myOID;
+                       public System.Type myClass;
+                       
+                       public RegisteredControl(RespControlVector enclosingInstance, System.String oid, System.Type controlClass)
+                       {
+                               InitBlock(enclosingInstance);
+                               myOID = oid;
+                               myClass = controlClass;
+                       }
+               }
+               
+               /* Adds a control to the current list of registered response controls.
+               *
+               */
+               public void  registerResponseControl(System.String oid, System.Type controlClass)
+               {
+                       lock (this)
+                       {
+                               
+                               Add(new RegisteredControl(this, oid, controlClass));
+                       }
+               }
+               
+               /* Searches the list of registered controls for a mathcing control.  We
+               * search using the OID string.  If a match is found we return the
+               * Class name that was provided to us on registration.
+               */
+               public System.Type findResponseControl(System.String searchOID)
+               {
+                       lock (this)
+                       {
+                               RegisteredControl ctl = null;
+                               
+                               /* loop through the contents of the vector */
+                               for (int i = 0; i < Count; i++)
+                               {
+                                       
+                                       /* Get next registered control */
+                                       if ((ctl = (RegisteredControl) ToArray()[i]) == null)
+                                       {
+                                               throw new System.FieldAccessException();
+                                       }
+                                       
+                                       /* Does the stored OID match with whate we are looking for */
+                                       if (ctl.myOID.CompareTo(searchOID) == 0)
+                                       {
+                                               
+                                               
+                                               /* Return the class name if we have match */
+                                               return ctl.myClass;
+                                       }
+                               }
+                               /* The requested control does not have a registered response class */
+                               return null;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResultCodeMessages.cs b/mcs/class/Novell.Directory.Ldap/Novell.Directory.Ldap.Utilclass/ResultCodeMessages.cs
new file mode 100755 (executable)
index 0000000..0db59a4
--- /dev/null
@@ -0,0 +1,50 @@
+/******************************************************************************
+* The MIT License
+* Copyright (c) 2003 Novell Inc.  www.novell.com
+* 
+* Permission is hereby granted, free of charge, to any person obtaining  a copy
+* of this software and associated documentation files (the Software), to deal
+* in the Software without restriction, including  without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+* copies of the Software, and to  permit persons to whom the Software is 
+* furnished to do so, subject to the following conditions:
+* 
+* The above copyright notice and this permission notice shall be included in 
+* all copies or substantial portions of the Software.
+* 
+* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*******************************************************************************/
+//
+// Novell.Directory.Ldap.Utilclass.ResultCodeMessages.cs
+//
+// Author:
+//   Sunil Kumar (Sunilk@novell.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+
+namespace Novell.Directory.Ldap.Utilclass
+{
+       
+       /// <summary> This class contains strings corresponding to Ldap Result Codes.
+       /// The resources are accessed by the String representation of the result code.
+       /// </summary>
+       
+       public class ResultCodeMessages:System.Resources.ResourceManager
+       {
+               public System.Object[][] getContents()
+               {
+                       return contents;
+               }
+               internal static readonly System.Object[][] contents = {new System.Object[]{"0", "Success"}, new System.Object[]{"1", "Operations Error"}, new System.Object[]{"2", "Protocol Error"}, new System.Object[]{"3", "Timelimit Exceeded"}, new System.Object[]{"4", "Sizelimit Exceeded"}, new System.Object[]{"5", "Compare False"}, new System.Object[]{"6", "Compare True"}, new System.Object[]{"7", "Authentication Method Not Supported"}, new System.Object[]{"8", "Strong Authentication Required"}, new System.Object[]{"9", "Partial Results"}, new System.Object[]{"10", "Referral"}, new System.Object[]{"11", "Administrative Limit Exceeded"}, new System.Object[]{"12", "Unavailable Critical Extension"}, new System.Object[]{"13", "Confidentiality Required"}, new System.Object[]{"14", "SASL Bind In Progress"}, new System.Object[]{"16", "No Such Attribute"}, new System.Object[]{"17", "Undefined Attribute Type"}, new System.Object[]{"18", "Inappropriate Matching"}, new System.Object[]{"19", "Constraint Violation"}, new System.Object[]{"20", "Attribute Or Value Exists"}, new System.Object[]{"21", "Invalid Attribute Syntax"}, new System.Object[]{"32", "No Such Object"}, new System.Object[]{"33", "Alias Problem"}, new System.Object[]{"34", "Invalid DN Syntax"}, new System.Object[]{"35", "Is Leaf"}, new System.Object[]{"36", "Alias Dereferencing Problem"}, new System.Object[]{"48", "Inappropriate Authentication"}, new System.Object[]{"49", "Invalid Credentials"}, new System.Object[]{"50", "Insufficient Access Rights"}, new System.Object[]{"51", "Busy"}, new System.Object[]{"52", "Unavailable"}, new System.Object[]{"53", "Unwilling To Perform"}, new System.Object[]{"54", "Loop Detect"}, new System.Object[]{"64", "Naming Violation"}, new System.Object[]{"65", "Object Class Violation"}, new System.Object[]{"66", "Not Allowed On Non-leaf"}, new System.Object[]{"67", "Not Allowed On RDN"}, new System.Object[]{"68", "Entry Already Exists"}, new System.Object[]{"69", "Object Class Modifications Prohibited"}, new System.Object[]{"71", 
+                       "Affects Multiple DSAs"}, new System.Object[]{"80", "Other"}, new System.Object[]{"81", "Server Down"}, new System.Object[]{"82", "Local Error"}, new System.Object[]{"83", "Encoding Error"}, new System.Object[]{"84", "Decoding Error"}, new System.Object[]{"85", "Ldap Timeout"}, new System.Object[]{"86", "Authentication Unknown"}, new System.Object[]{"87", "Filter Error"}, new System.Object[]{"88", "User Cancelled"}, new System.Object[]{"89", "Parameter Error"}, new System.Object[]{"90", "No Memory"}, new System.Object[]{"91", "Connect Error"}, new System.Object[]{"92", "Ldap Not Supported"}, new System.Object[]{"93", "Control Not Found"}, new System.Object[]{"94", "No Results Returned"}, new System.Object[]{"95", "More Results To Return"}, new System.Object[]{"96", "Client Loop"}, new System.Object[]{"97", "Referral Limit Exceeded"}, new System.Object[]{"112", "TLS not supported"}};
+       } //End ResultCodeMessages
+}