Hello Sébastien,
I've finished implementing the default ldap server feature (currently
waiting for devlist approval) and I've also made an example for defining
default ldap server configuration.(attached are an example file and the
proposed patch for the case you missed my mail to the devlist).
The main point if the change is: if user does not specifies a path of an
entry, the entry should point to default ldap server on the network
(actually, to default naming context of the default ldap server). The
default naming context can be retrieved from the server rootDse entry,
so the only information we need to provide a desired functionality is a
default ldap server host and port.
User does not have to provide his own configuration: the default
configuration (absence of user configuration file) means "use
localhost:389". User _can_ overwrite this with his own values using app
config or machine config.
Is the "root" System.DirectoryServices is the best place to place an
example and the explanation file?
Should also user configuration file reside there (since, for example,
the tests run by default in this directory).
The second point is that DirectoryServices tests require environment
variable of (some, not necessary the default) ldap server to run on.
So, the tests logic can possibly be: if no environment variable present,
test prints warning message and silently passes(or, maybe, fails?). If
someone wants to run this tests, he should define both environment
variable and a user configuration file (or configure the host running
these tests to act also as a default ldap server)
What do you think about this?
Thanks,
Boris
Sébastien Pouliot wrote:
Hello Boris,
I understand that use of machine.config or app.config is far from ideal,
but at least it can provide us with a basic solution.
When things gets too complicated people quit. I don't think many people are
gonna be runned the LDAP tests but I wouldn't want to discourage anyone. So
the easier the better ;-)
Why don't keep the environment variable (very simple) and point it to a
configuration file (XML or plain ASCII) ?
That would mean:
* that, by default, all non-network tests in System.DirectoryServices.dll
will be executed (here I'm thinking about the few permissions tests already
present _and_ future CAS tests);
* it would be possible to check into SVN a configuration sample file that
any user can copy (so it won't get in conflict with SVN) and edit;
* it would be possible to have multiple configuration files, e.g. if you
want to test against different LDAP servers (machine or software);
* all configuration could be done in a single place whatever the
runtime/version you are using.
Do you think there is a better way to provide a "default" behavior,
either at DirectoryServices or Ldap level, such that it will be easily
configured for each client application?
The trivial solution - default is "LDAP://localhost:389", does not looks
satisfactory and, in addition, does not provides a solution for base dsn.
Without a valid configuration file I would simply ignore all tests
(requiring a server). This is similar to what I'm doing for the CAS tests.
If someone doesn't exclude them (default for "make run-test") and doesn't
supply --security to the mono runtime, then they are all ignore (and nicely
nunit still shows them as ignored when they aren't excluded).
Sebastien Pouliot
home: [EMAIL PROTECTED]
blog: http://pages.infinit.net/ctech/poupou.html
--
Boris Kirzner
Mainsoft Corporation
http://www.mainsoft.com
Index: Assembly/AssemblyInfo.cs
===================================================================
--- Assembly/AssemblyInfo.cs (revision 45938)
+++ Assembly/AssemblyInfo.cs (working copy)
@@ -42,6 +42,8 @@
[assembly: ComVisible(false)]
+#if (!TARGET_JVM)
[assembly: AssemblyDelaySign(true)]
[assembly: AssemblyKeyFile("../msfinal.pub")]
+#endif
Index: Assembly/ChangeLog
===================================================================
--- Assembly/ChangeLog (revision 45938)
+++ Assembly/ChangeLog (working copy)
@@ -1,3 +1,6 @@
+2005-06-19 Boris Kirzner <[EMAIL PROTECTED]>
+ * AssemblyInfo.cs: Added #ifdef on attributes not used in TARGET_JVM.
+
2004-01-15 Andreas Nahr <[EMAIL PROTECTED]>
* Locale.cs: Added
Index: Test/System.DirectoryServices/DirectoryServicesSearchResultTest.cs
===================================================================
--- Test/System.DirectoryServices/DirectoryServicesSearchResultTest.cs
(revision 45938)
+++ Test/System.DirectoryServices/DirectoryServicesSearchResultTest.cs
(working copy)
@@ -261,16 +261,20 @@
SearchResultCollection results = ds.FindAll();
- Assert.AreEqual(results[0].Path,LDAPServerRoot +
"dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(results[0].Path.ToLower(),(LDAPServerRoot +
"dc=myhosting,dc=example").ToLower());
Assert.AreEqual(results[0].Path,results[0].GetDirectoryEntry().Path);
- Assert.AreEqual(results[1].Path,LDAPServerRoot +
"ou=people,dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(results[1].Path.ToLower(),(LDAPServerRoot +
"ou=people,dc=myhosting,dc=example").ToLower());
Assert.AreEqual(results[1].Path,results[1].GetDirectoryEntry().Path);
- Assert.AreEqual(results[2].Path,LDAPServerRoot +
"ou=Human Resources,ou=people,dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(results[2].Path.ToLower(),(LDAPServerRoot + "ou=Human
Resources,ou=people,dc=myhosting,dc=example").ToLower());
Assert.AreEqual(results[2].Path,results[2].GetDirectoryEntry().Path);
- Assert.AreEqual(results[3].Path,LDAPServerRoot +
"cn=John Smith,ou=Human Resources,ou=people,dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(results[3].Path.ToLower(),(LDAPServerRoot + "cn=John
Smith,ou=Human Resources,ou=people,dc=myhosting,dc=example").ToLower());
Assert.AreEqual(results[3].Path,results[3].GetDirectoryEntry().Path);
}
@@ -323,7 +327,8 @@
Assert.AreEqual(((ResultPropertyValueCollection)result.Properties["cn"])[0],"Barak
Tsabari");
Assert.AreEqual(((ResultPropertyValueCollection)result.Properties["objectClass"])[0],"person");
-
Assert.AreEqual(((ResultPropertyValueCollection)result.Properties["AdsPath"])[0],LDAPServerRoot
+ "cn=Barak Tsabari,ou=Human Resources,ou=people,dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(((string)((ResultPropertyValueCollection)result.Properties["AdsPath"])[0]).ToLower(),(LDAPServerRoot
+ "cn=Barak Tsabari,ou=Human
Resources,ou=people,dc=myhosting,dc=example").ToLower());
}
#endregion Tests
Index: Test/System.DirectoryServices/DirectoryServicesDirectoryEntryTest.cs
===================================================================
--- Test/System.DirectoryServices/DirectoryServicesDirectoryEntryTest.cs
(revision 45938)
+++ Test/System.DirectoryServices/DirectoryServicesDirectoryEntryTest.cs
(working copy)
@@ -1029,21 +1029,24 @@
{
de = new DirectoryEntry(LDAPServerConnectionString);
- Assert.AreEqual(de.Parent.Path,LDAPServerRoot +
"dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(de.Parent.Path.ToLower(),(LDAPServerRoot +
"dc=example").ToLower());
de = new DirectoryEntry(LDAPServerConnectionString,
LDAPServerUsername,
LDAPServerPassword,
AuthenticationTypes.ServerBind);
- Assert.AreEqual(de.Parent.Path,LDAPServerRoot +
"dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(de.Parent.Path.ToLower(),(LDAPServerRoot +
"dc=example").ToLower());
de = new DirectoryEntry(LDAPServerRoot + "cn=Barak
Tsabari,ou=Human Resources,ou=people,dc=myhosting,dc=example" ,
LDAPServerUsername,
LDAPServerPassword,
AuthenticationTypes.ServerBind);
- Assert.AreEqual(de.Parent.Path,LDAPServerRoot +
"ou=Human Resources,ou=people,dc=myhosting,dc=example");
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(de.Parent.Path.ToLower(),(LDAPServerRoot + "ou=Human
Resources,ou=people,dc=myhosting,dc=example").ToLower());
}
@@ -1138,6 +1141,12 @@
de.Path = wrongPath;
Assert.AreEqual(de.Path,wrongPath);
+
+ de = new
DirectoryEntry("ldap://myhost:389/ou=people",null,null,AuthenticationTypes.None);
+ Assert.AreEqual(de.Path,"ldap://myhost:389/ou=people");
+
+ de.Path = null;
+ Assert.AreEqual(de.Path,String.Empty);
}
@@ -1272,20 +1281,21 @@
[Test]
public void DirectoryEntry_SchemaEntry()
{
- // de = new DirectoryEntry();
- // DirectoryEntry schemaEntry =
de.SchemaEntry;
- //
- //
Assert.AreEqual(schemaEntry.Path,"LDAP://schema/domainDNS");
- //
Assert.AreEqual(schemaEntry.Name,"domainDNS");
- //
Assert.AreEqual(schemaEntry.Username,null);
- //
Assert.AreEqual(schemaEntry.Password,null);
- //
Assert.AreEqual(schemaEntry.UsePropertyCache,true);
- //
Assert.AreEqual(schemaEntry.SchemaClassName,"Class");
- //
Assert.AreEqual(schemaEntry.AuthenticationType,AuthenticationTypes.None);
+ de = new DirectoryEntry();
+ DirectoryEntry schemaEntry = de.SchemaEntry;
+ // MS works only with "LDAP" while RFC2255 states "ldap"
+
Assert.AreEqual(schemaEntry.Path.ToLower(),"LDAP://schema/domainDNS".ToLower());
+ Assert.AreEqual(schemaEntry.Name,"domainDNS");
+ Assert.AreEqual(schemaEntry.Username,null);
+ Assert.AreEqual(schemaEntry.Password,null);
+ Assert.AreEqual(schemaEntry.UsePropertyCache,true);
+ Assert.AreEqual(schemaEntry.SchemaClassName,"Class");
+
Assert.AreEqual(schemaEntry.AuthenticationType,AuthenticationTypes.None);
+
de = new DirectoryEntry(LDAPServerConnectionString);
- DirectoryEntry schemaEntry = de.SchemaEntry;
+ schemaEntry = de.SchemaEntry;
Assert.AreEqual(schemaEntry.Path,LDAPServerRoot +
"schema/organization");
Assert.AreEqual(schemaEntry.Name,"organization");
Index: Test/System.DirectoryServices/ChangeLog
===================================================================
--- Test/System.DirectoryServices/ChangeLog (revision 45938)
+++ Test/System.DirectoryServices/ChangeLog (working copy)
@@ -1,3 +1,10 @@
+2005-06-19 Boris Kirzner <[EMAIL PROTECTED]>
+ * DirectoryServicesSearchResultTest.cs: since MS works only with "LDAP"
while RFC2255 states "ldap", use lowercase comparing on ldap urls.
+ * DirectoryServicesDirectoryEntryTest.cs:
+ - Since MS works only with "LDAP" while RFC2255 states "ldap",
use lowercase comparing on ldap urls.
+ - Added more Path tests.
+ - Uncommented SchemaEntry tests.
+
2005-06-01 Sebastien Pouliot <[EMAIL PROTECTED]>
* DirectoryServicesPermissionTest.cs: IsSubset(null) has a different
Index: App.config
===================================================================
--- App.config (revision 0)
+++ App.config (revision 0)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Example app.config file for specifying default LDAP server information -->
+<configuration>
+ <configSections>
+ <sectionGroup name="System.DirectoryServices">
+ <section name="Settings"
type="System.Configuration.NameValueSectionHandler"/>
+ </sectionGroup>
+ </configSections>
+
+ <System.DirectoryServices>
+ <Settings>
+ <add key="servername" value="xp050"/>
+ <add key="port" value="389"/>
+ </Settings>
+ </System.DirectoryServices>
+</configuration>
Index: System.DirectoryServices_test.dll.sources
===================================================================
--- System.DirectoryServices_test.dll.sources (revision 45938)
+++ System.DirectoryServices_test.dll.sources (working copy)
@@ -1,2 +1,6 @@
System.DirectoryServices/DirectoryServicesPermissionAttributeTest.cs
System.DirectoryServices/DirectoryServicesPermissionTest.cs
+System.DirectoryServices/DirectoryServicesDirectoryEntryTest.cs
+System.DirectoryServices/DirectoryServicesDirectorySearcherTest.cs
+System.DirectoryServices/DirectoryServicesSearchResultTest.cs
+
Index: ChangeLog
===================================================================
--- ChangeLog (revision 45938)
+++ ChangeLog (working copy)
@@ -1,3 +1,7 @@
+2005-06-19 Boris Kirzner <[EMAIL PROTECTED]>
+ * System.DirectoryServices_test.dll.sources: added
DirectoryServicesDirectoryEntryTest.cs,/DirectoryServicesDirectorySearcherTest.cs,DirectoryServicesSearchResultTest.cs
+ * App.config - added new file, contaning an example of specifying
default LDAP server information in app config.
+
2005-02-14 Anil Bhatia <[EMAIL PROTECTED]>
* Fixed DoSearch() in DirectorySearcher.cs: Search scope was hardcoded
as LdapConnection.SCOPE_SUB. Chnaged to the value contained by
Index: System.DirectoryServices/DirectorySearcher.cs
===================================================================
--- System.DirectoryServices/DirectorySearcher.cs (revision 45939)
+++ System.DirectoryServices/DirectorySearcher.cs (working copy)
@@ -80,7 +80,7 @@
private void InitBlock()
{
_conn = new LdapConnection();
- LdapUrl lUrl=new LdapUrl(SearchRoot.Path);
+ LdapUrl lUrl=new LdapUrl(SearchRoot.ADsPath);
_Host=lUrl.Host;
_Port=lUrl.Port;
_conn.Connect(_Host,_Port);
@@ -657,7 +657,7 @@
connScope,
Filter,
attrs,
-
false,cons);
+
PropertyNamesOnly,cons);
while(lsc.hasMore())
{
@@ -680,7 +680,7 @@
DirectoryEntry de = new DirectoryEntry(_conn);
PropertyCollection pcoll = new
PropertyCollection();
// de.SetProperties();
- de.Path="LDAP://" + _Host+ ":" + _Port + "/" +
nextEntry.DN;
+ de.Path =
DirectoryEntry.GetLdapUrlString(_Host,_Port,nextEntry.DN);
LdapAttributeSet attributeSet =
nextEntry.getAttributeSet();
System.Collections.IEnumerator
ienum=attributeSet.GetEnumerator();
if(ienum!=null)
Index: System.DirectoryServices/ChangeLog
===================================================================
--- System.DirectoryServices/ChangeLog (revision 45939)
+++ System.DirectoryServices/ChangeLog (working copy)
@@ -1,3 +1,23 @@
+2005-06-19 Boris Kirzner <[EMAIL PROTECTED]>
+ * DirectorySearcher.cs:
+ - Use ADsPath property (always represents an actual url)
instead of Path (may be null or empty string).
+ - Use PropertyNamesOnly property while perfoming search, so
property values retrieved only when needed.
+ - Create parent path in more clean way.
+ * DirectoryEntry.cs:
+ - Use ADsPath property (always represents an actual url)
instead of Path (may be null or empty string).
+ - InitEntry takes special care about rootDse entries.
+ - Path return empty string if assigned to null.
+ - Added ADsPath property. This is an "actual" entry path on the
server. If user does not specifies a path, it is resolved usinf rootDse server
entry properties. We need this since the user-specified PAth property should
never change.
+ - Added GetProperties,SetProperties and LoadProperties methods
to handle internal properties load and assignment.
+ - Added DefaultHost and DefaultPort properties, so user can
specify the default LDAP server information using app config. If user does not
specify it, the localhost:389 is the default.
+ - Added InitToRootDse method - initializes current entry to
specified server rootDse entry.
+ - CheckEntry takes special care about rootDse entries.
+ - CommitEntry rewrited to use .NET style iteration. In
addition, the method uses entry peroperties whout enforsing their reload.
+ - Implemented RefreshCache methods.
+ - Added method GetLdapUrlString, returns LDAP URL string
representation that omits default port (i.e. ldap://server/dn instead of
ldap://server:389/dn), as .NET does.
+ * PropertyValueCollection.cs: removed redundant MonoTodo attributes.
+ * SearchResult.cs: if underlined result properties collection is empty,
do not try lto load a properties from it.
+
2005-06-14 Boris Kirzner <[EMAIL PROTECTED]>
* DirectorySearcher.cs : AdsPath property should not appear in the
query, but it still should appear in the SearchResult properties (by
initialization from result entry path).
Index: System.DirectoryServices/DirectoryEntry.cs
===================================================================
--- System.DirectoryServices/DirectoryEntry.cs (revision 45938)
+++ System.DirectoryServices/DirectoryEntry.cs (working copy)
@@ -27,6 +27,7 @@
// Authors:
// Sunil Kumar ([EMAIL PROTECTED])
// Andreas Nahr ([EMAIL PROTECTED])
+// Boris Kirzner ([EMAIL PROTECTED])
//
// (C) Novell Inc.
//
@@ -36,6 +37,8 @@
using Novell.Directory.Ldap.Utilclass;
using System.Globalization;
using System.DirectoryServices.Design;
+using System.Collections.Specialized;
+using System.Configuration;
namespace System.DirectoryServices
{
@@ -46,7 +49,9 @@
[TypeConverter (typeof (DirectoryEntryConverter))]
public class DirectoryEntry : Component
{
-
+ private static readonly string DEFAULT_LDAP_HOST =
"System.DirectoryServices.DefaultLdapHost";
+ private static readonly string DEFAULT_LDAP_PORT =
"System.DirectoryServices.DefaultLdapPort";
+
private LdapConnection _conn = null;
private AuthenticationTypes
_AuthenticationType=AuthenticationTypes.None;
private DirectoryEntries _Children;
@@ -70,12 +75,12 @@
{
get {
if (_Fdn == null) {
- LdapUrl lUrl = new LdapUrl(Path);
+ LdapUrl lUrl = new LdapUrl (ADsPath);
string fDn=lUrl.getDN();
if(fDn != null)
_Fdn = fDn;
else
- _Fdn="";
+ _Fdn=String.Empty;
}
return _Fdn;
}
@@ -119,7 +124,7 @@
{
try {
_conn= new LdapConnection ();
- LdapUrl lUrl=new LdapUrl (Path);
+ LdapUrl lUrl = new LdapUrl (ADsPath);
_conn.Connect(lUrl.Host,lUrl.Port);
_conn.Bind(Username,Password);
}
@@ -135,15 +140,19 @@
/// Initializes the Entry specific properties e.g entry DN etc.
/// </summary>
void InitEntry()
- {
- LdapUrl lUrl=new LdapUrl (Path);
- if(lUrl.getDN()!=null) {
- DN userDn = new DN(lUrl.getDN());
+ {
+ LdapUrl lUrl = new LdapUrl (ADsPath);
+ string dn = lUrl.getDN();
+ if (dn != null ) {
+ if (String.Compare (dn,"rootDSE",true) == 0)
+ InitToRootDse (lUrl.Host,lUrl.Port);
+ else {
+ DN userDn = new DN (dn);
String[] lRdn = userDn.explodeDN(false);
_Name = (string)lRdn[0];
_Parent = new DirectoryEntry(conn);
- LdapUrl cUrl=new
LdapUrl(lUrl.Host,lUrl.Port,userDn.Parent.ToString());
- _Parent.Path=cUrl.ToString();
+ _Parent.Path = GetLdapUrlString
(lUrl.Host,lUrl.Port,userDn.Parent.ToString ());
+ }
}
else {
_Name=lUrl.Host+":"+lUrl.Port;
@@ -273,7 +282,7 @@
{
get
{
- _Children = new DirectoryEntries(Path, conn);
+ _Children = new DirectoryEntries(ADsPath, conn);
return _Children;
}
}
@@ -314,7 +323,7 @@
{
get
{
if(_Name==null) {
- if(CheckEntry(conn,Path))
+ if(CheckEntry(conn,ADsPath))
InitEntry();
else
throw new
SystemException("There is no such object on the server");
@@ -334,7 +343,7 @@
{
get {
if(_Parent==null)
{
- if(CheckEntry(conn,Path))
+ if(CheckEntry(conn,ADsPath))
InitEntry();
else
throw new
SystemException("There is no such object on the server");
@@ -484,9 +493,28 @@
return _Path;
}
set {
- _Path = value;
+ if (value == null)
+ _Path = String.Empty;
+ else
+ _Path = value;
}
+ }
+ internal string ADsPath
+ {
+ get {
+ if (Path == null || Path == String.Empty) {
+ DirectoryEntry rootDse = new
DirectoryEntry ();
+ rootDse.InitToRootDse (null,-1);
+ string namingContext = (string)
rootDse.Properties ["defaultNamingContext"].Value;
+ if ( namingContext == null )
+ namingContext = (string)
rootDse.Properties ["namingContexts"].Value;
+
+ LdapUrl actualUrl= new LdapUrl
(DefaultHost,DefaultPort,namingContext);
+ return actualUrl.ToString ();
+ }
+ return Path;
+ }
}
/// <summary>
@@ -501,51 +529,7 @@
public PropertyCollection Properties
{
get {
- if ( _Properties == null )
{
-
- _Properties = new
PropertyCollection(this);
- _inPropertiesLoading = true;
-
- try
{
- LdapSearchResults
lsc=conn.Search( Fdn,
-
LdapConnection.SCOPE_BASE,
-
"objectClass=*",
-
null,
-
false);
- while(lsc.hasMore())
{
-
- LdapEntry nextEntry =
null;
- try
{
- nextEntry =
lsc.next();
- }
- catch(LdapException e)
{
- // Exception is
thrown, go for next entry
- throw e;
- }
- LdapAttributeSet
attributeSet = nextEntry.getAttributeSet();
-
System.Collections.IEnumerator ienum=attributeSet.GetEnumerator();
- if(ienum!=null)
{
-
while(ienum.MoveNext()) {
-
LdapAttribute attribute=(LdapAttribute)ienum.Current;
- string
attributeName = attribute.Name;
-
_Properties[attributeName].AddRange(attribute.StringValueArray);
-
_Properties[attributeName].Mbit=false;
- //
string attributeVal =
attribute.StringValue;
- //
_Properties[attributeName].Add(attributeVal);
- }
- }
- break;
- }
- }
- catch( LdapException le)
{
- if(le.ResultCode ==
LdapException.NO_SUCH_OBJECT)
- { }
- }
- finally {
- _inPropertiesLoading = false;
- }
- }
- return _Properties;
+ return GetProperties (true);
}
}
@@ -579,12 +563,134 @@
public DirectoryEntry SchemaEntry
{
[MonoTODO]
- get {
+ get {
throw new NotImplementedException();
}
}
+ private string DefaultHost
+ {
+ get {
+ string defaultHost = (string)
AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_HOST);
+
+ if (defaultHost == null) {
+ NameValueCollection config =
(NameValueCollection) ConfigurationSettings.GetConfig
("System.DirectoryServices/Settings");
+ if (config != null)
+ defaultHost = config
["servername"];
+
+ if (defaultHost == null)
+ defaultHost = "localhost";
+
+ AppDomain.CurrentDomain.SetData
(DEFAULT_LDAP_HOST,defaultHost);
+ }
+ return defaultHost;
+ }
+ }
+
+ private int DefaultPort
+ {
+ get {
+ string defaultPortStr = (string)
AppDomain.CurrentDomain.GetData (DEFAULT_LDAP_PORT);
+
+ if (defaultPortStr == null) {
+ NameValueCollection config =
(NameValueCollection) ConfigurationSettings.GetConfig
("System.DirectoryServices/Settings");
+ if (config != null)
+ defaultPortStr = config
["port"];
+
+ if (defaultPortStr == null)
+ defaultPortStr = "389";
+
+ AppDomain.CurrentDomain.SetData
(DEFAULT_LDAP_PORT,defaultPortStr);
+ }
+ return Int32.Parse (defaultPortStr);
+ }
+ }
+
+ private void InitToRootDse(string host,int port)
+ {
+ if ( host == null )
+ host = DefaultHost;
+ if ( port < 0 )
+ port = DefaultPort;
+
+ LdapUrl rootPath = new LdapUrl (host,port,String.Empty);
+ string [] attrs = new string [] {"+","*"};
+ DirectoryEntry rootEntry = new DirectoryEntry
(rootPath.ToString (),this.Username,this.Password,this.AuthenticationType);
+ DirectorySearcher searcher = new DirectorySearcher
(rootEntry,null,attrs,SearchScope.Base);
+
+ SearchResult result = searcher.FindOne ();
+ // copy properties from search result
+ PropertyCollection pcoll = new PropertyCollection ();
+ foreach (string propertyName in
result.Properties.PropertyNames) {
+ System.Collections.IEnumerator enumerator =
result.Properties [propertyName].GetEnumerator ();
+ if (enumerator != null)
+ while (enumerator.MoveNext ())
+ if (String.Compare
(propertyName,"ADsPath",true) != 0)
+ pcoll
[propertyName].Add (enumerator.Current);
+ }
+ this.SetProperties (pcoll);
+ this._Name = "rootDSE";
+ }
+
+ private void SetProperties(PropertyCollection pcoll)
+ {
+ _Properties = pcoll;
+ }
+
/// <summary>
+ /// Returns entry properties.
+ /// </summary>
+ /// <param name="forceLoad">Specifies whenever to force the
properties load from the server if local property cache is empty.</param>
+ /// <returns></returns>
+ private PropertyCollection GetProperties(bool forceLoad)
+ {
+ if (_Properties == null) {
+ // load properties into a different collection
+ // to preserve original collection state if
exception occurs
+ PropertyCollection properties = new
PropertyCollection (this);
+ if (forceLoad && !Nflag)
+ LoadProperties (properties,null);
+
+ _Properties = properties ;
+ }
+ return _Properties;
+ }
+
+ /// <summary>
+ /// Loads the values of the specified properties into the
property cache.
+ /// </summary>
+ /// <param name="propertyNames">An array of the specified
properties.</param>
+ private void LoadProperties(PropertyCollection
properties,string[] propertyNames)
+ {
+ _inPropertiesLoading = true;
+ try {
+ LdapSearchResults lsc=conn.Search
(Fdn,LdapConnection.SCOPE_BASE,"objectClass=*",null,false);
+ if (lsc.hasMore ()) {
+ LdapEntry nextEntry = lsc.next ();
+ string [] lowcasePropertyNames = null;
+ int length = 0;
+ if (propertyNames != null) {
+ length = propertyNames.Length;
+ lowcasePropertyNames = new
string [length];
+ for(int i=0; i < length; i++)
+ lowcasePropertyNames
[i] = propertyNames [i].ToLower ();
+ }
+ foreach (LdapAttribute attribute in
nextEntry.getAttributeSet ()) {
+ string attributeName =
attribute.Name;
+ if ((propertyNames == null) ||
(Array.IndexOf (lowcasePropertyNames,attributeName.ToLower ()) != -1)) {
+ properties
[attributeName].Value = null;
+ properties
[attributeName].AddRange (attribute.StringValueArray);
+ properties
[attributeName].Mbit=false;
+ }
+ }
+ }
+ }
+ finally {
+ _inPropertiesLoading = false;
+ }
+ }
+
+ /// <summary>
/// Searches an entry in the Ldap directory and returns the
attribute value
/// </summary>
/// <param name="attrName">attribute whose value is
required</param>
@@ -651,8 +757,12 @@
string eDn=lUrl.getDN();
if(eDn==null)
{
- eDn="";
+ eDn = String.Empty;
}
+ // rootDSE is a "virtual" entry that always exists
+ else if (String.Compare (eDn,"rootDSE",true) == 0)
+ return true;
+
string[] attrs={"objectClass"};
try
{
@@ -862,38 +972,37 @@
/// </remarks>
public void CommitChanges()
{
- if(UsePropertyCache)
- {
- CommitEntry();
- }
- }
-
- private void CommitEntry()
+ if(UsePropertyCache)
+ {
+ CommitEntry();
+ }
+ }
+
+ private void CommitEntry()
{
+ PropertyCollection properties = GetProperties(false);
if(!Nflag)
{
System.Collections.ArrayList modList = new
System.Collections.ArrayList();
- System.Collections.IDictionaryEnumerator id =
Properties.GetEnumerator();
- while(id.MoveNext())
+ foreach (string attribute in
properties.PropertyNames)
{
- string attribute=(string)id.Key;
LdapAttribute attr=null;
- if(Properties[attribute].Mbit)
+ if (properties [attribute].Mbit)
{
-
if(Properties[attribute].Count==1)
+ if (properties
[attribute].Count == 1)
{
- String val =
(String)Properties[attribute].Value;
+ string val = (string)
properties [attribute].Value;
attr = new
LdapAttribute( attribute , val);
}
else
{
- Object[] vals=(Object
[])Properties[attribute].Value;
- String[] aStrVals= new
String[Properties[attribute].Count];
-
Array.Copy(vals,0,aStrVals,0,Properties[attribute].Count);
+ object[] vals =(object
[]) properties [attribute].Value;
+ string[] aStrVals = new
string [properties [attribute].Count];
+ Array.Copy
(vals,0,aStrVals,0,properties [attribute].Count);
attr = new
LdapAttribute( attribute , aStrVals);
}
modList.Add( new
LdapModification(LdapModification.REPLACE, attr));
-
Properties[attribute].Mbit=false;
+ properties
[attribute].Mbit=false;
}
}
if (modList.Count > 0) {
@@ -906,20 +1015,18 @@
else
{
LdapAttributeSet attributeSet = new
LdapAttributeSet();
- System.Collections.IDictionaryEnumerator id =
Properties.GetEnumerator();
- while(id.MoveNext())
+ foreach (string attribute in
properties.PropertyNames)
{
- string attribute=(string)id.Key;
- if(Properties[attribute].Count==1)
+ if (properties [attribute].Count == 1)
{
- String val =
(String)Properties[attribute].Value;
+ string val = (string)
properties [attribute].Value;
attributeSet.Add(new
LdapAttribute(attribute, val));
}
else
{
- Object[] vals=(Object
[])Properties[attribute].Value;
- String[] aStrVals= new
String[Properties[attribute].Count];
-
Array.Copy(vals,0,aStrVals,0,Properties[attribute].Count);
+ object[] vals = (object [])
properties [attribute].Value;
+ string[] aStrVals = new string
[properties [attribute].Count];
+ Array.Copy
(vals,0,aStrVals,0,properties [attribute].Count);
attributeSet.Add( new
LdapAttribute( attribute , aStrVals));
}
}
@@ -929,12 +1036,12 @@
}
}
- internal void CommitDeferred()
- {
- if (!_inPropertiesLoading && !UsePropertyCache &&
!Nflag)
- {
- CommitEntry();
- }
+ internal void CommitDeferred()
+ {
+ if (!_inPropertiesLoading && !UsePropertyCache &&
!Nflag)
+ {
+ CommitEntry();
+ }
}
void RefreshEntry()
@@ -947,16 +1054,23 @@
InitEntry();
}
- [MonoTODO]
+ /// <summary>
+ /// Loads the values of the specified properties into the
property cache.
+ /// </summary>
public void RefreshCache ()
{
- throw new NotImplementedException
("System.DirectoryServices.DirectoryEntry.RefreshCache()");
+ // note that GetProperties must be called with false,
elswere infinite loop will be caused
+ LoadProperties(GetProperties(false),null);
}
- [MonoTODO]
- public void RefreshCache (string[] args)
+ /// <summary>
+ /// Loads the values of the specified properties into the
property cache.
+ /// </summary>
+ /// <param name="propertyNames">An array of the specified
properties. </param>
+ public void RefreshCache (string[] propertyNames)
{
- throw new NotImplementedException
("System.DirectoryServices.DirectoryEntry.RefreshCache(System.String[])");
+ // note that GetProperties must be called with false,
elswere infinite loop will be caused
+ LoadProperties(GetProperties(false),propertyNames);
}
protected override void Dispose (bool disposing)
@@ -966,5 +1080,15 @@
}
base.Dispose (disposing);
}
+
+ internal static string GetLdapUrlString(string host, int port,
string dn)
+ {
+ LdapUrl lUrl;
+ if (port == LdapConnection.DEFAULT_PORT)
+ lUrl = new LdapUrl (host,0,dn);
+ else
+ lUrl = new LdapUrl (host,port,dn);
+ return lUrl.ToString();
+ }
}
}
Index: System.DirectoryServices/PropertyValueCollection.cs
===================================================================
--- System.DirectoryServices/PropertyValueCollection.cs (revision 45938)
+++ System.DirectoryServices/PropertyValueCollection.cs (working copy)
@@ -135,6 +135,7 @@
copy_to[index++] = o;
}
+ [MonoTODO]
protected override void OnClearComplete ()
{
if (_parent != null) {
@@ -142,6 +143,7 @@
}
}
+ [MonoTODO]
protected override void OnInsertComplete (int index, object
value)
{
if (_parent != null) {
@@ -149,6 +151,7 @@
}
}
+ [MonoTODO]
protected override void OnRemoveComplete (int index, object
value)
{
if (_parent != null) {
@@ -156,6 +159,7 @@
}
}
+ [MonoTODO]
protected override void OnSetComplete (int index, object
oldValue, object newValue)
{
if (_parent != null) {
Index: System.DirectoryServices/SearchResult.cs
===================================================================
--- System.DirectoryServices/SearchResult.cs (revision 45938)
+++ System.DirectoryServices/SearchResult.cs (working copy)
@@ -109,7 +109,7 @@
String val =
(String)Rproperties[attribute].Value;
rpVal.Add(val);
}
- else
+ else if
(Rproperties[attribute].Count > 1)
{
Object[]
vals=(Object [])Rproperties[attribute].Value;
// String[]
aStrVals= new String[_Entry.Properties[attribute].Count];
<?xml version="1.0" encoding="utf-8" ?>
<!-- Example app.config file for specifying default LDAP server information -->
<configuration>
<configSections>
<sectionGroup name="System.DirectoryServices">
<section name="Settings"
type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
</configSections>
<System.DirectoryServices>
<Settings>
<add key="servername" value="xp050"/>
<add key="port" value="389"/>
</Settings>
</System.DirectoryServices>
</configuration>
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list