(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / System.DirectoryServices / System.DirectoryServices / DirectorySearcher.cs
blob7e9f62d3fdb482c32ac2a4597ad6428279264a5e
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.DirectorySearcher.cs
27 // Authors:
28 // Sunil Kumar (sunilk@novell.com)
29 // Andreas Nahr (ClassDevelopment@A-SoftTech.com)
31 // (C) Novell Inc.
34 using System.ComponentModel;
35 using Novell.Directory.Ldap;
36 using Novell.Directory.Ldap.Utilclass;
37 using System.Collections.Specialized;
39 namespace System.DirectoryServices
42 /// <summary>
43 ///Performs queries against Ldap directory.
44 /// </summary>
45 public class DirectorySearcher : Component
48 private DirectoryEntry _SearchRoot=null;
49 private bool _CacheResults=true;
50 private TimeSpan _ClientTimeout = new TimeSpan(-1);
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=new TimeSpan(-1);
60 private int _SizeLimit=1000;
61 private LdapConnection _conn = null;
62 private string _Host=null;
63 private int _Port=389;
64 private SearchResultCollection _SrchColl=null;
65 private bool emptycoll=true;
67 internal SearchResultCollection SrchColl
69 get
71 if (emptycoll)
73 _SrchColl = new SearchResultCollection();
74 DoSearch();
75 emptycoll=false;
77 return _SrchColl;
81 private void InitBlock()
83 _conn = new LdapConnection();
84 LdapUrl lUrl=new LdapUrl(SearchRoot.Path);
85 _Host=lUrl.Host;
86 _Port=lUrl.Port;
87 _conn.Connect(_Host,_Port);
88 _conn.Bind(SearchRoot.Username,SearchRoot.Password);
92 /// <summary>
93 /// Gets or sets a value indicating whether the result is
94 /// cached on the client computer.
95 /// </summary>
96 /// <value>
97 /// true if the result is cached on the client computer; otherwise,
98 /// false. The default is true
99 /// </value>
100 /// <remarks>
101 /// If the search returns a large result set, it is better to set
102 /// this property to false.
103 /// </remarks>
104 [DSDescription ("The cacheability of results.")]
105 [DefaultValue (true)]
106 public bool CacheResults
110 return _CacheResults;
114 CacheResults = value;
118 /// <summary>
119 /// Gets or sets the maximum amount of time that the client waits for
120 /// the server to return results. If the server does not respond
121 /// within this time, the search is aborted and no results are
122 /// returned.
123 /// </summary>
124 /// <value>
125 /// A TimeSpan that represents the maximum amount of time (in seconds)
126 /// for the client to wait for the server to return results. The
127 /// default is -1, which means to wait indefinitely.
128 /// </value>
129 /// <remarks>
130 /// If the ServerTimeLimit is reached before the client times out,
131 /// the server returns its results and the client stops waiting. The
132 /// maximum server time limit is 120 seconds.
133 /// </remarks>
134 [DSDescription ("The maximum amount of time that the client waits for the server to return results.")]
135 public TimeSpan ClientTimeout
139 return _ClientTimeout;
143 _ClientTimeout = value;
147 /// <summary>
148 /// Gets or sets the Lightweight Directory Access Protocol (Ldap)
149 /// format filter string.
150 /// </summary>
151 /// <value>
152 /// The search filter string in Ldap format, such as
153 /// "(objectClass=user)". The default is "(objectClass=*)", which
154 /// retrieves all objects.
155 /// </value>
156 /// <remarks>
157 /// The filter uses the following guidelines:
158 /// 1. The string must be enclosed in parentheses.
159 /// 2. Expressions can use the relational operators: <, <=, =, >=,
160 /// and >. An example is "(objectClass=user)". Another example is
161 /// "(lastName>=Davis)".
162 /// 3. Compound expressions are formed with the prefix operators &
163 /// and |. Anexampleis"(&(objectClass=user)(lastName= Davis))".
164 /// Anotherexampleis"(&(objectClass=printer)(|(building=42)
165 /// (building=43)))".
166 /// </remarks>
167 [DSDescription ("The Lightweight Directory Access Protocol (Ldap) format filter string.")]
168 [DefaultValue ("(objectClass=*)")]
169 [RecommendedAsConfigurable (true)]
170 [TypeConverter ("System.Diagnostics.Design.StringValueConverter, " + Consts.AssemblySystem_Design)]
171 public string Filter
175 return _Filter;
179 _Filter = value;
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
202 return _PageSize;
206 _PageSize = value;
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
229 return _PropertiesToLoad;
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
248 return _PropertyNamesOnly;
252 _PropertyNamesOnly = value;
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
275 return _ReferralChasing;
279 _ReferralChasing = value;
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
297 return _SearchRoot;
301 _SearchRoot = value;
305 /// <summary>
306 /// Gets or sets the scope of the search that is observed by the
307 /// server.
308 /// </summary>
309 /// <value>
310 /// One of the SearchScope values. The default is Subtree.
311 /// </value>
312 [DSDescription ("The scope of the search that is observed by the server.")]
313 [DefaultValue (SearchScope.Subtree)]
314 [RecommendedAsConfigurable (true)]
315 public SearchScope SearchScope
319 return _SearchScope;
323 _SearchScope = value;
327 /// <summary>
328 /// Gets or sets the time limit the server should observe to search an
329 /// individual page of results (as opposed to the time limit for the
330 /// entire search).
331 /// </summary>
332 /// <value>
333 /// A TimeSpan that represents the amount of time the server should
334 /// observe to search a page of results. The default is -1, which
335 /// means to search indefinitely.
336 /// </value>
337 /// <remarks>
338 /// When the time limit is reached, the server stops searching and
339 /// returns the result obtained up to that point, along with a cookie
340 /// containing the information about where to resume searching.
341 /// A negative value means to search indefinitely.
342 /// Note: This property only applies to searches where PageSize
343 /// is set to a value that is not the default of -1.
344 /// </remarks>
345 [DSDescription ("The time limit the server should observe to search an individual page of results.")]
346 public TimeSpan ServerPageTimeLimit
350 return _ServerPageTimeLimit;
354 _ServerPageTimeLimit = value;
358 /// <summary>
359 /// Gets or sets the time limit the server should observe to search.
360 /// </summary>
361 /// <value>
362 /// A TimeSpan that represents the amount of time the server should
363 /// observe to search.
364 /// </value>
365 /// <remarks>
366 /// Not implemented
367 /// </remarks>
368 [DSDescription ("The time limit the server should observe to search.")]
369 public TimeSpan ServerTimeLimit
371 [MonoTODO]
374 throw new NotImplementedException();
376 [MonoTODO]
379 throw new NotImplementedException();
383 /// <summary>
384 /// Gets or sets the maximum number of objects the server returns in
385 /// a search.
386 /// </summary>
387 /// <value>
388 /// The maximum number of objects the server returns in a search. The
389 /// default of zero means to use the server-determined default size
390 /// limit of 1000 entries.
391 /// </value>
392 /// <remarks>
393 /// The server stops searching after the size limit is reached and
394 /// returns the results accumulated up to that point.
395 /// Note: If you set SizeLimit to a value that is larger
396 /// than the server-determined default of 1000 entries, the
397 /// server-determined default is used.
398 /// </remarks>
399 [DSDescription ("The maximum number of objects the server returns in a search.")]
400 [DefaultValue (0)]
401 public int SizeLimit
405 return _SizeLimit;
409 _SizeLimit = value;
413 [DSDescription ("An object that defines how the data should be sorted.")]
414 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
415 [TypeConverter (typeof (ExpandableObjectConverter))]
416 public SortOption Sort
418 [MonoTODO]
421 throw new NotImplementedException();
423 [MonoTODO]
426 throw new NotImplementedException();
430 /// <summary>
431 /// Initializes a new instance of the DirectorySearcher class with
432 /// SearchRoot, Filter, PropertiesToLoad, and SearchScope set to the
433 /// default values.
434 /// </summary>
435 public DirectorySearcher()
439 /// <summary>
440 /// Initializes a new instance of the DirectorySearcher class with
441 /// Filter, PropertiesToLoad, and SearchScope set to the default
442 /// values. SearchRoot is set to the specified value.
443 /// </summary>
444 /// <param name="searchRoot">
445 /// The node in the Active Directory hierarchy where the search starts.
446 /// The SearchRoot property is initialized to this value.
447 /// </param>
448 public DirectorySearcher(DirectoryEntry searchRoot)
450 _SearchRoot = searchRoot;
453 /// <summary>
454 /// Initializes a new instance of the DirectorySearcher class with
455 /// SearchRoot, PropertiesToLoad, and SearchScope set to the default
456 /// values. Filter is set to the specified value.
457 /// </summary>
458 /// <param name="filter">
459 /// The search filter string in Lightweight Directory Access Protocol
460 /// (Ldap) format. The Filter property is initialized to this value.
461 /// </param>
462 public DirectorySearcher(string filter)
464 _Filter = filter;
467 /// <summary>
468 /// Initializes a new instance of the DirectorySearcher class with
469 /// PropertiesToLoad and SearchScope set to the default values.
470 /// SearchRoot and Filter are set to the specified values.
471 /// </summary>
472 /// <param name="searchRoot">
473 /// The node in the Active Directory hierarchy where the search starts.
474 /// The SearchRoot property is initialized to this value.
475 /// </param>
476 /// <param name="filter">
477 /// The search filter string in Lightweight Directory Access Protocol
478 /// (Ldap) format. The Filter property is initialized to this value.
479 /// </param>
480 public DirectorySearcher( DirectoryEntry searchRoot,
481 string filter )
483 _SearchRoot = searchRoot;
484 _Filter = filter;
487 /// <summary>
488 /// Initializes a new instance of the DirectorySearcher class with
489 /// SearchRoot and SearchScope set to the default values. Filter and
490 /// PropertiesToLoad are set to the specified values.
491 /// </summary>
492 /// <param name="filter">
493 /// The search filter string in Lightweight Directory Access Protocol
494 /// (Ldap) format. The Filter property is initialized to this value.
495 /// </param>
496 /// <param name="propertiesToLoad">
497 /// The set of properties to retrieve during the search. The
498 /// PropertiesToLoad property is initialized to this value.
499 /// </param>
500 public DirectorySearcher( string filter,
501 string[] propertiesToLoad )
503 _Filter = filter;
504 PropertiesToLoad.AddRange(propertiesToLoad);
507 /// <summary>
508 /// Initializes a new instance of the DirectorySearcher class with
509 /// SearchScope set to its default value. SearchRoot, Filter, and
510 /// PropertiesToLoad are set to the specified values.
511 /// </summary>
512 /// <param name="searchRoot">
513 /// The node in the Active Directory hierarchy where the search starts.
514 /// The SearchRoot property is initialized to this value
515 /// </param>
516 /// <param name="filter">
517 /// The search filter string in Lightweight Directory Access Protocol
518 /// (Ldap) format. The Filter property is initialized to this value.
519 /// </param>
520 /// <param name="propertiesToLoad">
521 /// The set of properties retrieved during the search. The
522 /// PropertiesToLoad property is initialized to this value.
523 /// </param>
524 public DirectorySearcher( DirectoryEntry searchRoot,
525 string filter,
526 string[] propertiesToLoad )
528 _SearchRoot = searchRoot;
529 _Filter = filter;
530 PropertiesToLoad.AddRange(propertiesToLoad);
533 /// <summary>
534 /// Initializes a new instance of the DirectorySearcher class with
535 /// SearchRoot set to its default value. Filter, PropertiesToLoad,
536 /// and SearchScope are set to the specified values
537 /// </summary>
538 /// <param name="filter">
539 /// The search filter string in Lightweight Directory Access Protocol
540 /// (Ldap) format. The Filter property is initialized to this value.
541 /// </param>
542 /// <param name="propertiesToLoad">
543 /// The set of properties to retrieve during the search. The
544 /// PropertiesToLoad property is initialized to this value.
545 /// </param>
546 /// <param name="scope">
547 /// The scope of the search that is observed by the server. The
548 /// SearchScope property is initialized to this value.
549 /// </param>
550 public DirectorySearcher( string filter,
551 string[] propertiesToLoad,
552 SearchScope scope )
554 _SearchScope = scope;
555 _Filter = filter;
556 PropertiesToLoad.AddRange(propertiesToLoad);
559 /// <summary>
560 /// Initializes a new instance of the DirectorySearcher class with the
561 /// SearchRoot, Filter, PropertiesToLoad, and SearchScope properties
562 /// set to the specified values
563 /// </summary>
564 /// <param name="searchRoot">
565 /// The node in the Active Directory hierarchy where the search starts.
566 /// The SearchRoot property is initialized to this value.
567 /// </param>
568 /// <param name="filter">
569 /// The search filter string in Lightweight Directory Access Protocol
570 /// (Ldap) format. The Filter property is initialized to this value.
571 /// </param>
572 /// <param name="propertiesToLoad">
573 /// The set of properties to retrieve during the search. The
574 /// PropertiesToLoad property is initialized to this value.
575 /// </param>
576 /// <param name="scope">
577 /// The scope of the search that is observed by the server. The
578 /// SearchScope property is initialized to this value.
579 /// </param>
580 public DirectorySearcher( DirectoryEntry searchRoot,
581 string filter,
582 string[] propertiesToLoad,
583 SearchScope scope )
585 _SearchRoot = searchRoot;
586 _SearchScope = scope;
587 _Filter = filter;
588 PropertiesToLoad.AddRange(propertiesToLoad);
592 /// <summary>
593 /// Executes the Search and returns only the first entry found
594 /// </summary>
595 /// <returns>
596 /// A SearchResult that is the first entry found during the Search
597 /// </returns>
598 public SearchResult FindOne()
600 return SrchColl[0];
603 /// <summary>
604 /// Executes the Search and returns a collection of the entries that are found
605 /// </summary>
606 /// <returns>
607 /// A SearchResultCollection collection of entries from the director
608 /// </returns>
609 public SearchResultCollection FindAll()
611 return SrchColl;
614 private void DoSearch()
616 InitBlock();
617 String[] attrs= new String[PropertiesToLoad.Count];
618 PropertiesToLoad.CopyTo(attrs,0);
619 LdapSearchResults lsc=_conn.Search( SearchRoot.Fdn,
620 LdapConnection.SCOPE_SUB,
621 Filter,
622 attrs,
623 false);
625 while(lsc.hasMore())
628 LdapEntry nextEntry = null;
629 try
631 nextEntry = lsc.next();
633 catch(LdapException e)
635 Console.WriteLine("Error: " + e.LdapErrorMessage);
636 // Exception is thrown, go for next entry
637 throw e;
639 DirectoryEntry de = new DirectoryEntry(_conn);
640 PropertyCollection pcoll = new PropertyCollection();
641 // de.SetProperties();
642 de.Path="LDAP://" + _Host+ ":" + _Port + "/" + nextEntry.DN;
643 LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
644 System.Collections.IEnumerator ienum=attributeSet.GetEnumerator();
645 if(ienum!=null)
647 while(ienum.MoveNext())
649 LdapAttribute attribute=(LdapAttribute)ienum.Current;
650 string attributeName = attribute.Name;
651 pcoll[attributeName].AddRange(attribute.StringValueArray);
652 // de.Properties[attributeName].AddRange(attribute.StringValueArray);
653 // de.Properties[attributeName].Mbit=false;
656 // _SrchColl.Add(new SearchResult(de,PropertiesToLoad));
657 _SrchColl.Add(new SearchResult(de,pcoll));
659 return;
662 [MonoTODO]
663 protected override void Dispose(bool disposing)
665 throw new NotImplementedException();