fix typo
[mcs.git] / class / System.DirectoryServices / System.DirectoryServices / DirectoryEntry.cs
bloba1dffa258ff47f44fed1a2a93712ef84a6c9ee61
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc., www.novell.com
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
25 // System.DirectoryServices.DirectoryEntry.cs
27 // Authors:
28 // Sunil Kumar (sunilk@novell.com)
29 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
30 // Boris Kirzner (borisk@mainsoft.com)
32 // (C) Novell Inc.
35 using System.ComponentModel;
36 using Novell.Directory.Ldap;
37 using Novell.Directory.Ldap.Utilclass;
38 using System.Globalization;
39 using System.DirectoryServices.Design;
40 using System.Collections.Specialized;
41 using System.Configuration;
42 using System.Runtime.InteropServices;
44 namespace System.DirectoryServices
47 /// <summary>
48 ///Encapsulates a node or object in the Ldap Directory hierarchy.
49 /// </summary>
50 [TypeConverter (typeof (DirectoryEntryConverter))]
51 public class DirectoryEntry : Component
53 private static readonly string DEFAULT_LDAP_HOST = "System.DirectoryServices.DefaultLdapHost";
54 private static readonly string DEFAULT_LDAP_PORT = "System.DirectoryServices.DefaultLdapPort";
56 private LdapConnection _conn = null;
57 private AuthenticationTypes _AuthenticationType=AuthenticationTypes.None;
58 private DirectoryEntries _Children;
59 private string _Fdn = null;
60 private string _Path="";
61 private string _Name=null;
62 private DirectoryEntry _Parent=null;
63 private string _Username;
64 private string _Password;
65 //private string _Nativeguid;
66 private PropertyCollection _Properties = null;
67 private string _SchemaClassName=null;
68 private bool _Nflag = false;
69 private bool _usePropertyCache=true;
70 private bool _inPropertiesLoading;
72 /// <summary>
73 /// Returns entry's Fully distinguished name.
74 /// </summary>
75 internal string Fdn
77 get {
78 if (_Fdn == null) {
79 LdapUrl lUrl = new LdapUrl (ADsPath);
80 string fDn=lUrl.getDN();
81 if(fDn != null)
82 _Fdn = fDn;
83 else
84 _Fdn=String.Empty;
86 return _Fdn;
90 /// <summary>
91 /// Returns the connection object used to communicate with
92 /// Ldap server
93 /// </summary>
94 internal LdapConnection conn
96 get {
97 if( _conn == null)
98 InitBlock();
100 return _conn;
102 set {
103 _conn=value;
107 /// <summary>
108 /// Flag to check whether the entry is to be cerated or it already
109 /// exists.
110 /// </summary>
111 internal bool Nflag
113 get {
114 return _Nflag;
116 set {
117 _Nflag = value;
121 /// <summary> Initializes the Connection and other properties.
122 ///
123 /// </summary>
124 private void InitBlock()
126 try {
127 _conn= new LdapConnection ();
128 LdapUrl lUrl = new LdapUrl (ADsPath);
129 _conn.Connect(lUrl.Host,lUrl.Port);
130 _conn.Bind(Username,Password, (Novell.Directory.Ldap.AuthenticationTypes)AuthenticationType);
132 catch(LdapException ex) {
133 throw ex;
135 catch(Exception e) {
136 throw e;
140 /// <summary>
141 /// Initializes the Entry specific properties e.g entry DN etc.
142 /// </summary>
143 void InitEntry()
145 LdapUrl lUrl = new LdapUrl (ADsPath);
146 string dn = lUrl.getDN();
147 if (dn != null ) {
148 if (String.Compare (dn,"rootDSE",true) == 0)
149 InitToRootDse (lUrl.Host,lUrl.Port);
150 else {
151 DN userDn = new DN (dn);
152 String[] lRdn = userDn.explodeDN(false);
153 _Name = (string)lRdn[0];
154 _Parent = new DirectoryEntry(conn);
155 _Parent.Path = GetLdapUrlString (lUrl.Host,lUrl.Port,userDn.Parent.ToString ());
158 else {
159 _Name=lUrl.Host+":"+lUrl.Port;
160 _Parent = new DirectoryEntry(conn);
161 _Parent.Path = "Ldap:";
165 /// <summary>
166 /// Initializes a new instance of the DirectoryEntry class
167 /// </summary>
168 public DirectoryEntry()
172 /// <summary>
173 /// Initializes a new instance of the DirectoryEntry class that binds
174 /// to the specified native Active Directory object.
175 /// </summary>
176 /// <param name="adsObject"> native active directory object</param>
177 public DirectoryEntry(object adsObject)
179 throw new NotImplementedException();
182 /// <summary>
183 /// Initializes a new instance of the DirectoryEntry class that binds
184 /// this instance to the node in Ldap Directory located at the
185 /// specified path.
186 /// </summary>
187 /// <param name="path"> Path of the entry i.e Ldap URL specifying
188 /// entry path</param>
189 public DirectoryEntry(string path)
191 _Path=path;
194 /// <summary>
195 /// Initializes a new instance of the DirectoryEntry class. The Path,
196 /// Username, and Password properties are set to the specified values.
197 /// </summary>
198 /// <param name="path">Path of the entry i.e Ldap URL specifying
199 /// entry path</param>
200 /// <param name="username">user name to use when authenticating the client
201 /// </param>
202 /// <param name="password">password to use when authenticating the client
203 /// </param>
204 public DirectoryEntry(string path,string username,string password)
206 _Path=path;
207 _Username=username;
208 _Password=password;
211 /// <summary>
212 /// Initializes a new instance of the DirectoryEntry class. The Path,
213 /// Username, and Password properties are set to the specified values.
214 /// </summary>
215 /// <param name="path">Path of the entry i.e Ldap URL specifying
216 /// entry path</param>
217 /// <param name="username">user name to use when authenticating the client
218 /// </param>
219 /// <param name="password">password to use when authenticating the client
220 /// </param>
221 /// <param name="authenticationType"> type of authentication to use</param>
222 public DirectoryEntry(
223 string path,
224 string username,
225 string password,
226 AuthenticationTypes authenticationType)
228 _Path=path;
229 _Username=username;
230 _Password=password;
231 _AuthenticationType=authenticationType;
234 /// <summary>
235 /// Creates the entry object
236 /// </summary>
237 /// <param name="lconn">Connection object used to communicate with
238 /// Ldap server</param>
239 internal DirectoryEntry(LdapConnection lconn)
241 conn = lconn;
244 /// <summary>
245 /// Returns Type of authentication to use while Binding to Ldap server
246 /// </summary>
247 [DSDescription ("Type of authentication to use while Binding to Ldap server")]
248 [DefaultValue (AuthenticationTypes.None)]
249 public AuthenticationTypes AuthenticationType
251 get
253 return _AuthenticationType;
255 set
257 _AuthenticationType = value;
261 /// <summary>
262 /// Gets a DirectoryEntries containing the child entries of this node
263 /// in the Ldap Directory hierarchy.
264 /// </summary>
265 /// <value>A DirectoryEntries containing the child entries of this node
266 /// in the Ldap Directory hierarchy.</value>
267 /// <remarks>
268 /// The child entries are only the immediate children of this node.
269 /// Use this property to find, retrieve, or create a directory entry
270 /// in the hierarchy. This property is a collection that, along with
271 /// usual iteration capabilities, provides an Add method through which
272 /// you add a node to the collection directly below the parent node
273 /// that you are currently bound to. When adding a node to the
274 /// collection, you must specify a name for the new node and the name of
275 /// a schema template that you want to associate with the node. For
276 /// example, you might want to use a schema titled "Computer" to add
277 /// new computers to the hierarchy.
278 /// </remarks>
279 [DSDescription ("Child entries of this node")]
280 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
281 [Browsable (false)]
282 public DirectoryEntries Children
284 get
286 _Children = new DirectoryEntries(ADsPath, conn);
287 return _Children;
291 /// <summary>
292 /// Gets the globally unique identifier (GUID) of the DirectoryEntry
293 /// </summary>
294 /// <value>The globally unique identifier of the DirectoryEntry.</value>
295 /// <remarks>
296 /// Not implemented yet.
297 /// </remarks>
298 [DSDescription ("A globally unique identifier for this DirectoryEntry")]
299 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300 [Browsable (false)]
301 [MonoTODO]
302 public Guid Guid
304 get
306 throw new NotImplementedException();
311 /// <summary>
312 /// Gets the name of the object as named with the underlying directory
313 /// service
314 /// </summary>
315 /// <value>The name of the object as named with the underlying directory
316 /// service</value>
317 /// <remarks>This name, along with SchemaClassName, distinguishes this
318 /// entry from its siblings and must be unique amongst its siblings
319 /// in each instance of DirectoryEntry.</remarks>
320 [DSDescription ("The name of the object as named with the underlying directory")]
321 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
322 [Browsable (false)]
323 public string Name
325 get {
326 if(_Name==null) {
327 if(CheckEntry(conn,ADsPath))
328 InitEntry();
329 else
330 throw new SystemException("There is no such object on the server");
332 return _Name;
336 /// <summary>
337 /// Gets this entry's parent in the Ldap Directory hierarchy.
338 /// </summary>
339 /// <value>This entry's parent in the Active Directory hierarc</value>
340 [DSDescription ("This entry's parent in the Ldap Directory hierarchy.")]
341 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
342 [Browsable (false)]
343 public DirectoryEntry Parent
345 get {
346 if(_Parent==null) {
347 if(CheckEntry(conn,ADsPath))
348 InitEntry();
349 else
350 throw new SystemException("There is no such object on the server");
352 return _Parent;
356 /// <summary>
357 /// Gets the globally unique identifier of the DirectoryEntry, as
358 /// returned from the provider
359 /// </summary>
360 /// <value>
361 /// The globally unique identifier of the DirectoryEntry, as returned
362 /// from the provider.
363 /// </value>
364 /// <remarks>
365 /// Not implemented yet.
366 /// </remarks>
367 [DSDescription ("The globally unique identifier of the DirectoryEntry, as returned from the provider")]
368 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
369 [Browsable (false)]
370 [MonoTODO]
371 public string NativeGuid
373 get {
374 throw new NotImplementedException();
378 /// <summary>
379 /// Gets the native Active Directory Service Interfaces (ADSI) object.
380 /// </summary>
381 /// <remarks>
382 /// Not implemented yet
383 [DSDescription ("The native Active Directory Service Interfaces (ADSI) object.")]
384 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
385 [Browsable (false)]
386 public object NativeObject
388 [MonoTODO]
389 get {
390 throw new NotImplementedException();
394 /// <summary>
395 /// Determines if a cache should be used.
396 /// </summary>
397 [DSDescription ("Determines if a cache should be used.")]
398 [DefaultValue (true)]
399 public bool UsePropertyCache
401 get
403 return _usePropertyCache;
405 set
407 _usePropertyCache = value;
411 /// <summary>
412 /// Gets or sets the password to use when authenticating the client.
413 /// </summary>
414 /// <value>
415 /// The password to use when authenticating the client.
416 /// </value>
417 /// <remarks>
418 /// You can set the Username and password in order to specify alternate
419 /// credentials with which to access the information in Ldap Directory.
420 /// Any other DirectoryEntry objects retrieved from this instance (for
421 /// example, through Children) are automatically created with the same
422 /// alternate credentials.
423 /// </remarks>
424 [DSDescription ("The password to use when authenticating the client.")]
425 [DefaultValue (null)]
426 [Browsable (false)]
427 public string Password
429 get {
430 return _Password;
432 set {
433 _Password = value;
438 /// <summary>
439 /// Gets or sets the user name to use when authenticating the client.
440 /// </summary>
441 /// <value>
442 /// The user name to use when authenticating the client.
443 /// </value>
444 /// <remarks>
445 /// You can set the user name and Password in order to specify alternate
446 /// credentials with which to access the information in Ldap Directory.
447 /// Any other DirectoryEntry objects retrieved from this instance (for
448 /// example, through Children) are automatically created with the same
449 /// alternate
450 /// </remarks>
451 [DSDescription ("The user name to use when authenticating the client.")]
452 [DefaultValue (null)]
453 [Browsable (false)]
454 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
455 public string Username
457 get {
458 return _Username ;
460 set {
461 _Username = value;
466 /// <summary>
467 /// Gets or sets the path for this DirectoryEntry.
468 /// </summary>
469 /// <value>
470 /// The path of this DirectoryEntry. The default is an empty string ("").
471 /// </value>
472 /// <remarks>
473 /// The Path property uniquely identifies this entry in a networked
474 /// environment. This entry can always be retrieved using this Path.
475 ///
476 /// Setting the Path retrieves a new entry from the directory store; it
477 /// does not change the path of the currently bound entry.
478 ///
479 /// The classes associated with the DirectoryEntry component can be used
480 /// with any of the Directory service providers. Some of the current
481 /// providers are Internet Information Services (IIS), Lightweight Directory
482 /// Access Protocol (Ldap), Novell NetWare Directory Service (NDS), and WinNT.
483 ///
484 /// Currently we Support only Ldap provider.
485 /// e.g Ldap://[hostname]:[port number]/[ObjectFDN]
486 /// </remarks>
487 [DSDescription ("The path for this DirectoryEntry.")]
488 [DefaultValue ("")]
489 [RecommendedAsConfigurable (true)]
490 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
491 public string Path
493 get {
494 return _Path;
496 set {
497 if (value == null)
498 _Path = String.Empty;
499 else
500 _Path = value;
504 internal string ADsPath
506 get {
507 if (Path == null || Path == String.Empty) {
508 DirectoryEntry rootDse = new DirectoryEntry ();
509 rootDse.InitToRootDse (null,-1);
510 string namingContext = (string) rootDse.Properties ["defaultNamingContext"].Value;
511 if ( namingContext == null )
512 namingContext = (string) rootDse.Properties ["namingContexts"].Value;
514 LdapUrl actualUrl= new LdapUrl (DefaultHost,DefaultPort,namingContext);
515 return actualUrl.ToString ();
517 return Path;
521 /// <summary>
522 /// Gets a PropertyCollection of properties set on this object.
523 /// </summary>
524 /// <value>
525 /// A PropertyCollection of properties set on this object.
526 /// </value>
527 [DSDescription ("Properties set on this object.")]
528 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
529 [Browsable (false)]
530 public PropertyCollection Properties
532 get {
533 return GetProperties (true);
537 /// <summary>
538 /// Gets the name of the schema used for this DirectoryEntry
539 /// </summary>
540 /// <value>
541 /// The name of the schema used for this DirectoryEntry.
542 /// </value>
543 [DSDescription ("The name of the schema used for this DirectoryEntry.")]
544 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
545 [Browsable (false)]
546 public string SchemaClassName
548 get {
549 if(_SchemaClassName==null) {
550 _SchemaClassName = FindAttrValue("structuralObjectClass");
552 return _SchemaClassName;
556 /// <summary>
557 /// Gets the current schema directory entry.
558 /// </summary>
559 /// <remarks>
560 /// Not implemented yet
561 [DSDescription ("The current schema directory entry.")]
562 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
563 [Browsable (false)]
564 public DirectoryEntry SchemaEntry
566 [MonoTODO]
567 get {
568 throw new NotImplementedException();
572 private string DefaultHost
574 get {
575 string defaultHost = (string) AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_HOST);
577 if (defaultHost == null) {
578 NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("mainsoft.directoryservices/settings");
579 if (config != null)
580 defaultHost = config ["servername"];
582 if (defaultHost == null)
583 defaultHost = "localhost";
585 AppDomain.CurrentDomain.SetData (DEFAULT_LDAP_HOST,defaultHost);
587 return defaultHost;
591 private int DefaultPort
593 get {
594 string defaultPortStr = (string) AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_PORT);
596 if (defaultPortStr == null) {
597 NameValueCollection config = (NameValueCollection) ConfigurationSettings.GetConfig ("mainsoft.directoryservices/settings");
598 if (config != null)
599 defaultPortStr = config ["port"];
601 if (defaultPortStr == null)
602 defaultPortStr = "389";
604 AppDomain.CurrentDomain.SetData (DEFAULT_LDAP_PORT,defaultPortStr);
606 return Int32.Parse (defaultPortStr);
610 private void InitToRootDse(string host,int port)
612 if ( host == null )
613 host = DefaultHost;
614 if ( port < 0 )
615 port = DefaultPort;
617 LdapUrl rootPath = new LdapUrl (host,port,String.Empty);
618 string [] attrs = new string [] {"+","*"};
619 DirectoryEntry rootEntry = new DirectoryEntry (rootPath.ToString (),this.Username,this.Password,this.AuthenticationType);
620 DirectorySearcher searcher = new DirectorySearcher (rootEntry,null,attrs,SearchScope.Base);
622 SearchResult result = searcher.FindOne ();
623 // copy properties from search result
624 PropertyCollection pcoll = new PropertyCollection ();
625 foreach (string propertyName in result.Properties.PropertyNames) {
626 System.Collections.IEnumerator enumerator = result.Properties [propertyName].GetEnumerator ();
627 if (enumerator != null)
628 while (enumerator.MoveNext ())
629 if (String.Compare (propertyName,"ADsPath",true) != 0)
630 pcoll [propertyName].Add (enumerator.Current);
632 this.SetProperties (pcoll);
633 this._Name = "rootDSE";
636 private void SetProperties(PropertyCollection pcoll)
638 _Properties = pcoll;
641 /// <summary>
642 /// Returns entry properties.
643 /// </summary>
644 /// <param name="forceLoad">Specifies whenever to force the properties load from the server if local property cache is empty.</param>
645 /// <returns></returns>
646 private PropertyCollection GetProperties(bool forceLoad)
648 if (_Properties == null) {
649 // load properties into a different collection
650 // to preserve original collection state if exception occurs
651 PropertyCollection properties = new PropertyCollection (this);
652 if (forceLoad && !Nflag)
653 LoadProperties (properties,null);
655 _Properties = properties ;
657 return _Properties;
660 /// <summary>
661 /// Loads the values of the specified properties into the property cache.
662 /// </summary>
663 /// <param name="propertyNames">An array of the specified properties.</param>
664 private void LoadProperties(PropertyCollection properties,string[] propertyNames)
666 _inPropertiesLoading = true;
667 try {
668 LdapSearchResults lsc=conn.Search (Fdn,LdapConnection.SCOPE_BASE,"objectClass=*",propertyNames,false);
669 if (lsc.hasMore ()) {
670 LdapEntry nextEntry = lsc.next ();
671 string [] lowcasePropertyNames = null;
672 int length = 0;
673 if (propertyNames != null) {
674 length = propertyNames.Length;
675 lowcasePropertyNames = new string [length];
676 for(int i=0; i < length; i++)
677 lowcasePropertyNames [i] = propertyNames [i].ToLower ();
679 foreach (LdapAttribute attribute in nextEntry.getAttributeSet ()) {
680 string attributeName = attribute.Name;
681 if ((propertyNames == null) || (Array.IndexOf (lowcasePropertyNames,attributeName.ToLower ()) != -1)) {
682 properties [attributeName].Value = null;
683 properties [attributeName].AddRange (attribute.StringValueArray);
684 properties [attributeName].Mbit=false;
689 finally {
690 _inPropertiesLoading = false;
694 /// <summary>
695 /// Searches an entry in the Ldap directory and returns the attribute value
696 /// </summary>
697 /// <param name="attrName">attribute whose value is required</param>
698 /// <returns> value of the attribute stored in Ldap directory</returns>
699 private string FindAttrValue(string attrName)
701 string aValue=null;
702 string[] attrs={attrName};
704 LdapSearchResults lsc=conn.Search( Fdn,
705 LdapConnection.SCOPE_BASE,
706 "objectClass=*",
707 attrs,
708 false);
709 while(lsc.hasMore()) {
710 LdapEntry nextEntry = null;
711 try {
712 nextEntry = lsc.next();
714 catch(LdapException e) {
715 // Exception is thrown, go for next entry
716 throw e;
718 LdapAttribute attribute = nextEntry.getAttribute(attrName);
719 aValue = attribute.StringValue;
720 break;
722 return aValue;
725 /// <summary>
726 /// Modifies an entry in the Ldap directory with the input LdapModification
727 /// values.
728 /// </summary>
729 /// <param name="mods">Array consisting of the entry attribute name and the
730 /// attribute values to be modified.</param>
731 private void ModEntry(LdapModification[] mods)
734 try {
735 conn.Modify(Fdn,mods);
737 catch(LdapException le) {
738 throw le;
742 /// <summary>
743 /// Checks whether the entry exists in the Ldap directory or not
744 /// </summary>
745 /// <param name="lconn">
746 /// Connection used to communicate with directory
747 /// </param>
748 /// <param name="epath">
749 /// path of the entry
750 /// </param>
751 /// <returns>
752 /// true of the entry exists in the Ldap directory
753 /// false if entry doesn't exists
754 /// </returns>
755 private static bool CheckEntry(LdapConnection lconn, string epath)
757 LdapUrl lUrl=new LdapUrl(epath);
758 string eDn=lUrl.getDN();
759 if(eDn==null)
761 eDn = String.Empty;
763 // rootDSE is a "virtual" entry that always exists
764 else if (String.Compare (eDn,"rootDSE",true) == 0)
765 return true;
767 string[] attrs={"objectClass"};
770 LdapSearchResults lsc=lconn.Search( eDn,
771 LdapConnection.SCOPE_BASE,
772 "objectClass=*",
773 attrs,
774 false);
775 while(lsc.hasMore())
777 LdapEntry nextEntry = null;
778 try
780 nextEntry = lsc.next();
782 catch(LdapException e)
784 // Exception is thrown, go for next entry
785 throw e;
787 break;
791 catch(LdapException le)
793 if(le.ResultCode == LdapException.NO_SUCH_OBJECT)
795 return false;
797 else
799 throw le;
802 catch(Exception e)
804 throw e;
806 return true;
809 /// <summary>
810 /// Closes the DirectoryEntry and releases any system resources associated
811 /// with this component.
812 /// </summary>
813 /// <remarks>
814 /// Following a call to Close, any operations on the DirectoryEntry might
815 /// raise exceptions.
816 /// </remarks>
817 public void Close()
819 if (_conn != null && _conn.Connected) {
820 _conn.Disconnect();
824 /// <summary>
825 /// Creates a copy of this entry as a child of the specified parent.
826 /// </summary>
827 /// <param name="newParent">The parent DirectoryEntry. </param>
828 /// <returns>A copy of this entry as a child of the specified parent.
829 [MonoTODO]
830 public DirectoryEntry CopyTo(DirectoryEntry newParent)
832 throw new NotImplementedException();
835 /// <summary>
836 /// Deletes this entry and its entire subtree from the Active Directory
837 /// hierarchy.
838 /// </summary>
839 /// <remarks>
840 /// CAUTION The entry and its entire subtree are deleted from the
841 /// Ldap Directory hierarchy.
842 /// </remarks>
843 public void DeleteTree()
845 System.Collections.IEnumerator ienum = Children.GetEnumerator();
846 while(ienum.MoveNext())
848 DirectoryEntry de=(DirectoryEntry)ienum.Current;
849 conn.Delete(de.Fdn);
851 conn.Delete(Fdn);
854 /// <summary>
855 /// Searches the directory store at the specified path to see whether
856 /// an entry exists
857 /// </summary>
858 /// <param name="path">
859 /// The path at which to search the directory store.
860 /// </param>
861 /// <returns>
862 /// true if an entry exists in the directory store at the specified
863 /// path; otherwise, false.
864 /// </returns>
865 public static bool Exists(string path)
867 LdapConnection aconn=new LdapConnection();
868 LdapUrl lurl=new LdapUrl(path);
869 aconn.Connect(lurl.Host,lurl.Port);
870 aconn.Bind("","");
871 if(CheckEntry(aconn,path))
872 return true;
873 else
874 return false;
877 /// <summary>
878 /// Moves this entry to the specified parent.
879 /// </summary>
880 /// <param name="pentry">
881 /// The parent to which you want to move this entry
882 /// </param>
883 public void MoveTo(DirectoryEntry newParent)
885 string oldParentFdn = Parent.Fdn;
886 conn.Rename(Fdn, Name, newParent.Fdn, true);
887 // TBD : threat multiple name instance in path
888 Path = Path.Replace(oldParentFdn,newParent.Fdn);
889 RefreshEntry();
892 /// <summary>
893 /// Moves this entry to the specified parent and changes its name to
894 /// the value of the newName parameter.
895 /// </summary>
896 /// <param name="newParent"> The parent to which you want to move
897 /// this entry
898 /// </param>
899 /// <param name="newName">
900 /// The new name of this entry.
901 /// </param>
902 public void MoveTo( DirectoryEntry newParent,
903 string newName )
905 string oldParentFdn = Parent.Fdn;
906 conn.Rename(Fdn, newName, newParent.Fdn, true);
907 // TBD : threat multiple name instance in path
908 Path = Path.Replace(oldParentFdn,newParent.Fdn).Replace(Name,newName);
909 RefreshEntry();
912 /// <summary>
913 /// Changes the name of this entry.
914 /// </summary>
915 /// <param name="newName">
916 /// The new name of the entry.
917 /// </param>
918 /// <remarks>
919 /// Note This will also affect the path used to refer to this entry.
920 /// </remarks>
921 public void Rename( string newName )
923 string oldName = Name;
924 conn.Rename( Fdn, newName, true);
925 // TBD : threat multiple name instance in path
926 Path = Path.Replace(oldName,newName);
927 RefreshEntry();
930 /// <summary>
931 /// Calls a method on the native Active Directory.
932 /// </summary>
933 /// <param name="methodName">The name of the method to invoke.
934 /// </param>
935 /// <param name="args">
936 /// An array of type Object that contains the arguments of the method
937 /// to invoke.
938 /// </param>
939 /// <returns>The return value of the invoked method</returns>
940 /// <remarks>
941 /// Not implemented.
942 [MonoTODO]
943 public object Invoke(string methodName,
944 params object[] args)
946 throw new NotImplementedException();
949 #if NET_2_0
950 /// <summary>
951 /// Gets a property value from the native Active Directory Entry.
952 /// </summary>
953 /// <param name="propertyName">The name of the property to get.
954 /// </param>
955 /// <returns>The value of the property</returns>
956 /// <remarks>
957 /// Not implemented yet.
958 [ComVisibleAttribute (false)]
959 [MonoNotSupported ("")]
960 public object InvokeGet (string propertyName)
962 throw new NotImplementedException ();
965 /// <summary>
966 /// Sets a property value on the native Active Directory Entry.
967 /// </summary>
968 /// <param name="propertyName">The name of the property to get.
969 /// </param>
970 /// <param name="args">
971 /// An array of type Object that contains the arguments of the property
972 /// beeing set.
973 /// </param>
974 /// <remarks>
975 /// Not implemented yet.
976 [ComVisibleAttribute (false)]
977 [MonoNotSupported ("")]
978 public void InvokeSet (string propertyName, params object [] args)
980 throw new NotImplementedException ();
982 #endif
984 /// <summary>
985 /// Creates a copy of this entry, as a child of the specified parent, with
986 /// the specified new name.
987 /// </summary>
988 /// <param name="newParent">The parent DirectoryEntry. </param>
989 /// <param name="newName"> The name of the copy of this entry.
990 /// </param>
991 /// <returns>A renamed copy of this entry as a child of the specified parent.
992 [MonoTODO]
993 public DirectoryEntry CopyTo( DirectoryEntry newParent,
994 string newName )
996 throw new NotImplementedException();
999 /// <summary>
1000 /// Saves any changes to the entry in the Ldap Directory store.
1001 /// </summary>
1002 /// <remarks>
1003 /// By default, changes to properties are done locally to a cache, and
1004 /// property values to be read are cached after the first read. For more
1005 /// information, see UsePropertyCache.
1006 /// Changes made to the cache include changes to the properties as well as
1007 /// calls to Add (if this is the newly created entry).
1008 /// </remarks>
1009 public void CommitChanges()
1011 if(UsePropertyCache)
1013 CommitEntry();
1017 private void CommitEntry()
1019 PropertyCollection properties = GetProperties(false);
1020 if(!Nflag)
1022 System.Collections.ArrayList modList = new System.Collections.ArrayList();
1023 foreach (string attribute in properties.PropertyNames)
1025 LdapAttribute attr=null;
1026 if (properties [attribute].Mbit)
1028 switch (properties [attribute].Count) {
1029 case 0:
1030 attr = new LdapAttribute (attribute, new string [0]);
1031 modList.Add (new LdapModification (LdapModification.DELETE, attr));
1032 break;
1033 case 1:
1034 string val = (string) properties [attribute].Value;
1035 attr = new LdapAttribute (attribute, val);
1036 modList.Add (new LdapModification (LdapModification.REPLACE, attr));
1037 break;
1038 default:
1039 object [] vals = (object [])properties [attribute].Value;
1040 string [] aStrVals = new string [properties [attribute].Count];
1041 Array.Copy (vals, 0, aStrVals, 0, properties [attribute].Count);
1042 attr = new LdapAttribute (attribute, aStrVals);
1043 modList.Add (new LdapModification (LdapModification.REPLACE, attr));
1044 break;
1046 properties [attribute].Mbit=false;
1049 if (modList.Count > 0) {
1050 LdapModification[] mods = new LdapModification[modList.Count];
1051 Type mtype = typeof (LdapModification);
1052 mods = (LdapModification[])modList.ToArray(mtype);
1053 ModEntry(mods);
1056 else
1058 LdapAttributeSet attributeSet = new LdapAttributeSet();
1059 foreach (string attribute in properties.PropertyNames)
1061 if (properties [attribute].Count == 1)
1063 string val = (string) properties [attribute].Value;
1064 attributeSet.Add(new LdapAttribute(attribute, val));
1066 else
1068 object[] vals = (object []) properties [attribute].Value;
1069 string[] aStrVals = new string [properties [attribute].Count];
1070 Array.Copy (vals,0,aStrVals,0,properties [attribute].Count);
1071 attributeSet.Add( new LdapAttribute( attribute , aStrVals));
1074 LdapEntry newEntry = new LdapEntry( Fdn, attributeSet );
1075 conn.Add( newEntry );
1076 Nflag = false;
1080 internal void CommitDeferred()
1082 if (!_inPropertiesLoading && !UsePropertyCache && !Nflag)
1084 CommitEntry();
1088 void RefreshEntry()
1090 _Properties = null;
1091 _Fdn = null;
1092 _Name = null;
1093 _Parent = null;
1094 _SchemaClassName = null;
1095 InitEntry();
1098 /// <summary>
1099 /// Loads the values of the specified properties into the property cache.
1100 /// </summary>
1101 public void RefreshCache ()
1103 // note that GetProperties must be called with false, elswere infinite loop will be caused
1104 PropertyCollection properties = new PropertyCollection ();
1105 LoadProperties(properties, null);
1106 SetProperties (properties);
1109 /// <summary>
1110 /// Loads the values of the specified properties into the property cache.
1111 /// </summary>
1112 /// <param name="propertyNames">An array of the specified properties. </param>
1113 public void RefreshCache (string[] propertyNames)
1115 // note that GetProperties must be called with false, elswere infinite loop will be caused
1116 LoadProperties(GetProperties(false),propertyNames);
1119 protected override void Dispose (bool disposing)
1121 if (disposing) {
1122 Close ();
1124 base.Dispose (disposing);
1127 internal static string GetLdapUrlString(string host, int port, string dn)
1129 LdapUrl lUrl;
1130 if (port == LdapConnection.DEFAULT_PORT)
1131 lUrl = new LdapUrl (host,0,dn);
1132 else
1133 lUrl = new LdapUrl (host,port,dn);
1134 return lUrl.ToString();