added NET_2_0 strongly typed overrides
[mono.git] / mcs / class / System.DirectoryServices / System.DirectoryServices / DirectorySearcher.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.DirectorySearcher.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.Collections.Specialized;
38
39 namespace System.DirectoryServices
40 {
41         
42         /// <summary>
43         ///Performs queries against Ldap directory.
44         /// </summary>
45         public class DirectorySearcher : Component      
46         {
47                 private static readonly TimeSpan DefaultTimeSpan = new TimeSpan(-TimeSpan.TicksPerSecond);
48                 private DirectoryEntry _SearchRoot=null;
49                 private bool _CacheResults=true;
50                 private TimeSpan _ClientTimeout = DefaultTimeSpan;
51                 private string _Filter="(objectClass=*)";
52                 private int _PageSize=0;
53                 private StringCollection _PropertiesToLoad=new StringCollection();
54                 private bool _PropertyNamesOnly=false;
55                 private ReferralChasingOption _ReferralChasing=
56                                                 System.DirectoryServices.ReferralChasingOption.External;
57                 private SearchScope _SearchScope=
58                                                 System.DirectoryServices.SearchScope.Subtree;
59                 private TimeSpan _ServerPageTimeLimit = DefaultTimeSpan;
60                 private TimeSpan _serverTimeLimit = DefaultTimeSpan;
61                 private int _SizeLimit=0;
62                 private LdapConnection _conn = null;
63                 private string _Host=null;
64                 private int _Port=389;
65                 private SearchResultCollection _SrchColl=null;
66
67                 internal SearchResultCollection SrchColl 
68                 {
69                         get
70                         {
71                                 if (_SrchColl == null)
72                                 {
73                                         _SrchColl =  new SearchResultCollection();
74                                         DoSearch();
75                                 }
76                                 return _SrchColl;
77                         }
78                 }
79
80                 private void InitBlock()
81                 {
82                         _conn = new LdapConnection();
83                         LdapUrl lUrl=new LdapUrl(SearchRoot.ADsPath);
84                         _Host=lUrl.Host;
85                         _Port=lUrl.Port;
86                         _conn.Connect(_Host,_Port);
87                         _conn.Bind(SearchRoot.Username,SearchRoot.Password,(Novell.Directory.Ldap.AuthenticationTypes)SearchRoot.AuthenticationType);
88
89                 }
90
91                 /// <summary>
92                 /// Gets or sets a value indicating whether the result is 
93                 /// cached on the client computer.
94                 /// </summary>
95                 /// <value>
96                 /// true if the result is cached on the client computer; otherwise, 
97                 /// false. The default is true
98                 /// </value>
99                 /// <remarks>
100                 /// If the search returns a large result set, it is better to set 
101                 /// this property to false.
102                 /// </remarks>
103                 [DSDescription ("The cacheability of results.")]
104                 [DefaultValue (true)]
105                 public bool CacheResults 
106                 {
107                         get
108                         {
109                                 return _CacheResults;
110                         }
111                         set
112                         {
113                                 _CacheResults = value;
114                         }
115                 }
116
117                 /// <summary>
118                 /// Gets or sets the maximum amount of time that the client waits for 
119                 /// the server to return results. If the server does not respond 
120                 /// within this time, the search is aborted and no results are 
121                 /// returned.
122                 /// </summary>
123                 /// <value>
124                 /// A TimeSpan that represents the maximum amount of time (in seconds) 
125                 /// for the client to wait for the server to return results. The 
126                 /// default is -1, which means to wait indefinitely.
127                 /// </value>
128                 /// <remarks>
129                 /// If the ServerTimeLimit is reached before the client times out, 
130                 /// the server returns its results and the client stops waiting. The 
131                 /// maximum server time limit is 120 seconds.
132                 /// </remarks>
133                 [DSDescription ("The maximum amount of time that the client waits for the server to return results.")]
134                 public TimeSpan ClientTimeout 
135                 {
136                         get
137                         {
138                                 return _ClientTimeout;
139                         }
140                         set
141                         {
142                                 _ClientTimeout = value;
143                         }
144                 }
145
146                 /// <summary>
147                 /// Gets or sets the Lightweight Directory Access Protocol (Ldap) 
148                 /// format filter string.
149                 /// </summary>
150                 /// <value>
151                 /// The search filter string in Ldap format, such as 
152                 /// "(objectClass=user)". The default is "(objectClass=*)", which 
153                 /// retrieves all objects.
154                 /// </value>
155                 /// <remarks>
156                 /// The filter uses the following guidelines: 
157                 /// 1. The string must be enclosed in parentheses. 
158                 ///     2. Expressions can use the relational operators: <, <=, =, >=, 
159                 ///     and >. An example is "(objectClass=user)". Another example is 
160                 ///     "(lastName>=Davis)". 
161                 /// 3. Compound expressions are formed with the prefix operators & 
162                 /// and |. Anexampleis"(&(objectClass=user)(lastName= Davis))".
163                 /// Anotherexampleis"(&(objectClass=printer)(|(building=42)
164                 /// (building=43)))". 
165                 /// </remarks>
166                 [DSDescription ("The Lightweight Directory Access Protocol (Ldap) format filter string.")]
167                 [DefaultValue ("(objectClass=*)")]
168                 [RecommendedAsConfigurable (true)]
169                 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
170                 public string Filter 
171                 {
172                         get
173                         {
174                                 return _Filter;
175                         }
176                         set
177                         {
178                                 _Filter = value;
179                                 ClearCachedResults();
180                         }
181                 }
182
183                 /// <summary>
184                 /// Gets or sets the page size in a paged search.
185                 /// </summary>
186                 /// <value>
187                 /// The maximum number of objects the server can return in a paged 
188                 /// search. The default is zero, which means do not do a paged search.
189                 /// </value>
190                 /// <remarks>
191                 /// After the server has found a PageSize object, it will stop 
192                 /// searching and return the results to the client. When the client 
193                 /// requests more data, the server will restart the search where it 
194                 /// left off.
195                 /// </remarks>
196                 [DSDescription ("The page size in a paged search.")]
197                 [DefaultValue (0)]
198                 public int PageSize 
199                 {
200                         get
201                         {
202                                 return _PageSize;
203                         }
204                         set
205                         {
206                                 _PageSize =  value;
207                         }
208                 }
209
210                 /// <summary>
211                 /// Gets the set of properties retrieved during the search.
212                 /// </summary>
213                 /// <value>
214                 /// The set of properties retrieved during the search. The default is 
215                 /// an empty StringCollection, which retrieves all properties.
216                 /// </value>
217                 /// <remarks>
218                 /// To retrieve specific properties, add them to this collection 
219                 /// before you begin the search. For example, searcher.
220                 /// PropertiesToLoad.Add("phone");. 
221                 /// </remarks>
222                 [DSDescription ("The set of properties retrieved during the search.")]
223                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
224                 [Editor ("System.Windows.Forms.Design.StringCollectionEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
225                 public StringCollection PropertiesToLoad 
226                 {
227                         get
228                         {
229                                 return _PropertiesToLoad;
230                         }
231                 }
232
233                 /// <summary>
234                 /// Gets or sets a value indicating whether the search retrieves only the 
235                 /// names of attributes to which values have been assigned.
236                 /// </summary>
237                 /// <value>
238                 /// true if the search obtains only the names of attributes to which 
239                 /// values have been assigned; false if the search obtains the names 
240                 /// and values for all the requested attributes. The default is false.
241                 /// </value>
242                 [DSDescription ("A value indicating whether the search retrieves only the names of attributes to which values have been assigned.")]
243                 [DefaultValue (false)]
244                 public bool PropertyNamesOnly 
245                 {
246                         get
247                         {
248                                 return _PropertyNamesOnly;
249                         }
250                         set
251                         {
252                                 _PropertyNamesOnly = value;
253                         }
254                 }
255
256                 /// <summary>
257                 /// Gets or sets how referrals are chased.
258                 /// </summary>
259                 /// <value>
260                 /// One of the ReferralChasingOption values. The default is External.
261                 /// </value>
262                 /// <remarks>
263                 /// If the root search is not specified in the naming context of the 
264                 /// server or when the search results cross a naming context (for 
265                 /// example, when you have child domains and search in the parent 
266                 /// domain), the server sends a referral message to the client that 
267                 /// the client can choose to ignore or chase.
268                 /// </remarks>
269                 [DSDescription ("How referrals are chased.")]
270                 [DefaultValue (ReferralChasingOption.External)]
271                 public ReferralChasingOption ReferralChasing 
272                 {
273                         get
274                         {
275                                 return _ReferralChasing;
276                         }
277                         set
278                         {
279                                 _ReferralChasing = value;
280                         }
281                 }
282
283                 /// <summary>
284                 /// Gets or sets the node in the Ldap Directory hierarchy where the 
285                 /// search starts.
286                 /// </summary>
287                 /// <value>
288                 /// The DirectoryEntry in the Ldap Directory hierarchy where the 
289                 /// search starts. The default is a null reference 
290                 /// </value>
291                 [DSDescription ("The node in the Ldap Directory hierarchy where the search starts.")]
292                 [DefaultValue (null)]
293                 public DirectoryEntry SearchRoot 
294                 {
295                         get
296                         {
297                                 return _SearchRoot;
298                         }
299                         set
300                         {
301                                 _SearchRoot = value;
302                                 ClearCachedResults();
303                         }
304                 }
305
306                 /// <summary>
307                 /// Gets or sets the scope of the search that is observed by the 
308                 /// server.
309                 /// </summary>
310                 /// <value>
311                 /// One of the SearchScope values. The default is Subtree.
312                 /// </value>
313                 [DSDescription ("The scope of the search that is observed by the server.")]
314                 [DefaultValue (SearchScope.Subtree)]
315                 [RecommendedAsConfigurable (true)]
316                 public SearchScope SearchScope 
317                 {
318                         get
319                         {
320                                 return _SearchScope;
321                         }
322                         set
323                         {
324                                 _SearchScope =  value;
325                                 ClearCachedResults();
326                         }
327                 }
328
329                 /// <summary>
330                 /// Gets or sets the time limit the server should observe to search an 
331                 /// individual page of results (as opposed to the time limit for the 
332                 /// entire search).
333                 /// </summary>
334                 /// <value>
335                 /// A TimeSpan that represents the amount of time the server should 
336                 /// observe to search a page of results. The default is -1, which 
337                 /// means to search indefinitely.
338                 /// </value>
339                 /// <remarks>
340                 /// When the time limit is reached, the server stops searching and 
341                 /// returns the result obtained up to that point, along with a cookie
342                 ///  containing the information about where to resume searching.
343                 ///  A negative value means to search indefinitely.
344                 ///             Note:   This property only applies to searches where PageSize 
345                 ///             is set to a value that is not the default of -1.
346                 /// </remarks>
347                 [DSDescription ("The time limit the server should observe to search an individual page of results.")]
348                 public TimeSpan ServerPageTimeLimit 
349                 {
350                         get
351                         {
352                                 return _ServerPageTimeLimit;
353                         }
354                         set
355                         {
356                                 _ServerPageTimeLimit = value;
357                         }
358                 }
359
360                 /// <summary>
361                 /// Gets or sets the time limit the server should observe to search.
362                 /// </summary>
363                 /// <value>
364                 /// A TimeSpan that represents the amount of time the server should 
365                 /// observe to search.
366                 /// </value>
367                 /// <remarks>
368                 /// Not implemented
369                 /// </remarks>
370                 [DSDescription ("The time limit the server should observe to search.")]
371                 public TimeSpan ServerTimeLimit 
372                 {
373                         [MonoTODO]
374                         get
375                         {
376                                 return _serverTimeLimit;
377                         }
378                         [MonoTODO]
379                         set
380                         {
381                                 _serverTimeLimit = value;
382                         }
383                 }
384
385                 /// <summary>
386                 /// Gets or sets the maximum number of objects the server returns in 
387                 /// a search.
388                 /// </summary>
389                 /// <value>
390                 /// The maximum number of objects the server returns in a search. The
391                 /// default of zero means to use the server-determined default size 
392                 /// limit of 1000 entries.
393                 /// </value>
394                 /// <remarks>
395                 /// The server stops searching after the size limit is reached and 
396                 /// returns the results accumulated up to that point.
397                 ///             Note:   If you set SizeLimit to a value that is larger 
398                 ///             than the server-determined default of 1000 entries, the 
399                 ///             server-determined default is used.
400                 /// </remarks>
401                 [DSDescription ("The maximum number of objects the server returns in a search.")]
402                 [DefaultValue (0)]
403                 public int SizeLimit 
404                 {
405                         get
406                         {
407                                 return _SizeLimit;
408                         }
409                         set
410                         {
411                                 if (value < 0) {
412                                         throw new ArgumentException();
413                                 }
414                                 _SizeLimit =  value;
415                         }
416                 }
417
418                 [DSDescription ("An object that defines how the data should be sorted.")]
419                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
420                 [TypeConverter (typeof (ExpandableObjectConverter))]
421                 public SortOption Sort
422                 {
423                         [MonoTODO]
424                         get
425                         {
426                                 throw new NotImplementedException();
427                         }
428                         [MonoTODO]
429                         set
430                         {
431                                 throw new NotImplementedException();
432                         }
433                 }
434
435                 /// <summary>
436                 /// Initializes a new instance of the DirectorySearcher class with 
437                 /// SearchRoot, Filter, PropertiesToLoad, and SearchScope set to the 
438                 /// default values.
439                 /// </summary>
440                 public DirectorySearcher()
441                 {
442                 }
443
444                 /// <summary>
445                 /// Initializes a new instance of the DirectorySearcher class with 
446                 /// Filter, PropertiesToLoad, and SearchScope set to the default 
447                 /// values. SearchRoot is set to the specified value.
448                 /// </summary>
449                 /// <param name="searchRoot">
450                 /// The node in the Active Directory hierarchy where the search starts. 
451                 /// The SearchRoot property is initialized to this value. 
452                 /// </param>
453                 public DirectorySearcher(DirectoryEntry searchRoot)
454                 {
455                         _SearchRoot = searchRoot;
456                 }
457
458                 /// <summary>
459                 /// Initializes a new instance of the DirectorySearcher class with 
460                 /// SearchRoot, PropertiesToLoad, and SearchScope set to the default 
461                 /// values. Filter is set to the specified value.
462                 /// </summary>
463                 /// <param name="filter">
464                 /// The search filter string in Lightweight Directory Access Protocol 
465                 /// (Ldap) format. The Filter property is initialized to this value. 
466                 /// </param>
467                 public DirectorySearcher(string filter)
468                 {
469                         _Filter = filter;
470                 }
471
472                 /// <summary>
473                 /// Initializes a new instance of the DirectorySearcher class with 
474                 /// PropertiesToLoad and SearchScope set to the default values. 
475                 /// SearchRoot and Filter are set to the specified values.
476                 /// </summary>
477                 /// <param name="searchRoot">
478                 /// The node in the Active Directory hierarchy where the search starts. 
479                 /// The SearchRoot property is initialized to this value. 
480                 /// </param>
481                 /// <param name="filter">
482                 /// The search filter string in Lightweight Directory Access Protocol 
483                 /// (Ldap) format. The Filter property is initialized to this value. 
484                 /// </param>
485                 public DirectorySearcher(       DirectoryEntry searchRoot,
486                                                                         string filter   )
487                 {
488                         _SearchRoot = searchRoot;
489                         _Filter = filter;
490                 }
491
492                 /// <summary>
493                 /// Initializes a new instance of the DirectorySearcher class with 
494                 /// SearchRoot and SearchScope set to the default values. Filter and 
495                 /// PropertiesToLoad are set to the specified values.
496                 /// </summary>
497                 /// <param name="filter">
498                 /// The search filter string in Lightweight Directory Access Protocol 
499                 /// (Ldap) format. The Filter property is initialized to this value. 
500                 /// </param>
501                 /// <param name="propertiesToLoad">
502                 /// The set of properties to retrieve during the search. The 
503                 /// PropertiesToLoad property is initialized to this value. 
504                 /// </param>
505                 public DirectorySearcher(       string filter,
506                                                                         string[] propertiesToLoad       )
507                 {
508                         _Filter = filter;
509                         PropertiesToLoad.AddRange(propertiesToLoad);
510                 }
511
512                 /// <summary>
513                 /// Initializes a new instance of the DirectorySearcher class with 
514                 /// SearchScope set to its default value. SearchRoot, Filter, and 
515                 /// PropertiesToLoad are set to the specified values.
516                 /// </summary>
517                 /// <param name="searchRoot">
518                 /// The node in the Active Directory hierarchy where the search starts. 
519                 /// The SearchRoot property is initialized to this value
520                 /// </param>
521                 /// <param name="filter">
522                 /// The search filter string in Lightweight Directory Access Protocol 
523                 /// (Ldap) format. The Filter property is initialized to this value. 
524                 /// </param>
525                 /// <param name="propertiesToLoad">
526                 /// The set of properties retrieved during the search. The 
527                 /// PropertiesToLoad property is initialized to this value. 
528                 /// </param>
529                 public DirectorySearcher(       DirectoryEntry searchRoot,
530                                                                         string filter,
531                                                                         string[] propertiesToLoad       )
532                 {
533                         _SearchRoot = searchRoot;
534                         _Filter = filter;
535                         PropertiesToLoad.AddRange(propertiesToLoad);
536                 }
537
538                 /// <summary>
539                 /// Initializes a new instance of the DirectorySearcher class with 
540                 /// SearchRoot set to its default value. Filter, PropertiesToLoad, 
541                 /// and SearchScope are set to the specified values
542                 /// </summary>
543                 /// <param name="filter">
544                 /// The search filter string in Lightweight Directory Access Protocol 
545                 /// (Ldap) format. The Filter property is initialized to this value.
546                 /// </param>
547                 /// <param name="propertiesToLoad">
548                 /// The set of properties to retrieve during the search. The 
549                 /// PropertiesToLoad property is initialized to this value. 
550                 /// </param>
551                 /// <param name="scope">
552                 /// The scope of the search that is observed by the server. The 
553                 /// SearchScope property is initialized to this value. 
554                 /// </param>
555                 public DirectorySearcher(       string filter,
556                                                                         string[] propertiesToLoad,
557                                                                         SearchScope scope )
558                 {
559                         _SearchScope = scope;
560                         _Filter = filter;
561                         PropertiesToLoad.AddRange(propertiesToLoad);
562                 }
563
564                 /// <summary>
565                 /// Initializes a new instance of the DirectorySearcher class with the
566                 /// SearchRoot, Filter, PropertiesToLoad, and SearchScope properties 
567                 /// set to the specified values
568                 /// </summary>
569                 /// <param name="searchRoot">
570                 /// The node in the Active Directory hierarchy where the search starts. 
571                 /// The SearchRoot property is initialized to this value. 
572                 /// </param>
573                 /// <param name="filter">
574                 /// The search filter string in Lightweight Directory Access Protocol 
575                 /// (Ldap) format. The Filter property is initialized to this value.
576                 /// </param>
577                 /// <param name="propertiesToLoad">
578                 /// The set of properties to retrieve during the search. The 
579                 /// PropertiesToLoad property is initialized to this value. 
580                 /// </param>
581                 /// <param name="scope">
582                 /// The scope of the search that is observed by the server. The 
583                 /// SearchScope property is initialized to this value. 
584                 /// </param>
585                 public DirectorySearcher(       DirectoryEntry searchRoot,
586                                                                         string filter,
587                                                                         string[] propertiesToLoad,
588                                                                         SearchScope scope )
589                 {
590                         _SearchRoot = searchRoot;
591                         _SearchScope = scope;
592                         _Filter = filter;
593                         PropertiesToLoad.AddRange(propertiesToLoad);
594
595                 }
596
597                 /// <summary>
598                 /// Executes the Search and returns only the first entry found
599                 /// </summary>
600                 /// <returns> 
601                 /// A SearchResult that is the first entry found during the Search
602                 /// </returns>
603                 public SearchResult FindOne()
604                 {
605                         // TBD : should search for no more than single result
606                         if (SrchColl.Count == 0) {
607                                 return null;
608                         }
609                         return SrchColl[0];
610                 }
611
612                 /// <summary>
613                 /// Executes the Search and returns a collection of the entries that are found
614                 /// </summary>
615                 /// <returns> 
616                 /// A SearchResultCollection collection of entries from the director
617                 /// </returns>
618                 public SearchResultCollection FindAll()
619                 {
620                         return SrchColl;
621                 }
622
623                 private void DoSearch()
624                 {
625                         InitBlock();
626                         String[] attrs= new String[PropertiesToLoad.Count];
627                         PropertiesToLoad.CopyTo(attrs,0);
628                         
629                         LdapSearchConstraints cons = _conn.SearchConstraints;
630                         if (SizeLimit > 0) {
631                                 cons.MaxResults = SizeLimit;
632                         }
633                         if (ServerTimeLimit != DefaultTimeSpan) {
634                                 cons.ServerTimeLimit = (int)ServerTimeLimit.TotalSeconds;
635                         }
636
637                         int connScope = LdapConnection.SCOPE_SUB;\r
638                         switch (_SearchScope)\r
639                         {\r
640                         case SearchScope.Base:\r
641                           connScope = LdapConnection.SCOPE_BASE;\r
642                           break;\r
643 \r
644                         case SearchScope.OneLevel:\r
645                           connScope = LdapConnection.SCOPE_ONE;\r
646                           break;\r
647 \r
648                         case SearchScope.Subtree:\r
649                           connScope = LdapConnection.SCOPE_SUB;\r
650                           break;\r
651 \r
652                         default:\r
653                           connScope = LdapConnection.SCOPE_SUB;\r
654                           break;\r
655                         }
656                         LdapSearchResults lsc=_conn.Search(     SearchRoot.Fdn,
657                                                                                                 connScope,
658                                                                                                 Filter,
659                                                                                                 attrs,
660                                                                                                 PropertyNamesOnly,cons);
661
662                         while(lsc.hasMore())                                            
663                         {
664                                 LdapEntry nextEntry = null;
665                                 try                                                     
666                                 {
667                                         nextEntry = lsc.next();
668                                 }
669                                 catch(LdapException e)                                                  
670                                 {
671                                         switch (e.ResultCode) {
672                                                 // in case of this return codes exception should not be thrown
673                                                 case LdapException.SIZE_LIMIT_EXCEEDED:
674                                                 case LdapException.TIME_LIMIT_EXCEEDED:
675                                                         continue;
676                                                 default :
677                                                         throw e;
678                                         }
679                                 }
680                                 DirectoryEntry de = new DirectoryEntry(_conn);
681                                 PropertyCollection pcoll = new PropertyCollection();
682 //                              de.SetProperties();
683                                 de.Path = DirectoryEntry.GetLdapUrlString(_Host,_Port,nextEntry.DN); 
684                                 LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
685                                 System.Collections.IEnumerator ienum=attributeSet.GetEnumerator();
686                                 if(ienum!=null)                                                 
687                                 {
688                                         while(ienum.MoveNext())                         
689                                         {
690                                                 LdapAttribute attribute=(LdapAttribute)ienum.Current;
691                                                 string attributeName = attribute.Name;
692                                                 pcoll[attributeName].AddRange(attribute.StringValueArray);
693 //                                              de.Properties[attributeName].AddRange(attribute.StringValueArray);
694 //                                              de.Properties[attributeName].Mbit=false;
695                                         }
696                                 }
697                                 if (!pcoll.Contains("ADsPath")) {
698                                         pcoll["ADsPath"].Add(de.Path);
699                                 }
700 //                              _SrchColl.Add(new SearchResult(de,PropertiesToLoad));
701                                 _SrchColl.Add(new SearchResult(de,pcoll));
702                         }
703                         return;
704                 }
705
706                 [MonoTODO]
707                 protected override void Dispose(bool disposing)
708                 {
709                         if (disposing) {\r
710                                 if(_conn != null && _conn.Connected) {\r
711                                         _conn.Disconnect();\r
712                                 }\r
713                         }\r
714                         base.Dispose(disposing);
715                 }
716
717                 private void ClearCachedResults()
718                 {
719                         _SrchColl = null;
720                 }
721
722         }
723 }
724