This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / System.DirectoryServices / System.DirectoryServices / DirectoryEntry.cs
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc.,  www.novell.com
4
5 * Permission is hereby granted, free of charge, to any person obtaining  a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including  without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
9 * copies of the Software, and to  permit persons to whom the Software is 
10 * furnished to do so, subject to the following conditions:
11
12 * The above copyright notice and this permission notice shall be included in 
13 * all copies or substantial portions of the Software.
14
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
23
24 //
25 // System.DirectoryServices.DirectoryEntry.cs
26 //
27 // Authors:
28 //   Sunil Kumar (sunilk@novell.com)
29 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
30 //
31 // (C)  Novell Inc.
32 //
33
34 using System.ComponentModel;
35 using Novell.Directory.Ldap;
36 using Novell.Directory.Ldap.Utilclass;
37 using System.Globalization;
38 using System.DirectoryServices.Design;
39
40 namespace System.DirectoryServices
41 {
42         
43         /// <summary>
44         ///Encapsulates a node or object in the Ldap Directory hierarchy.
45         /// </summary>
46         [TypeConverter (typeof (DirectoryEntryConverter))]
47         public class DirectoryEntry : Component 
48         {
49                 
50                 private LdapConnection _conn = null;
51                 private AuthenticationTypes _AuthenticationType=AuthenticationTypes.None;
52                 private DirectoryEntries _Children;
53                 private string _Fdn = null;
54                 private string _Path="";
55                 private string _Name=null;
56                 private DirectoryEntry _Parent=null;
57                 private string _Username="";
58                 private string _Password="";
59                 //private string _Nativeguid;
60                 private PropertyCollection _Properties = null;
61                 private string _SchemaClassName=null;
62                 private bool _Nflag = false;
63                 private bool _disposed;
64
65                 /// <summary>
66                 /// Returns entry's Fully distinguished name.
67                 /// </summary>
68                 internal string Fdn
69                 {
70                         get                     {
71                                 if (_Fdn == null)                               {
72                                         LdapUrl lUrl = new LdapUrl(Path);
73                                         string fDn=lUrl.getDN();
74                                         if(fDn != null)
75                                                 _Fdn = fDn;
76                                         else
77                                                 _Fdn="";
78                                 }
79                                 return _Fdn;
80                         }
81                 }
82
83                 /// <summary>
84                 ///  Returns the connection object used to communicate with
85                 /// Ldap server
86                 /// </summary>
87                 internal LdapConnection conn
88                 {
89                         get                     {
90                                 if( _conn == null)
91                                         InitBlock();
92
93                                 return _conn;
94                         }
95                         set                     {
96                                 _conn=value;
97                         }
98                 }
99
100                 /// <summary>
101                 /// Flag to check whether the entry is to be cerated or it already
102                 /// exists.
103                 /// </summary>
104                 internal bool Nflag
105                 {
106                         get                     {
107                                 return _Nflag;
108                         }
109                         set                     {
110                                 _Nflag = value;
111                         }
112                 }
113
114                 /// <summary> Initializes the Connection and other properties.
115                 /// 
116                 /// </summary>
117                 private void InitBlock()
118                 {
119                         try                     {
120                                 _conn= new LdapConnection ();
121                                 LdapUrl lUrl=new LdapUrl (Path);
122                                 _conn.Connect(lUrl.Host,lUrl.Port);
123                                 _conn.Bind(Username,Password);
124                         }
125                         catch(LdapException ex)                 {
126                                 Console.WriteLine("Error:" + ex.LdapErrorMessage);
127                                 throw ex;
128                         }
129                         catch(Exception e)                      {
130                                 Console.WriteLine("Error:" +  e.Message);
131                                 throw e;
132                         }
133                 }
134
135                 /// <summary>
136                 /// Initializes the Entry specific properties e.g entry DN etc.
137                 /// </summary>
138                 void InitEntry()
139                 {
140                         LdapUrl lUrl=new LdapUrl (Path);
141                         if(lUrl.getDN()!=null)                  {
142                                 DN userDn = new DN(lUrl.getDN());
143                                 String[] lRdn = userDn.explodeDN(false);
144                                 _Name = (string)lRdn[0];
145                                 _Parent = new DirectoryEntry(conn);
146                                 LdapUrl cUrl=new LdapUrl(lUrl.Host,lUrl.Port,userDn.Parent.ToString());
147                                 _Parent.Path=cUrl.ToString();
148                         }
149                         else                    {
150                                 _Name=lUrl.Host+":"+lUrl.Port;
151                                 _Parent = new DirectoryEntry(conn);
152                                 _Parent.Path = "Ldap:";
153                         }
154                 }
155
156                 /// <summary>
157                 /// Initializes a new instance of the DirectoryEntry class
158                 /// </summary>
159                 public DirectoryEntry()
160                 {
161                 }
162
163                 /// <summary>
164                 /// Initializes a new instance of the DirectoryEntry class that binds
165                 ///  to the specified native Active Directory object.
166                 /// </summary>
167                 /// <param name="adsObject"> native active directory object</param>
168                 public DirectoryEntry(object adsObject)
169                 {
170                          throw new NotImplementedException();
171                 }
172
173                 /// <summary>
174                 /// Initializes a new instance of the DirectoryEntry class that binds
175                 ///  this instance to the node in Ldap Directory located at the
176                 ///  specified path.
177                 /// </summary>
178                 /// <param name="path"> Path of the entry i.e Ldap URL specifying 
179                 /// entry path</param>
180                 public DirectoryEntry(string path)
181                 {
182                         _Path=path;
183                 }
184
185                 /// <summary>
186                 /// Initializes a new instance of the DirectoryEntry class. The Path,
187                 ///  Username, and Password properties are set to the specified values.
188                 /// </summary>
189                 /// <param name="path">Path of the entry i.e Ldap URL specifying 
190                 /// entry path</param>
191                 /// <param name="username">user name to use when authenticating the client
192                 /// </param>
193                 /// <param name="password">password to use when authenticating the client
194                 /// </param>
195                 public DirectoryEntry(string path,string username,string password)
196                 {
197                         _Path=path;
198                         _Username=username;
199                         _Password=password;
200                 }
201
202                 /// <summary>
203                 /// Initializes a new instance of the DirectoryEntry class. The Path,
204                 ///  Username, and Password properties are set to the specified values.
205                 /// </summary>
206                 /// <param name="path">Path of the entry i.e Ldap URL specifying 
207                 /// entry path</param>
208                 /// <param name="username">user name to use when authenticating the client
209                 /// </param>
210                 /// <param name="password">password to use when authenticating the client
211                 /// </param>
212                 /// <param name="authenticationType"> type of authentication to use</param>
213                 public DirectoryEntry(
214                                 string path,
215                                 string username,
216                                 string password,
217                                 AuthenticationTypes authenticationType)
218                 {
219                         _Path=path;
220                         _Username=username;
221                         _Password=password;
222                         _AuthenticationType=authenticationType;
223                 }
224
225                 /// <summary>
226                 /// Creates the entry object
227                 /// </summary>
228                 /// <param name="lconn">Connection object used to communicate with
229                 /// Ldap server</param>
230                 internal DirectoryEntry(LdapConnection lconn)
231                 {
232                         conn = lconn;
233                 }
234
235                 /// <summary>
236                 /// Returns Type of authentication to use while Binding to Ldap server
237                 /// </summary>
238                 [DSDescription ("Type of authentication to use while Binding to Ldap server")]
239                 [DefaultValue (AuthenticationTypes.None)]
240                 public AuthenticationTypes AuthenticationType 
241                 {
242                         get 
243                         {
244                                 return _AuthenticationType;
245                         }
246                         set 
247                         {
248                                 _AuthenticationType = value;
249                         }
250                 }
251
252                 /// <summary>
253                 /// Gets a DirectoryEntries containing the child entries of this node
254                 ///  in the Ldap Directory hierarchy.
255                 /// </summary>
256                 /// <value>A DirectoryEntries containing the child entries of this node
257                 ///  in the Ldap Directory hierarchy.</value>
258                 ///  <remarks>
259                 ///  The child entries are only the immediate children of this node.
260                 ///  Use this property to find, retrieve, or create a directory entry
261                 ///  in the hierarchy. This property is a collection that, along with 
262                 ///  usual iteration capabilities, provides an Add method through which
263                 ///  you add a node to the collection directly below the parent node
264                 ///  that you are currently bound to. When adding a node to the 
265                 ///  collection, you must specify a name for the new node and the name of 
266                 ///  a schema template that you want to associate with the node. For 
267                 ///  example, you might want to use a schema titled "Computer" to add 
268                 ///  new computers to the hierarchy.
269                 ///  </remarks>
270                 [DSDescription ("Child entries of this node")]
271                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
272                 [Browsable (false)]
273                 public DirectoryEntries Children 
274                 {
275                         get 
276                         {
277                                 _Children = new DirectoryEntries(Path, conn);
278                                 return _Children;
279                         }
280                 }
281
282                 /// <summary>
283                 /// Gets the globally unique identifier (GUID) of the DirectoryEntry
284                 /// </summary>
285                 /// <value>The globally unique identifier of the DirectoryEntry.</value>
286                 /// <remarks>
287                 /// Not implemented yet.                
288                 /// </remarks>
289                 [DSDescription ("A globally unique identifier for this DirectoryEntry")]
290                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
291                 [Browsable (false)]
292                 [MonoTODO]
293                 public Guid Guid 
294                 {
295                         get 
296                         {
297                                 throw new NotImplementedException();
298                         }
299
300                 }
301
302                 /// <summary>
303                 /// Gets the name of the object as named with the underlying directory
304                 ///  service
305                 /// </summary>
306                 /// <value>The name of the object as named with the underlying directory
307                 ///  service</value>
308                 /// <remarks>This name, along with SchemaClassName, distinguishes this
309                 ///  entry from its siblings and must be unique amongst its siblings 
310                 ///  in each instance of DirectoryEntry.</remarks>
311                 [DSDescription ("The name of the object as named with the underlying directory")]
312                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
313                 [Browsable (false)]
314                 public string Name 
315                 {
316                         get                                                             {
317                                 if(_Name==null)                         {
318                                         if(CheckEntry(conn,Path))
319                                                 InitEntry();
320                                         else
321                                                 throw new Exception("There is no such object on the server");
322                                 }
323                                 return _Name;
324                         }
325                 }
326
327                 /// <summary>
328                 /// Gets this entry's parent in the Ldap Directory hierarchy.
329                 /// </summary>
330                 /// <value>This entry's parent in the Active Directory hierarc</value>
331                 [DSDescription ("This entry's parent in the Ldap Directory hierarchy.")]
332                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
333                 [Browsable (false)]
334                 public DirectoryEntry Parent 
335                 {
336                         get                     {
337                                 if(_Parent==null)                               {
338                                         if(CheckEntry(conn,Path))
339                                                 InitEntry();
340                                         else
341                                                 throw new Exception("There is no such object on the server");
342                                 }
343                                 return _Parent;
344                         }
345                 }
346
347                 /// <summary>
348                 /// Gets the globally unique identifier of the DirectoryEntry, as 
349                 /// returned from the provider
350                 /// </summary>
351                 /// <value>
352                 /// The globally unique identifier of the DirectoryEntry, as returned 
353                 /// from the provider.
354                 /// </value>
355                 /// <remarks>
356                 /// Not implemented yet.
357                 /// </remarks>
358                 [DSDescription ("The globally unique identifier of the DirectoryEntry, as returned from the provider")]
359                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
360                 [Browsable (false)]
361                 [MonoTODO]
362                 public string NativeGuid 
363                 {
364                         get                     {
365                                 throw new NotImplementedException();
366                         }
367                 }
368
369                 /// <summary>
370                 /// Gets the native Active Directory Service Interfaces (ADSI) object.
371                 /// </summary>
372                 /// <remarks>
373                 /// Not implemented yet
374                 [DSDescription ("The native Active Directory Service Interfaces (ADSI) object.")]
375                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
376                 [Browsable (false)]
377                 public object NativeObject 
378                 {
379                         [MonoTODO]
380                         get                     {
381                                 throw new NotImplementedException();
382                         }
383                 }
384
385                 /// <summary>
386                 /// Determines if a cache should be used.
387                 /// </summary>
388                 [DSDescription ("Determines if a cache should be used.")]
389                 [DefaultValue (true)]
390                 public bool UsePropertyCache
391                 {
392                         [MonoTODO]
393                         get 
394                         {
395                                 throw new NotImplementedException();
396                         }
397                         [MonoTODO]
398                         set 
399                         {
400                                 throw new NotImplementedException();
401                         }
402                 }
403
404                 /// <summary>
405                 /// Gets or sets the password to use when authenticating the client.
406                 /// </summary>
407                 /// <value>
408                 /// The password to use when authenticating the client.
409                 /// </value>
410                 /// <remarks>
411                 /// You can set the Username and password in order to specify alternate 
412                 /// credentials with which to access the information in Ldap Directory. 
413                 /// Any other DirectoryEntry objects retrieved from this instance (for 
414                 /// example, through Children) are automatically created with the same 
415                 /// alternate credentials.
416                 /// </remarks>
417                 [DSDescription ("The password to use when authenticating the client.")]
418                 [DefaultValue (null)]
419                 [Browsable (false)]
420                 public string Password 
421                 {
422                         get             {
423                                 return _Password;
424                         }
425                         set                     {
426                                 _Password = value;
427                         }
428
429                 }
430
431                 /// <summary>
432                 /// Gets or sets the user name to use when authenticating the client.
433                 /// </summary>
434                 /// <value>
435                 /// The user name to use when authenticating the client.
436                 /// </value>
437                 /// <remarks>
438                 /// You can set the user name and Password in order to specify alternate 
439                 /// credentials with which to access the information in Ldap Directory. 
440                 /// Any other DirectoryEntry objects retrieved from this instance (for 
441                 /// example, through Children) are automatically created with the same 
442                 /// alternate 
443                 /// </remarks>
444                 [DSDescription ("The user name to use when authenticating the client.")]
445                 [DefaultValue (null)]
446                 [Browsable (false)]
447                 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
448                 public string Username 
449                 {
450                         get                     {
451                                 return _Username ;
452                         }
453                         set                     {
454                                 _Username = value;
455                         }
456
457                 }
458
459                 /// <summary>
460                 /// Gets or sets the path for this DirectoryEntry.
461                 /// </summary>
462                 /// <value>
463                 /// The path of this DirectoryEntry. The default is an empty string ("").
464                 /// </value>
465                 /// <remarks>
466                 /// The Path property uniquely identifies this entry in a networked 
467                 /// environment. This entry can always be retrieved using this Path.
468                 /// 
469                 /// Setting the Path retrieves a new entry from the directory store; it 
470                 /// does not change the path of the currently bound entry.
471                 /// 
472                 /// The classes associated with the DirectoryEntry component can be used 
473                 /// with any of the  Directory service providers. Some of the current 
474                 /// providers are Internet Information Services (IIS), Lightweight Directory 
475                 /// Access Protocol (Ldap), Novell NetWare Directory Service (NDS), and WinNT.
476                 /// 
477                 /// Currently we Support only Ldap provider.
478                 /// e.g Ldap://[hostname]:[port number]/[ObjectFDN]
479                 /// </remarks>
480                 [DSDescription ("The path for this DirectoryEntry.")]
481                 [DefaultValue ("")]
482                 [RecommendedAsConfigurable (true)]
483                 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
484                 public string Path 
485                 {
486                         get                     {
487                                 return _Path;
488                         }
489                         set                     {
490                                 _Path = value;
491                         }
492
493                 }
494
495                 /// <summary>
496                 /// Gets a PropertyCollection of properties set on this object.
497                 /// </summary>
498                 /// <value>
499                 /// A PropertyCollection of properties set on this object.
500                 /// </value>
501                 [DSDescription ("Properties set on this object.")]
502                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
503                 [Browsable (false)]
504                 public PropertyCollection Properties
505                 {
506                         get                     {
507                                 if ( _Properties == null )                              {
508
509                                         _Properties =  new PropertyCollection();
510
511                                         try                                     {
512                                                 LdapSearchResults lsc=conn.Search(      Fdn,
513                                                                                                                         LdapConnection.SCOPE_BASE,
514                                                                                                                         "objectClass=*",
515                                                                                                                         null,
516                                                                                                                         false);
517                                                 while(lsc.hasMore())                                            {
518
519                                                         LdapEntry nextEntry = null;
520                                                         try                                                     {
521                                                                 nextEntry = lsc.next();
522                                                         }
523                                                         catch(LdapException e)                                                  {
524                                                                 Console.WriteLine("Error: " + e.LdapErrorMessage);
525                                                                 // Exception is thrown, go for next entry
526                                                                 throw e;
527                                                         }
528                                                         LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
529                                                         System.Collections.IEnumerator ienum=attributeSet.GetEnumerator();
530                                                         if(ienum!=null)                                                 {
531                                                                 while(ienum.MoveNext())                         {
532                                                                         LdapAttribute attribute=(LdapAttribute)ienum.Current;
533                                                                         string attributeName = attribute.Name;
534                                                                         _Properties[attributeName].AddRange(attribute.StringValueArray);
535                                                                         _Properties[attributeName].Mbit=false;
536                                                                         //                                                      string attributeVal = attribute.StringValue;
537                                                                         //                                                      _Properties[attributeName].Add(attributeVal);
538                                                                 }
539                                                         }
540                                                         break;
541                                                 }
542                                         }
543                                         catch( LdapException le)                                        {
544                                                 if(le.ResultCode == LdapException.NO_SUCH_OBJECT)
545                                                 {       }
546                                         }
547
548                                 }
549                                 return _Properties;
550                         }
551                 }
552
553                 /// <summary>
554                 /// Gets the name of the schema used for this DirectoryEntry
555                 /// </summary>
556                 /// <value>
557                 /// The name of the schema used for this DirectoryEntry.
558                 /// </value>
559                 [DSDescription ("The name of the schema used for this DirectoryEntry.")]
560                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
561                 [Browsable (false)]
562                 public string SchemaClassName 
563                 {
564                         get                     {
565                                 if(_SchemaClassName==null)                              {
566                                                 _SchemaClassName = FindAttrValue("structuralObjectClass");
567                                 }
568                                 return _SchemaClassName;
569                         }
570                 }
571
572                 /// <summary>
573                 /// Gets the current schema directory entry.
574                 /// </summary>
575                 /// <remarks>
576                 /// Not implemented yet
577                 [DSDescription ("The current schema directory entry.")]
578                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
579                 [Browsable (false)]
580                 public DirectoryEntry SchemaEntry 
581                 {
582                         [MonoTODO]
583                         get                     {
584                                 throw new NotImplementedException();
585                         }
586                 }
587
588                 /// <summary>
589                 /// Searches an entry in the Ldap directory and returns the attribute value
590                 /// </summary>
591                 /// <param name="attrName">attribute whose value is required</param>
592                 /// <returns> value of the attribute stored in Ldap directory</returns>
593                 private string FindAttrValue(string attrName)
594                 {
595                         string aValue=null;
596                         string[] attrs={attrName};
597
598                         LdapSearchResults lsc=conn.Search(      Fdn,
599                                                                                                 LdapConnection.SCOPE_BASE,
600                                                                                                 "objectClass=*",
601                                                                                                 attrs,
602                                                                                                 false);
603                         while(lsc.hasMore())                    {
604                                 LdapEntry nextEntry = null;
605                                 try                                             {
606                                         nextEntry = lsc.next();
607                                 }
608                                 catch(LdapException e)          {
609                                         Console.WriteLine("Error: " + e.LdapErrorMessage);
610                                         // Exception is thrown, go for next entry
611                                         throw e;
612                                 }
613                                 LdapAttribute attribute = nextEntry.getAttribute(attrName);
614                                 aValue = attribute.StringValue;
615                                 break;
616                         }
617                         return aValue;
618                 }
619
620                 /// <summary>
621                 /// Modifies an entry in the Ldap directory with the input LdapModification
622                 /// values.
623                 /// </summary>
624                 /// <param name="mods">Array consisting of the entry attribute name and the
625                 /// attribute  values to be modified.</param>
626                 private void ModEntry(LdapModification[] mods)
627                 {
628
629                         try                                             {
630                                 conn.Modify(Fdn,mods);
631                         }
632                         catch(LdapException le) {
633                                 throw le;
634                         }
635                 }
636
637                 /// <summary>
638                 /// Checks whether the entry exists in the Ldap directory or not
639                 /// </summary>
640                 /// <param name="lconn">
641                 /// Connection used to communicate with directory
642                 /// </param>
643                 /// <param name="epath">
644                 /// path of the entry
645                 /// </param>
646                 /// <returns>
647                 ///             true of the entry exists in the Ldap directory
648                 ///             false if entry doesn't exists
649                 /// </returns>
650                 private static bool CheckEntry(LdapConnection lconn, string epath)
651                 {
652                         LdapUrl lUrl=new LdapUrl(epath);
653                         string eDn=lUrl.getDN();
654                         if(eDn==null)
655                         {
656                                 eDn="";
657                         }
658                         string[] attrs={"objectClass"};
659                         try
660                         {
661                                 LdapSearchResults lsc=lconn.Search(     eDn,
662                                         LdapConnection.SCOPE_BASE,
663                                         "objectClass=*",
664                                         attrs,
665                                         false);
666                                 while(lsc.hasMore())
667                                 {
668                                         LdapEntry nextEntry = null;
669                                         try 
670                                         {
671                                                 nextEntry = lsc.next();
672                                         }
673                                         catch(LdapException e) 
674                                         {
675                                                 Console.WriteLine("Error: " + e.LdapErrorMessage);
676                                                 // Exception is thrown, go for next entry
677                                                 throw e;
678                                         }
679                                         break;
680                                 }
681
682                         }
683                         catch(LdapException le)
684                         {
685                                 if(le.ResultCode == LdapException.NO_SUCH_OBJECT)
686                                 {
687                                         return false;
688                                 }
689                                 else
690                                 {
691                                         throw le;
692                                 }
693                         }
694                         catch(Exception e)
695                         {
696                                 throw e;
697                         }
698                         return true;
699                 }
700
701                 /// <summary>
702                 /// Closes the DirectoryEntry and releases any system resources associated 
703                 /// with this component.
704                 /// </summary>
705                 /// <remarks>
706                 /// Following a call to Close, any operations on the DirectoryEntry might 
707                 /// raise exceptions.
708                 /// </remarks>
709                 public void Close()
710                 {
711                         conn.Disconnect();
712                 }
713
714                 /// <summary>
715                 /// Creates a copy of this entry as a child of the specified parent.
716                 /// </summary>
717                 /// <param name="newParent">The parent DirectoryEntry.  </param>
718                 /// <returns>A copy of this entry as a child of the specified parent.
719                 [MonoTODO]
720                 public DirectoryEntry CopyTo(DirectoryEntry newParent)
721                 {
722                         throw new NotImplementedException();
723                 }
724
725                 /// <summary>
726                 /// Deletes this entry and its entire subtree from the Active Directory 
727                 /// hierarchy.
728                 /// </summary>
729                 /// <remarks>
730                 /// CAUTION   The entry and its entire subtree are deleted from the 
731                 /// Ldap Directory hierarchy.
732                 /// </remarks>
733                 public void DeleteTree()
734                 {
735                         System.Collections.IEnumerator ienum = Children.GetEnumerator();
736                         while(ienum.MoveNext())
737                         {
738                                 DirectoryEntry de=(DirectoryEntry)ienum.Current;
739                                 conn.Delete(de.Fdn);
740                         }
741                         conn.Delete(Fdn);
742                 }
743
744                 /// <summary>
745                 /// Searches the directory store at the specified path to see whether 
746                 /// an entry exists
747                 /// </summary>
748                 /// <param name="path">
749                 /// The path at which to search the directory store. 
750                 /// </param>
751                 /// <returns>
752                 /// true if an entry exists in the directory store at the specified 
753                 /// path; otherwise, false.
754                 /// </returns>
755                 public static bool Exists(string path)
756                 {
757                         LdapConnection aconn=new LdapConnection();
758                         LdapUrl lurl=new LdapUrl(path);
759                         aconn.Connect(lurl.Host,lurl.Port);
760                         aconn.Bind("","");
761                         if(CheckEntry(aconn,path))
762                                 return true;
763                         else
764                                 return false;
765                 }
766
767                 /// <summary>
768                 /// Moves this entry to the specified parent.
769                 /// </summary>
770                 /// <param name="pentry">
771                 /// The parent to which you want to move this entry
772                 /// </param>
773                 public void MoveTo(DirectoryEntry newParent)
774                 {
775                         conn.Rename(Fdn, Name, newParent.Fdn, true);
776                 }
777
778                 /// <summary>
779                 /// Moves this entry to the specified parent and changes its name to 
780                 /// the value of the newName parameter.
781                 /// </summary>
782                 /// <param name="newParent"> The parent to which you want to move 
783                 /// this entry
784                 /// </param>
785                 /// <param name="newName">
786                 /// The new name of this entry. 
787                 /// </param>
788                 public void MoveTo(     DirectoryEntry newParent,
789                                                         string newName  )
790                 {
791                         conn.Rename(Fdn, newName, newParent.Fdn, true);
792                 }
793
794                 /// <summary>
795                 /// Changes the name of this entry.
796                 /// </summary>
797                 /// <param name="newName">
798                 /// The new name of the entry. 
799                 /// </param>
800                 /// <remarks>
801                 /// Note   This will also affect the path used to refer to this entry.
802                 /// </remarks>
803                 public void Rename(     string newName  )
804                 {
805                         conn.Rename( Fdn, newName, true);
806                 }
807
808                 /// <summary>
809                 /// Calls a method on the native Active Directory.
810                 /// </summary>
811                 /// <param name="methodName">The name of the method to invoke. 
812                 /// </param>
813                 /// <param name="args">
814                 /// An array of type Object that contains the arguments of the method 
815                 /// to invoke. 
816                 /// </param>
817                 /// <returns>The return value of the invoked method</returns>
818                 /// <remarks>
819                 /// Not implemented.
820                 [MonoTODO]
821                 public object Invoke(string methodName,
822                         params object[] args)
823                 {
824                         throw new NotImplementedException();
825                 }
826
827                 /// <summary>
828                 /// Creates a copy of this entry, as a child of the specified parent, with 
829                 /// the specified new name.
830                 /// </summary>
831                 /// <param name="newParent">The parent DirectoryEntry.  </param>
832                 /// <param name="newName"> The name of the copy of this entry. 
833                 /// </param>
834                 /// <returns>A renamed copy of this entry as a child of the specified parent.
835                 [MonoTODO]
836                 public DirectoryEntry CopyTo( DirectoryEntry newParent,
837                         string newName  )
838                 {
839                         throw new NotImplementedException();
840                 }
841
842                 /// <summary>
843                 /// Saves any changes to the entry in the Ldap Directory store.
844                 /// </summary>
845                 /// <remarks>
846                 /// By default, changes to properties are done locally to a cache, and 
847                 /// property values to be read are cached after the first read. For more 
848                 /// information, see UsePropertyCache.
849                 /// Changes made to the cache include changes to the properties as well as 
850                 /// calls to Add (if this is the newly created entry).
851                 /// </remarks>
852                 public void CommitChanges()
853                 {
854                         if(!Nflag)
855                         {
856                                 System.Collections.ArrayList modList = new System.Collections.ArrayList();
857                                 System.Collections.IDictionaryEnumerator id = Properties.GetEnumerator();
858                                 while(id.MoveNext())
859                                 {
860                                         string attribute=(string)id.Key;
861                                         LdapAttribute attr=null;
862                                         if(Properties[attribute].Mbit)
863                                         {
864                                                 if(Properties[attribute].Count==1)
865                                                 {
866                                                         String val = (String)Properties[attribute].Value;
867                                                         attr = new LdapAttribute( attribute , val);
868                                                 }
869                                                 else
870                                                 {
871                                                         Object[] vals=(Object [])Properties[attribute].Value;
872                                                         String[] aStrVals= new String[Properties[attribute].Count];
873                                                         Array.Copy(vals,0,aStrVals,0,Properties[attribute].Count);
874                                                         attr = new LdapAttribute( attribute , aStrVals);
875                                                 }
876                                                 modList.Add( new LdapModification(LdapModification.REPLACE, attr));
877                                                 Properties[attribute].Mbit=false;
878                                         }
879 //                                      Console.WriteLine(attribute + "Total no of attr value" + Properties[attribute].Count);
880                                 }
881                                 LdapModification[] mods = new LdapModification[modList.Count];  
882                                 Type mtype=Type.GetType("System.DirectoryServices.LdapModification");
883                                 mods = (LdapModification[])modList.ToArray(typeof(LdapModification));
884                                 ModEntry(mods);
885                         }
886                         else
887                         {
888                                 LdapAttributeSet attributeSet = new LdapAttributeSet();
889                                 System.Collections.IDictionaryEnumerator id = Properties.GetEnumerator();
890                                 while(id.MoveNext())
891                                 {
892                                         string attribute=(string)id.Key;
893 //                                      Console.WriteLine("attribute:"  + attribute + "Vals:" + Properties[attribute][0]);
894                                         if(Properties[attribute].Count==1)
895                                         {
896                                                 String val = (String)Properties[attribute].Value;
897                                                 attributeSet.Add(new LdapAttribute(attribute, val));                
898                                         }
899                                         else
900                                         {
901                                                 Object[] vals=(Object [])Properties[attribute].Value;
902                                                 String[] aStrVals= new String[Properties[attribute].Count];
903                                                 Array.Copy(vals,0,aStrVals,0,Properties[attribute].Count);
904                                                 attributeSet.Add( new LdapAttribute( attribute , aStrVals));
905                                         }
906                                 }
907                                 LdapEntry newEntry = new LdapEntry( Fdn, attributeSet );
908                                 conn.Add( newEntry );                   
909                         }
910                 }
911
912                 [MonoTODO]
913                 public void RefreshCache ()
914                 {
915                         throw new NotImplementedException ("System.DirectoryServices.DirectoryEntry.RefreshCache()");
916                 }
917
918                 [MonoTODO]
919                 public void RefreshCache (string[] args)
920                 {
921                         throw new NotImplementedException ("System.DirectoryServices.DirectoryEntry.RefreshCache(System.String[])");
922                 }
923
924                 protected override void Dispose (bool disposing)
925                 {
926                         if (!_disposed && disposing) {
927                                 Close ();
928                                 _disposed = true;
929                         }
930                         base.Dispose (disposing);
931                 }
932         }
933 }