Bug 502597 thunderbird autoconfig, prefcalls.js Ldap queries broken - copy the nsILDAPSyncQuery component into comm-central alongside the LDAP code so that autoconfig with LDAP works again. r/sr=bienvenu
authorMark Banner <bugzilla@standard8.plus.com>
Wed, 26 Aug 2009 16:05:35 +0100
changeset 3424 581cb4a62c6b5ad57fa0906c31ed9e624973c85a
parent 3423 32083046dee3dad67db116dc56f42105c9f7a40d
child 3425 0bdcdd3c85a47ddca0ec6c7f5d83ab176a481add
push idunknown
push userunknown
push dateunknown
bugs502597
Bug 502597 thunderbird autoconfig, prefcalls.js Ldap queries broken - copy the nsILDAPSyncQuery component into comm-central alongside the LDAP code so that autoconfig with LDAP works again. r/sr=bienvenu
directory/xpcom/base/public/Makefile.in
directory/xpcom/base/public/nsILDAPSyncQuery.idl
directory/xpcom/base/src/Makefile.in
directory/xpcom/base/src/nsLDAPProtocolModule.cpp
directory/xpcom/base/src/nsLDAPSyncQuery.cpp
directory/xpcom/base/src/nsLDAPSyncQuery.h
--- a/directory/xpcom/base/public/Makefile.in
+++ b/directory/xpcom/base/public/Makefile.in
@@ -56,15 +56,19 @@ XPIDLSRCS	= 	\
 			nsILDAPServer.idl \
 			nsILDAPService.idl \
 			nsILDAPBERValue.idl \
 			nsILDAPControl.idl \
 			nsILDAPBERElement.idl \
 			nsILDAPModification.idl \
 			$(NULL)
 
+ifdef MOZ_PREF_EXTENSIONS
+XPIDLSRCS += nsILDAPSyncQuery.idl
+endif
+
 ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL
 XPIDLSRCS	+=	\
 			$(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/directory/xpcom/base/public/nsILDAPSyncQuery.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mitesh Shah <mitesh@netscape.com>
+ *   Dan Mosedale <dmose@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+interface nsILDAPURL;
+
+
+[scriptable, uuid (0308fb36-1dd2-11b2-b16f-8510e8c5311a)]
+interface nsILDAPSyncQuery : nsISupports {
+  
+  /**
+   * getQueryResults
+   *
+   * Create a new LDAP connection do a synchronous LDAP search and return 
+   * the results.
+   * @param aServerURL - LDAP URL with parameters to a LDAP search 
+   *                     ("ldap://host/base?attributes?one/sub?filter")
+   * @param aProtocolVersion - LDAP protocol version to use for connection
+   *                           (nsILDAPConnection.idl has symbolic constants)
+   * @return results
+   */
+   wstring getQueryResults (in nsILDAPURL aServerURL,
+                            in unsigned long aProtocolVersion);
+
+};
--- a/directory/xpcom/base/src/Makefile.in
+++ b/directory/xpcom/base/src/Makefile.in
@@ -69,16 +69,22 @@ CPPSRCS		= \
 		nsLDAPServer.cpp \
 		nsLDAPService.cpp \
 		nsLDAPBERValue.cpp \
 		nsLDAPControl.cpp \
 		nsLDAPBERElement.cpp \
 		nsLDAPModification.cpp \
 		$(NULL)
 
+ifdef MOZ_PREF_EXTENSIONS
+DEFINES += -DMOZ_PREF_EXTENSIONS
+
+CPPSRCS += nsLDAPSyncQuery.cpp
+endif
+
 ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL
 DEFINES		+= -DMOZ_LDAP_XPCOM_EXPERIMENTAL
 
 CPPSRCS		+= \
 		nsLDAPChannel.cpp \
 		$(NULL)
 
 REQUIRES	+= mimetype
--- a/directory/xpcom/base/src/nsLDAPProtocolModule.cpp
+++ b/directory/xpcom/base/src/nsLDAPProtocolModule.cpp
@@ -47,17 +47,19 @@
 #include "nsLDAPOperation.h"
 #include "nsLDAPMessage.h"
 #include "nsLDAPModification.h"
 #include "nsLDAPServer.h"
 #include "nsLDAPService.h"
 #include "nsLDAPBERValue.h"
 #include "nsLDAPBERElement.h"
 #include "nsLDAPControl.h"
-
+#ifdef MOZ_PREF_EXTENSIONS
+#include "nsLDAPSyncQuery.h"
+#endif
 #include "ldappr.h"
 
 #ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL
 #include "nsLDAPChannel.h"
 #endif
 
 // use the default constructor
 //
@@ -66,16 +68,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPOpe
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPMessage)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsLDAPModification, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPServer)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPURL)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsLDAPService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPBERValue)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPBERElement)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPControl)
+#ifdef MOZ_PREF_EXTENSIONS
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPSyncQuery)
+#endif
 #ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPChannel)
 #endif
 
 NS_DECL_CLASSINFO(nsLDAPMessage)
 NS_DECL_CLASSINFO(nsLDAPOperation)
 NS_DECL_CLASSINFO(nsLDAPConnection)
 
