diff --git a/directory/xpcom/base/public/nsILDAPConnection.idl b/directory/xpcom/base/public/nsILDAPConnection.idl index 1322fdf18c2c..2a9821b97293 100644 --- a/directory/xpcom/base/public/nsILDAPConnection.idl +++ b/directory/xpcom/base/public/nsILDAPConnection.idl @@ -47,8 +47,13 @@ interface nsILDAPConnection : nsISupports // return the string version of lderrno readonly attribute string errorString; - // wrapper for ldap_init() - void init(in string defhost, in short defport); + // who we're binding as + readonly attribute string bindName; + + // set up the connection. the first two params are for ldap init, + // the third is for this connection + // + void init(in string aHost, in short aPort, in string aBindName); // wrapper for ldap_get_lderrno() long getLdErrno(out string matched, out string s); diff --git a/directory/xpcom/base/public/nsILDAPMessage.idl b/directory/xpcom/base/public/nsILDAPMessage.idl index b67c8ce17c07..1b6cfc8e600e 100644 --- a/directory/xpcom/base/public/nsILDAPMessage.idl +++ b/directory/xpcom/base/public/nsILDAPMessage.idl @@ -74,5 +74,9 @@ interface nsILDAPMessage : nsISupports // errcode (wrapper around ldap_parse_result) // long getErrorCode(); - + + // returns an LDIF-like string representation of this message + // XXXdmose - should use wstring here + // + string toString(); }; diff --git a/directory/xpcom/base/public/nsILDAPOperation.idl b/directory/xpcom/base/public/nsILDAPOperation.idl index e0ac93089233..d65f05a94368 100644 --- a/directory/xpcom/base/public/nsILDAPOperation.idl +++ b/directory/xpcom/base/public/nsILDAPOperation.idl @@ -48,7 +48,7 @@ interface nsILDAPOperation : nsISupports // wrapper for ldap_simple_bind() // - void simpleBind(in string binddn, in string passwd); + void simpleBind(in string passwd); // wrapper for ldap_search_url() // diff --git a/directory/xpcom/base/src/Makefile.in b/directory/xpcom/base/src/Makefile.in index dd0ce49f3df7..4aff9f498b60 100644 --- a/directory/xpcom/base/src/Makefile.in +++ b/directory/xpcom/base/src/Makefile.in @@ -54,7 +54,6 @@ CPPSRCS = \ nsLDAPConnection.cpp \ nsLDAPOperation.cpp \ nsLDAPURL.cpp \ - ldapSearch.cpp \ $(NULL) EXTRA_DSO_LDOPTS += -lldap40 -llber40 $(MOZ_COMPONENT_LIBS) diff --git a/directory/xpcom/base/src/TestLDAP.cpp b/directory/xpcom/base/src/TestLDAP.cpp index eb886b4d6360..5729d27c0a44 100644 --- a/directory/xpcom/base/src/TestLDAP.cpp +++ b/directory/xpcom/base/src/TestLDAP.cpp @@ -108,7 +108,7 @@ main () fflush(stderr); myOperation = new ldapOperation(myConnection); returnCode = myOperation->SearchExt("ou=member_directory,o=netcenter.com", - LDAP_SCOPE_SUBTREE, "(sn=Mosedale)", + LDAP_SCOPE_SUBTREE, "(sn=Rasputin)", &timeout, -1); switch (returnCode) { diff --git a/directory/xpcom/base/src/ldapSearch.cpp b/directory/xpcom/base/src/ldapSearch.cpp deleted file mode 100644 index aa78c043f1cf..000000000000 --- a/directory/xpcom/base/src/ldapSearch.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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 the mozilla.org LDAP XPCOM component. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): Dan Mosedale n - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include -#include -#include "nspr.h" -#include "ldap.h" -#include "nsCOMPtr.h" -#include "nsIComponentManager.h" -#include "nsILDAPConnection.h" -#include "nsILDAPOperation.h" -#include "nsILDAPMessage.h" -#include "nsLDAPChannel.h" - -NS_METHOD -lds(class nsLDAPChannel *chan, const char *url) -{ - nsCOMPtr myConnection; - nsCOMPtr myMessage; - nsCOMPtr myOperation; - PRInt32 returnCode; - char *errString; - nsresult rv; - - // create an LDAP connection - // - myConnection = do_CreateInstance("mozilla.network.ldapconnection", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // initialize it with the defaults - // XXX should return reasonable err msg, not assert - // - rv = myConnection->Init("nsdirectory.netscape.com", LDAP_PORT); - NS_ENSURE_SUCCESS(rv, rv); - - // create and initialize an LDAP operation on the new connection - // - myOperation = do_CreateInstance("mozilla.network.ldapoperation", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = myOperation->SetConnection(myConnection); - NS_ENSURE_SUCCESS(rv, rv); - -#ifdef NO_URL_SEARCH -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "starting bind\n"); -#endif - - if ( !myOperation->SimpleBind(NULL, NULL) ) { - (void)myConnection->GetErrorString(&errString); - PR_fprintf(PR_STDERR, "ldap_simple_bind: %s\n", errString); - return NS_ERROR_FAILURE; - } - -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "waiting for bind to complete"); -#endif - - myMessage = new nsLDAPMessage(myOperation); - returnCode = myOperation->Result(0, &nullTimeval, myMessage); - - while (returnCode == 0 ) { - returnCode = - myOperation->Result(0, &nullTimeval, myMessage); - usleep(20); -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR,"."); -#endif - } - - switch (returnCode) { - case LDAP_RES_BIND: - // success - break; - case -1: - (void)myConnection->GetErrorString(&errString); - PR_fprintf(PR_STDERR, - "myOperation->Result() [myOperation->SimpleBind]: %s: errno=%d\n", - errString, errno); - ldap_memfree(errString); - return NS_ERROR_FAILURE; - break; - default: - PR_fprintf(PR_STDERR, - "\nmyOperation->Result() returned unexpected value: %d", - returnCode); - return NS_ERROR_FAILURE; - } -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "bound\n"); -#endif - -#endif - - // start search - // - PR_fprintf(PR_STDERR, "starting search\n"); - - myOperation = do_CreateInstance("mozilla.network.ldapoperation", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = myOperation->SetConnection(myConnection); - NS_ENSURE_SUCCESS(rv, rv); - - // XXX what about timeouts? - // XXX failure is a reasonable thing; don't assert - // - rv = myOperation->UrlSearch(url, PR_FALSE); - NS_ENSURE_SUCCESS(rv,rv); - - // poll for results - // -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "polling search operation"); -#endif - returnCode = LDAP_SUCCESS; - while ( returnCode != LDAP_RES_SEARCH_RESULT ) { - - PR_fprintf(PR_STDERR,"."); - - // XXX is 0 the right value? - // - rv = myOperation->Result(LDAP_MSG_ONE, (PRIntervalTime)0, - getter_AddRefs(myMessage), &returnCode); - - switch (returnCode) { - case -1: // something went wrong - (void)myConnection->GetErrorString(&errString); -#ifdef DEBUG - PR_fprintf(PR_STDERR, - "\nmyOperation->Result() [URLSearch]: %s: errno=%d\n", - errString, errno); -#endif - ldap_memfree(errString); - return NS_ERROR_FAILURE; - case 0: // nothing's been returned yet - break; - - default: - chan->OnLDAPMessage(myMessage, returnCode); - break; - - } - myMessage = 0; - - PR_Sleep(200); - } - - return NS_OK; -} diff --git a/directory/xpcom/base/src/nsLDAPChannel.cpp b/directory/xpcom/base/src/nsLDAPChannel.cpp index a99d768eb505..2e584df94aaf 100644 --- a/directory/xpcom/base/src/nsLDAPChannel.cpp +++ b/directory/xpcom/base/src/nsLDAPChannel.cpp @@ -50,8 +50,6 @@ #include "nspr.h" #endif -NS_METHOD lds(class nsLDAPChannel *chan, const char *); - NS_IMPL_THREADSAFE_ISUPPORTS4(nsLDAPChannel, nsIChannel, nsIRequest, nsIRunnable, nsILDAPMessageListener); @@ -64,12 +62,32 @@ nsLDAPChannel::~nsLDAPChannel() { } +// initialize the channel +// nsresult nsLDAPChannel::Init(nsIURI *uri) { - mURI = uri; - mReadPipeOffset = 0; - return NS_OK; + nsresult rv; + + mURI = uri; + mReadPipeOffset = 0; + + // create an LDAP connection + // + mConnection = do_CreateInstance("mozilla.network.ldapconnection", &rv); + if (NS_FAILED(rv)) { + return rv; + } + + // initialize it with the defaults + // XXX - should use nsLDAPURL and get the correct default + // + rv = mConnection->Init("memberdir.netscape.com", LDAP_PORT, NULL); + if (NS_FAILED(rv)) { + return (rv); + } + + return NS_OK; } // impl code cribbed from nsJARChannel.cpp @@ -493,27 +511,61 @@ NS_IMETHODIMP nsLDAPChannel::AsyncRead(nsIStreamListener* aListener, nsISupports* aCtxt) { - nsresult rv; + nsresult rv; + nsXPIDLCString urlSpec; - // deal with the input args - // - mListener = aListener; - mResponseContext = aCtxt; + // deal with the input args + // + mListener = aListener; + mResponseContext = aCtxt; - // add ourselves to the appropriate loadgroup - // - if (mLoadGroup) { - mLoadGroup->AddChannel(this, nsnull); - } + // add ourselves to the appropriate loadgroup + // + if (mLoadGroup) { + mLoadGroup->AddChannel(this, nsnull); + } - // kick off a thread to do the work - // - NS_ASSERTION(!mThread, "nsLDAPChannel thread already exists!"); + // start search + // +#ifdef DEBUG_dmose + PR_fprintf(PR_STDERR, "starting search\n"); +#endif - rv = NS_NewThread(getter_AddRefs(mThread), this, 0, PR_JOINABLE_THREAD); - NS_ENSURE_SUCCESS(rv, rv); + // create and initialize an LDAP operation (to be used for the bind) + // + mOperation = do_CreateInstance("mozilla.network.ldapoperation", &rv); + if (NS_FAILED(rv)) { + return (rv); + } + rv = mOperation->SetConnection(mConnection); + if (NS_FAILED(rv)) { + return (rv); + } - return NS_OK; + // get the URI spec + // + rv = mURI->GetSpec(getter_Copies(urlSpec)); + NS_ENSURE_SUCCESS(rv, rv); + + + // we already know the content type, so we can fire this now + // + mListener->OnStartRequest(this, mResponseContext); + + // XXX what about timeouts? + // XXX failure is a reasonable thing; don't assert + // + rv = mOperation->UrlSearch(urlSpec, PR_FALSE); + NS_ENSURE_SUCCESS(rv,rv); + + // kick off a thread to wait for results + // + NS_ASSERTION(!mThread, "nsLDAPChannel thread already exists!"); + + rv = NS_NewThread(getter_AddRefs(mThread), this, 0, PR_JOINABLE_THREAD); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; } // Writes asynchronously to the URL's specified destination. Notifications @@ -545,6 +597,9 @@ nsLDAPChannel::Run(void) { nsresult rv; nsXPIDLCString spec; + PRInt32 returnCode; + nsCOMPtr myMessage; + char *errString; // XXX fix ownership model #ifdef DEBUG_dmose PR_fprintf(PR_STDERR, "nsLDAPChannel::Run() entered!\n"); @@ -556,10 +611,6 @@ nsLDAPChannel::Run(void) NS_UI_THREAD_EVENTQ); NS_ENSURE_SUCCESS(rv, rv); - // we already know the content type, so might as well fire this now - // - mAsyncListener->OnStartRequest(this, mResponseContext); - // since the LDAP SDK does all the socket management, we don't have // an underlying transport channel to create an nsIInputStream to hand // back to the nsIStreamListener. So we do it ourselves: @@ -584,15 +635,41 @@ nsLDAPChannel::Run(void) // XXX handle incorrect second call to Run } - // get the URI spec + // wait for results // - rv = mURI->GetSpec(getter_Copies(spec)); - NS_ENSURE_SUCCESS(rv, rv); +#ifdef DEBUG_dmose + PR_fprintf(PR_STDERR, "waiting for messages\n"); +#endif - // do the search - // - rv = lds(this, spec); - NS_ENSURE_SUCCESS(rv, rv); + returnCode = LDAP_SUCCESS; + while ( returnCode != LDAP_RES_SEARCH_RESULT ) { + + // XXX is 0 the right value? + // + rv = mOperation->Result(LDAP_MSG_ONE, (PRIntervalTime)0, + getter_AddRefs(myMessage), &returnCode); + + switch (returnCode) { + case -1: // something went wrong + (void)mConnection->GetErrorString(&errString); +#ifdef DEBUG + PR_fprintf(PR_STDERR,"\nmyOperation->Result() [URLSearch]: %s\n", + errString); +#endif + ldap_memfree(errString); + return NS_ERROR_FAILURE; + case 0: // nothing's been returned yet + break; + + default: + this->OnLDAPMessage(myMessage, returnCode); + break; + + } + myMessage = 0; + + PR_Sleep(200); + } // close the pipe // @@ -667,7 +744,7 @@ nsLDAPChannel::OnLDAPSearchResult(nsILDAPMessage *aMessage) nsresult rv; #ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "\nresult returned: \n"); + PR_fprintf(PR_STDERR, "result returned\n"); #endif // XXX should use GetErrorString here? @@ -678,27 +755,17 @@ nsLDAPChannel::OnLDAPSearchResult(nsILDAPMessage *aMessage) return NS_ERROR_FAILURE; } -#ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "success\n"); -#endif - - // done with this message; cause nsCOMPtr to call the destructor - // - aMessage = 0; - - // XXX need to destroy the connection (to unbind) here - // the old code that did this in ldapSearch.cpp is pasted below - // -#if 0 #ifdef DEBUG_dmose PR_fprintf(PR_STDERR,"unbinding\n"); #endif - myConnection = 0; + // XXXdmose this is synchronous! (and presumably could conceivably stall) + // should check SDK code to verify, and somehow deal with this better. + // + mConnection = 0; #ifdef DEBUG_dmose PR_fprintf(PR_STDERR,"unbound\n"); -#endif #endif return NS_OK; @@ -707,7 +774,7 @@ nsLDAPChannel::OnLDAPSearchResult(nsILDAPMessage *aMessage) // void OnLDAPSearchEntry (in nsILDAPMessage aMessage); // // XXX need to addref my message? deal with scope? -// XXXdmose most of this function should live in nsILDAPMessage::toString +// XXXdmose most of this function should live in nsILDAPMessage::toString() // nsresult nsLDAPChannel::OnLDAPSearchEntry(nsILDAPMessage *aMessage) @@ -716,7 +783,7 @@ nsLDAPChannel::OnLDAPSearchEntry(nsILDAPMessage *aMessage) char *dn, *attr; #ifdef DEBUG_dmose - PR_fprintf(PR_STDERR, "\nentry returned!\n"); + PR_fprintf(PR_STDERR, "entry returned!\n"); #endif // get the DN diff --git a/directory/xpcom/base/src/nsLDAPChannel.h b/directory/xpcom/base/src/nsLDAPChannel.h index 1ddcaf6645c0..3455a1830f61 100644 --- a/directory/xpcom/base/src/nsLDAPChannel.h +++ b/directory/xpcom/base/src/nsLDAPChannel.h @@ -91,7 +91,9 @@ protected: // nsCOMPtr mAsyncListener; // since we can't call mListener // directly from the worker thread - nsCOMPtr mThread; // worker thread for this channer + nsCOMPtr mConnection; // LDAP connection for this channel + nsCOMPtr mOperation; // current LDAP operation + nsCOMPtr mThread; // worker thread for this channel nsCOMPtr mListener; // whoever is listening to us nsCOMPtr mResponseContext; nsCOMPtr mReadPipeIn; // this end given to the listener diff --git a/directory/xpcom/base/src/nsLDAPConnection.cpp b/directory/xpcom/base/src/nsLDAPConnection.cpp index 7d0ba11cc863..37c14dbeb57e 100644 --- a/directory/xpcom/base/src/nsLDAPConnection.cpp +++ b/directory/xpcom/base/src/nsLDAPConnection.cpp @@ -32,6 +32,7 @@ */ #include +#include "nspr.h" #include "nsLDAPConnection.h" NS_IMPL_THREADSAFE_ISUPPORTS1(nsLDAPConnection, nsILDAPConnection); @@ -52,23 +53,67 @@ nsLDAPConnection::~nsLDAPConnection() rc = ldap_unbind_s(this->mConnectionHandle); if (rc != LDAP_SUCCESS) { - fprintf(stderr, "nsLDAPConnection::~nsLDAPConnection: %s\n", +#ifdef DEBUG + PR_fprintf(PR_STDERR, "nsLDAPConnection::~nsLDAPConnection: %s\n", ldap_err2string(rc)); +#endif + } + + // XXX use delete here? + // XXX can delete fail? + // + if (mBindName) { + delete mBindName; } } // wrapper for ldap_init() // NS_IMETHODIMP -nsLDAPConnection::Init(const char *aDefHost, PRInt16 aDefPort) +nsLDAPConnection::Init(const char *aHost, PRInt16 aPort, const char *aBindName) { - NS_ENSURE_ARG(aDefHost); - NS_ENSURE_ARG(aDefPort); + NS_ENSURE_ARG(aHost); + NS_ENSURE_ARG(aPort); + + if (aBindName) { + mBindName = new nsCString(aBindName); + if (!mBindName) { + return NS_ERROR_OUT_OF_MEMORY; + } + } else { + mBindName = NULL; + } + + this->mConnectionHandle = ldap_init(aHost, aPort); - this->mConnectionHandle = ldap_init(aDefHost, aDefPort); return (this->mConnectionHandle == NULL ? NS_ERROR_FAILURE : NS_OK); } +// who we're binding as +// +// readonly attribute string bindName +NS_IMETHODIMP +nsLDAPConnection::GetBindName(char **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + + // check for NULL (meaning bind anonymously) + // + if (!mBindName) { + *_retval = nsnull; + } else { + + // otherwise, hand out a copy of the bind name + // + *_retval = mBindName->ToNewCString(); + if (!(*_retval)) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + return NS_OK; +} + // wrapper for ldap_get_lderrno // NS_IMETHODIMP diff --git a/directory/xpcom/base/src/nsLDAPConnection.h b/directory/xpcom/base/src/nsLDAPConnection.h index bc1f9966b0c5..852c54c8fcc9 100644 --- a/directory/xpcom/base/src/nsLDAPConnection.h +++ b/directory/xpcom/base/src/nsLDAPConnection.h @@ -36,6 +36,7 @@ #include "nsILDAPConnection.h" #include "ldap.h" +#include "nsString.h" // 0d871e30-1dd2-11b2-8ea9-831778c78e93 // @@ -60,8 +61,8 @@ class nsLDAPConnection : public nsILDAPConnection { protected: // the LDAP SDK's struct for the connection - LDAP *mConnectionHandle; - + LDAP *mConnectionHandle; // the LDAP C SDK's connection object + nsCString *mBindName; // who to bind as }; #endif /* _nsLDAPConnection_h_ */ diff --git a/directory/xpcom/base/src/nsLDAPMessage.cpp b/directory/xpcom/base/src/nsLDAPMessage.cpp index a5e57815d327..3c83b741e11e 100644 --- a/directory/xpcom/base/src/nsLDAPMessage.cpp +++ b/directory/xpcom/base/src/nsLDAPMessage.cpp @@ -280,3 +280,13 @@ nsLDAPMessage::GetValues(const char *aAttr, PRUint32 *aCount, *aValues = values; return NS_OK; } + +// returns an LDIF-like string representation of this message +// +// string toString(); +// +NS_IMETHODIMP +nsLDAPMessage::ToString(char* *aString) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/directory/xpcom/base/src/nsLDAPOperation.cpp b/directory/xpcom/base/src/nsLDAPOperation.cpp index 451db203c2ac..c8b96256ffc4 100644 --- a/directory/xpcom/base/src/nsLDAPOperation.cpp +++ b/directory/xpcom/base/src/nsLDAPOperation.cpp @@ -35,6 +35,7 @@ #include "nsLDAPOperation.h" #include "nsILDAPMessage.h" #include "nsIComponentManager.h" +#include "nsXPIDLString.h" struct timeval nsLDAPOperation::sNullTimeval = {0, 0}; @@ -87,10 +88,16 @@ nsLDAPOperation::GetConnection(nsILDAPConnection* *aConnection) // wrapper for ldap_simple_bind() // NS_IMETHODIMP -nsLDAPOperation::SimpleBind(const char *who, const char *passwd) +nsLDAPOperation::SimpleBind(const char *passwd) { - this->mMsgId = ldap_simple_bind(this->mConnectionHandle, who, - passwd); + nsresult rv; + nsXPIDLCString bindName; + + rv = this->mConnection->GetBindName(getter_Copies(bindName)); + if (NS_FAILED(rv)) + return rv; + + this->mMsgId = ldap_simple_bind(this->mConnectionHandle, bindName, passwd); if (this->mMsgId == -1) { return NS_ERROR_FAILURE;