@@ -121,16 +126,20 @@ static const nsModuleComponentInfo compo
     { "LDAP BER Value", NS_LDAPBERVALUE_CID,
       "@mozilla.org/network/ldap-ber-value;1", nsLDAPBERValueConstructor },
     { "LDAP BER Element", NS_LDAPBERELEMENT_CID,
       "@mozilla.org/network/ldap-ber-element;1", nsLDAPBERElementConstructor },
 #ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL
     { "LDAP Channel", NS_LDAPCHANNEL_CID,
       "@mozilla.org/network/ldap-channel;1", nsLDAPChannelConstructor },
 #endif
+#ifdef MOZ_PREF_EXTENSIONS
+    { "LDAPSyncQuery module", NS_LDAPSYNCQUERY_CID,
+      "@mozilla.org/ldapsyncquery;1", nsLDAPSyncQueryConstructor },
+#endif
     { "LDAP Control", NS_LDAPCONTROL_CID,
       "@mozilla.org/network/ldap-control;1", nsLDAPControlConstructor}
 };
 
 static nsresult
 nsLDAPInitialize(nsIModule *aSelf)
 {
 #ifdef PR_LOGGING
new file mode 100644
--- /dev/null
+++ b/directory/xpcom/base/src/nsLDAPSyncQuery.cpp
@@ -0,0 +1,468 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mitesh Shah <mitesh@netscape.com>
+ *   Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsLDAPSyncQuery.h"
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+#include "nsXPIDLString.h"
+#include "nsILDAPErrors.h"
+#include "nsThreadUtils.h"
+#include "nsReadableUtils.h"
+#include "nsILDAPMessage.h"
+
+// nsISupports Implementation
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsLDAPSyncQuery, nsILDAPSyncQuery, nsILDAPMessageListener)
+
+// Constructor
+//
+nsLDAPSyncQuery::nsLDAPSyncQuery() :
+    mFinished(PR_FALSE), // This is a control variable for event loop
+    mAttrCount(0), mAttrs(0), mProtocolVersion(nsILDAPConnection::VERSION3)
+{
+}
+
+// Destructor
+//
+nsLDAPSyncQuery::~nsLDAPSyncQuery()
+{
+}
+
+
+// Messages received are passed back via this function.
+// void OnLDAPMessage (in nsILDAPMessage aMessage) 
+//
+NS_IMETHODIMP 
+nsLDAPSyncQuery::OnLDAPMessage(nsILDAPMessage *aMessage)
+{
+    PRInt32 messageType;
+
+    // just in case.
+    //
+    if (!aMessage) {
+        return NS_OK;
+    }
+
+    // figure out what sort of message was returned
+    //
+    nsresult rv = aMessage->GetType(&messageType);
+    if (NS_FAILED(rv)) {
+        NS_ERROR("nsLDAPSyncQuery::OnLDAPMessage(): unexpected "
+                 "error in aMessage->GetType()");
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    switch (messageType) {
+
+    case nsILDAPMessage::RES_BIND:
+
+        // a bind has completed
+        //
+        return OnLDAPBind(aMessage);
+
+    case nsILDAPMessage::RES_SEARCH_ENTRY:
+        
+        // a search entry has been returned
+        //
+        return OnLDAPSearchEntry(aMessage);
+
+    case nsILDAPMessage::RES_SEARCH_RESULT:
+
+        // the search is finished; we're all done
+        //  
+        return OnLDAPSearchResult(aMessage);
+
+    default:
+        
+        // Given the LDAP operations nsLDAPSyncQuery uses, we should
+        // never get here.  If we do get here in a release build, it's
+        // probably a bug, but maybe it's the LDAP server doing something
+        // weird.  Might as well try and continue anyway.  The session should
+        // eventually get reaped by the timeout code, if necessary.
+        //
+        NS_ERROR("nsLDAPSyncQuery::OnLDAPMessage(): unexpected "
+                 "LDAP message received");
+        return NS_OK;
+    }
+}
+
+// void onLDAPInit (in nsresult aStatus);
+//
+NS_IMETHODIMP
+nsLDAPSyncQuery::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus)
+{
+    nsresult rv;        // temp for xpcom return values
+    nsCOMPtr<nsILDAPMessageListener> selfProxy;
+
+    // create and initialize an LDAP operation (to be used for the bind)
+    //  
+    mOperation = do_CreateInstance("@mozilla.org/network/ldap-operation;1", 
+                                   &rv);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // get a proxy object so the callback happens on the main thread
+    //
+    rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD,
+                              NS_GET_IID(nsILDAPMessageListener), 
+                              static_cast<nsILDAPMessageListener *>(this),
+                              NS_PROXY_ASYNC | NS_PROXY_ALWAYS, 
+                              getter_AddRefs(selfProxy));
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // our OnLDAPMessage accepts all result callbacks
+    //
+    rv = mOperation->Init(mConnection, selfProxy, nsnull);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED; // this should never happen
+    }
+
+    // kick off a bind operation 
+    // 
+    rv = mOperation->SimpleBind(EmptyCString()); 
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+    
+    return NS_OK;
+}
+
+nsresult
+nsLDAPSyncQuery::OnLDAPBind(nsILDAPMessage *aMessage)
+{
+
+    PRInt32 errCode;
+
+    mOperation = 0;  // done with bind op; make nsCOMPtr release it
+
+    // get the status of the bind
+    //
+    nsresult rv = aMessage->GetErrorCode(&errCode);
+    if (NS_FAILED(rv)) {
+        
+        NS_ERROR("nsLDAPSyncQuery::OnLDAPBind(): couldn't get "
+                 "error code from aMessage");
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+
+    // check to be sure the bind succeeded
+    //
+    if (errCode != nsILDAPErrors::SUCCESS) {
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // ok, we're starting a search
+    //
+    return StartLDAPSearch();
+}
+
+nsresult
+nsLDAPSyncQuery::OnLDAPSearchEntry(nsILDAPMessage *aMessage)
+{
+    nsresult rv;       
+
+    // Attributes are retrieved in StartLDAPSearch
+    // iterate through them
+    //
+    for (PRUint32 i = 0; i < mAttrCount; i++) {
+
+        PRUnichar **vals;
+        PRUint32 valueCount;
+
+        // get the values of this attribute
+        // XXX better failure handling
+        //
+        rv = aMessage->GetValues(mAttrs[i], &valueCount, &vals);
+        if (NS_FAILED(rv)) {
+            NS_WARNING("nsLDAPSyncQuery:OnLDAPSearchEntry(): "
+                       "aMessage->GetValues() failed\n");
+            FinishLDAPQuery();
+            return rv;;
+        }
+
+        // store  all values of this attribute in the mResults.
+        //
+        for (PRUint32 j = 0; j < valueCount; j++) {
+            mResults.Append(PRUnichar('\n'));
+            mResults.AppendASCII(mAttrs[i]);
+            mResults.Append(PRUnichar('='));
+            mResults.Append(vals[j]);
+        }
+        
+        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(valueCount, vals);
+
+    }
+
+    return NS_OK;
+}
+
+
+nsresult
+nsLDAPSyncQuery::OnLDAPSearchResult(nsILDAPMessage *aMessage)
+{
+    // We are done with the LDAP search.
+    // Release the control variable for the eventloop and other members
+    // 
+    FinishLDAPQuery();
+    
+    // Release memory allocated for mAttrs
+    
+    if (mAttrCount > 0)
+        NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mAttrCount, mAttrs);
+
+    return NS_OK;
+}
+
+nsresult
+nsLDAPSyncQuery::StartLDAPSearch()
+{
+    nsresult rv; 
+    nsCOMPtr<nsILDAPMessageListener> selfProxy; // for callback
+
+
+    // create and initialize an LDAP operation (to be used for the search
+    //  
+    mOperation = 
+        do_CreateInstance("@mozilla.org/network/ldap-operation;1", &rv);
+
+    if (NS_FAILED(rv)) {
+        NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't "
+                 "create @mozilla.org/network/ldap-operation;1");
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // get a proxy object so the callback happens on the main thread
+    //
+    rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD, 
+                              NS_GET_IID(nsILDAPMessageListener),
+                              static_cast<nsILDAPMessageListener *>(this),
+                              NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
+                              getter_AddRefs(selfProxy));
+    if (NS_FAILED(rv)) {
+        NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't "
+                 "create proxy to this object for callback");
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // initialize the LDAP operation object
+    //
+    rv = mOperation->Init(mConnection, selfProxy, nsnull);
+    if (NS_FAILED(rv)) {
+        NS_ERROR("nsLDAPSyncQuery::StartLDAPSearch(): couldn't "
+                 "initialize LDAP operation");
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    // get the search filter associated with the directory server url; 
+    //
+    nsCAutoString urlFilter;
+    rv = mServerURL->GetFilter(urlFilter);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    // get the base dn to search
+    //
+    nsCAutoString dn;
+    rv = mServerURL->GetDn(dn);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    // and the scope
+    //
+    PRInt32 scope;
+    rv = mServerURL->GetScope(&scope);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+    
+    rv = mServerURL->GetAttributes(&mAttrCount, &mAttrs);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED;
+    }
+
+
+    // time to kick off the search.
+    //
+    rv = mOperation->SearchExt(dn, scope, urlFilter, mAttrCount,
+                               const_cast<const char **>(mAttrs), 0, 0);
+
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    return NS_OK;
+}
+
+// void initConnection (); 
+//
+nsresult nsLDAPSyncQuery::InitConnection()
+{
+    nsCOMPtr<nsILDAPMessageListener> selfProxy;
+    nsresult rv;        // temp for xpcom return values
+    
+    // create an LDAP connection
+    //
+    mConnection = do_CreateInstance("@mozilla.org/network/ldap-connection;1",
+                                    &rv);
+    if (NS_FAILED(rv)) {
+        NS_ERROR("nsLDAPSyncQuery::InitConnection(): could "
+                 "not create @mozilla.org/network/ldap-connection;1");
+        FinishLDAPQuery();
+        return NS_ERROR_FAILURE;
+    }
+
+    // have we been properly initialized?
+    //
+    if (!mServerURL) {
+        NS_ERROR("nsLDAPSyncQuery::InitConnection(): mServerURL "
+                 "is NULL");
+        FinishLDAPQuery();
+        return NS_ERROR_NOT_INITIALIZED;
+    }
+
+    // get a proxy object so the callback happens on the main thread
+    //
+    rv = NS_GetProxyForObject(NS_PROXY_TO_CURRENT_THREAD,
+                              NS_GET_IID(nsILDAPMessageListener), 
+                              static_cast<nsILDAPMessageListener *>(this), 
+                              NS_PROXY_ASYNC | NS_PROXY_ALWAYS, 
+                              getter_AddRefs(selfProxy));
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        NS_ERROR("nsLDAPSyncQuery::InitConnection(): couldn't "
+                 "create proxy to this object for callback");
+        return NS_ERROR_FAILURE;
+    }
+
+    rv = mConnection->Init(mServerURL, EmptyCString(), selfProxy,
+                           nsnull, mProtocolVersion);
+    if (NS_FAILED(rv)) {
+        FinishLDAPQuery();
+        return NS_ERROR_UNEXPECTED; // this should never happen
+    }
+
+    return NS_OK;
+}
+
+void
+nsLDAPSyncQuery::FinishLDAPQuery()
+{
+    // We are done with the LDAP operation. 
+    // Release the Control variable for the eventloop
+    //
+    mFinished = PR_TRUE;
+    
+    // Release member variables
+    //
+    mConnection = 0;
+    mOperation = 0;
+    mServerURL = 0;
+ 
+}
+
+/* wstring getQueryResults (in nsILDAPURL aServerURL, in unsigned long aVersion); */
+NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL,
+                                               PRUint32 aProtocolVersion,
+                                               PRUnichar **_retval)
+{
+    nsresult rv;
+    
+    if (!aServerURL) {
+        NS_ERROR("nsLDAPSyncQuery::GetQueryResults() called without LDAP URL");
+        return NS_ERROR_FAILURE;
+    }
+    mServerURL = aServerURL;
+    mProtocolVersion = aProtocolVersion;
+
+    nsCOMPtr<nsIThread> currentThread = do_GetCurrentThread();
+
+    // Start an LDAP query. 
+    // InitConnection will bind to the ldap server and post a OnLDAPMessage 
+    // event. This event will trigger a search and the whole operation will 
+    // be carried out by chain of events
+    //
+    rv = InitConnection();
+    if (NS_FAILED(rv))
+        return rv;
+    
+    // We want this LDAP query to be synchronous while the XPCOM LDAP is 
+    // async in nature. So this eventQueue handling will wait for the 
+    // LDAP operation to be finished. 
+    // mFinished controls the state of the LDAP opertion. 
+    // It will be released in any case (success/failure)
+    
+    
+    // Run the event loop, 
+    // mFinished is a control variable
+    //
+    while (!mFinished)
+        NS_ENSURE_STATE(NS_ProcessNextEvent(currentThread));
+
+    // Return results
+    //
+    if (!mResults.IsEmpty()) {
+        *_retval = ToNewUnicode(mResults);
+        if (!_retval)
+          rv = NS_ERROR_OUT_OF_MEMORY;
+    }
+    return rv;
+
+}
new file mode 100644
--- /dev/null
+++ b/directory/xpcom/base/src/nsLDAPSyncQuery.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mitesh Shah <mitesh@netscape.com>
+ *   Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsILDAPConnection.h"
+#include "nsILDAPOperation.h"
+#include "nsILDAPMessageListener.h"
+#include "nsILDAPURL.h"
+#include "nsString.h"
+#include "nsILDAPSyncQuery.h"
+
+// DDDEE14E-ED81-4182-9323-C2AB22FBA68E
+#define NS_LDAPSYNCQUERY_CID \
+{ 0xdddee14e, 0xed81, 0x4182, \
+ { 0x93, 0x23, 0xc2, 0xab, 0x22, 0xfb, 0xa6, 0x8e }}
+
+
+class nsLDAPSyncQuery : public nsILDAPSyncQuery,
+                        public nsILDAPMessageListener
+
+{
+  public:
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSILDAPMESSAGELISTENER
+    NS_DECL_NSILDAPSYNCQUERY
+
+    nsLDAPSyncQuery();
+    virtual ~nsLDAPSyncQuery();
+
+  protected:
+
+    nsCOMPtr<nsILDAPConnection> mConnection; // connection used for search
+    nsCOMPtr<nsILDAPOperation> mOperation;   // current ldap op
+    nsCOMPtr<nsILDAPURL> mServerURL;         // LDAP URL
+    PRBool mFinished;                        // control variable for eventQ
+    PRUint32 mAttrCount;                     // No. of attrbiutes
+    char **mAttrs;                           // Attributes to search
+    nsString mResults;                       // values to return
+    PRUint32 mProtocolVersion;               // LDAP version to use
+
+    nsresult InitConnection();
+    // check that we bound ok and start then call StartLDAPSearch
+    nsresult OnLDAPBind(nsILDAPMessage *aMessage); 
+
+    // add to the results set
+    nsresult OnLDAPSearchEntry(nsILDAPMessage *aMessage); 
+
+
+    nsresult OnLDAPSearchResult(nsILDAPMessage *aMessage); 
+
+    // kick off a search
+    nsresult StartLDAPSearch();
+    
+    // Clean up after the LDAP Query is done.
+    void FinishLDAPQuery();
+};
+