From e8a2b5393f19614db0e46603aaed2bcaa9150fe3 Mon Sep 17 00:00:00 2001 From: "bugzilla%standard8.demon.co.uk" Date: Fri, 9 Mar 2007 16:33:49 +0000 Subject: [PATCH] Bug 124897 Implement editing of a directory in the LDAP XPCOM SDK. Original patch by peterv, updated and revised by me. r=bienvenu,sr=mscott git-svn-id: svn://10.0.0.236/trunk@221612 18797224-902f-48f8-a5cc-f745e15eee43 --- .../directory/xpcom/base/public/Makefile.in | 1 + .../xpcom/base/public/nsILDAPModification.idl | 92 ++++ .../xpcom/base/public/nsILDAPOperation.idl | 127 ++++- mozilla/directory/xpcom/base/src/Makefile.in | 1 + .../xpcom/base/src/nsLDAPBERValue.cpp | 5 +- .../xpcom/base/src/nsLDAPModification.cpp | 200 +++++++ .../xpcom/base/src/nsLDAPModification.h | 73 +++ .../xpcom/base/src/nsLDAPOperation.cpp | 515 +++++++++++++++--- .../xpcom/base/src/nsLDAPOperation.h | 49 +- .../xpcom/base/src/nsLDAPProtocolModule.cpp | 4 + 10 files changed, 980 insertions(+), 87 deletions(-) create mode 100644 mozilla/directory/xpcom/base/public/nsILDAPModification.idl create mode 100644 mozilla/directory/xpcom/base/src/nsLDAPModification.cpp create mode 100644 mozilla/directory/xpcom/base/src/nsLDAPModification.h diff --git a/mozilla/directory/xpcom/base/public/Makefile.in b/mozilla/directory/xpcom/base/public/Makefile.in index 296af988bde..97cce992f94 100644 --- a/mozilla/directory/xpcom/base/public/Makefile.in +++ b/mozilla/directory/xpcom/base/public/Makefile.in @@ -58,6 +58,7 @@ XPIDLSRCS = \ nsILDAPBERValue.idl \ nsILDAPControl.idl \ nsILDAPBERElement.idl \ + nsILDAPModification.idl \ $(NULL) ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL diff --git a/mozilla/directory/xpcom/base/public/nsILDAPModification.idl b/mozilla/directory/xpcom/base/public/nsILDAPModification.idl new file mode 100644 index 00000000000..71c960d1b40 --- /dev/null +++ b/mozilla/directory/xpcom/base/public/nsILDAPModification.idl @@ -0,0 +1,92 @@ +/* -*- 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 the mozilla.org LDAP XPCOM SDK. + * + * The Initial Developer of the Original Code is + * Peter Van der Beken. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Peter Van der Beken. All Rights Reserved. + * + * Contributor(s): + * Peter Van der Beken + * Mark Banner + * + * 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 nsILDAPBERValue; +interface nsIArray; + +[scriptable, uuid(f64ef501-0623-11d6-a7f2-b65476fc49dc)] +interface nsILDAPModification : nsISupports +{ + /** + * The operation to perform. + */ + attribute long operation; + + /** + * Add operation + */ + const long MOD_ADD = 0x00; + + /** + * Delete operation + */ + const long MOD_DELETE = 0x01; + + /** + * Replace operation + */ + const long MOD_REPLACE = 0x02; + + /** + * Values are BER encoded + */ + const long MOD_BVALUES = 0x80; + + /** + * The attribute to modify. + */ + attribute ACString type; + + /** + * The array of values this modification sets for the attribute + */ + attribute nsIArray values; + + /** + * Function that allows all the attributes to be set at the same + * time to avoid multiple function calls. + */ + void setUpModification(in long aOperation, in ACString aType, + in nsIArray aValues); + + void setUpModificationOneValue(in long aOperation, in ACString aType, + in nsILDAPBERValue aValue); +}; diff --git a/mozilla/directory/xpcom/base/public/nsILDAPOperation.idl b/mozilla/directory/xpcom/base/public/nsILDAPOperation.idl index abb8ddd848a..adae395c857 100644 --- a/mozilla/directory/xpcom/base/public/nsILDAPOperation.idl +++ b/mozilla/directory/xpcom/base/public/nsILDAPOperation.idl @@ -42,7 +42,9 @@ interface nsILDAPMessage; interface nsILDAPMessageListener; +interface nsILDAPModification; interface nsIMutableArray; +interface nsIArray; %{C++ #define NS_LDAPOPERATION_CONTRACTID "@mozilla.org/network/ldap-operation;1" @@ -52,7 +54,7 @@ interface nsIMutableArray; typedef PRUint32 PRIntervalTime; -[scriptable, uuid(51f3b2f3-1f22-4fa8-9836-2e30e1471bff)] +[scriptable, uuid(b9a7ed9d-adf9-4612-8cb7-cdb5c4ef16fd)] interface nsILDAPOperation : nsISupports { /** @@ -127,6 +129,113 @@ interface nsILDAPOperation : nsISupports */ void simpleBind(in AUTF8String passwd); + /** + * Kicks off an asynchronous add request. The "ext" stands for + * "extensions", and is intended to convey that this method will + * eventually support the extensions described in the + * draft-ietf-ldapext-ldap-c-api-04.txt Internet Draft. + * + * @param aBaseDn Base DN to add + * @param aModCount Number of modifications + * @param aMods Array of modifications + * + * @exception NS_ERROR_NOT_INITIALIZED operation not initialized + * @exception NS_ERROR_INVALID_ARG invalid argument + * @exception NS_ERROR_LDAP_ENCODING_ERROR error during BER-encoding + * @exception NS_ERROR_LDAP_SERVER_DOWN the LDAP server did not + * receive the request or the + * connection was lost + * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory + * @exception NS_ERROR_LDAP_NOT_SUPPORTED not supported in the version + * of the LDAP protocol that the + * client is using + * @exception NS_ERROR_UNEXPECTED an unexpected error has + * occurred + * + * XXX doesn't currently handle LDAPControl params + */ + void addExt(in AUTF8String aBaseDn, in nsIArray aMods); + + /** + * Kicks off an asynchronous delete request. The "ext" stands for + * "extensions", and is intended to convey that this method will + * eventually support the extensions described in the + * draft-ietf-ldapext-ldap-c-api-04.txt Internet Draft. + * + * @param aBaseDn Base DN to delete + * + * @exception NS_ERROR_NOT_INITIALIZED operation not initialized + * @exception NS_ERROR_INVALID_ARG invalid argument + * @exception NS_ERROR_LDAP_ENCODING_ERROR error during BER-encoding + * @exception NS_ERROR_LDAP_SERVER_DOWN the LDAP server did not + * receive the request or the + * connection was lost + * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory + * @exception NS_ERROR_LDAP_NOT_SUPPORTED not supported in the version + * of the LDAP protocol that the + * client is using + * @exception NS_ERROR_UNEXPECTED an unexpected error has + * occurred + * + * XXX doesn't currently handle LDAPControl params + */ + void deleteExt(in AUTF8String aBaseDn); + + /** + * Kicks off an asynchronous modify request. The "ext" stands for + * "extensions", and is intended to convey that this method will + * eventually support the extensions described in the + * draft-ietf-ldapext-ldap-c-api-04.txt Internet Draft. + * + * @param aBaseDn Base DN to modify + * @param aModCount Number of modifications + * @param aMods Array of modifications + * + * @exception NS_ERROR_NOT_INITIALIZED operation not initialized + * @exception NS_ERROR_INVALID_ARG invalid argument + * @exception NS_ERROR_LDAP_ENCODING_ERROR error during BER-encoding + * @exception NS_ERROR_LDAP_SERVER_DOWN the LDAP server did not + * receive the request or the + * connection was lost + * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory + * @exception NS_ERROR_LDAP_NOT_SUPPORTED not supported in the version + * of the LDAP protocol that the + * client is using + * @exception NS_ERROR_UNEXPECTED an unexpected error has + * occurred + * + * XXX doesn't currently handle LDAPControl params + */ + void modifyExt(in AUTF8String aBaseDn, in nsIArray aMods); + + /** + * Kicks off an asynchronous rename request. + * + * @param aBaseDn Base DN to rename + * @param aNewRDn New relative DN + * @param aNewParent DN of the new parent under which to move the + * entry + * @param aDeleteOldRDn Indicates whether to remove the old relative + * DN as a value in the entry or not + * + * @exception NS_ERROR_NOT_INITIALIZED operation not initialized + * @exception NS_ERROR_INVALID_ARG invalid argument + * @exception NS_ERROR_LDAP_ENCODING_ERROR error during BER-encoding + * @exception NS_ERROR_LDAP_SERVER_DOWN the LDAP server did not + * receive the request or the + * connection was lost + * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory + * @exception NS_ERROR_LDAP_NOT_SUPPORTED not supported in the version + * of the LDAP protocol that the + * client is using + * @exception NS_ERROR_UNEXPECTED an unexpected error has + * occurred + * + * XXX doesn't currently handle LDAPControl params + */ + void rename(in AUTF8String aBaseDn, in AUTF8String aNewRDn, + in AUTF8String aNewParent, in boolean aDeleteOldRDn); + /** * Kicks off an asynchronous search request. The "ext" stands for * "extensions", and is intended to convey that this method will @@ -141,12 +250,16 @@ interface nsILDAPOperation : nsISupports * @param aTimeOut How long to wait * @param aSizeLimit Maximum number of entries to return. * - * @exception NS_ERROR_NOT_INITIALIZED - * @exception NS_ERROR_LDAP_ENCODING_ERROR - * @exception NS_ERROR_LDAP_SERVER_DOWN - * @exception NS_ERROR_OUT_OF_MEMORY - * @exception NS_ERROR_INVALID_ARG - * @exception NS_ERROR_LDAP_NOT_SUPPORTED + * @exception NS_ERROR_NOT_INITIALIZED operation not initialized + * @exception NS_ERROR_LDAP_ENCODING_ERROR error during BER-encoding + * @exception NS_ERROR_LDAP_SERVER_DOWN the LDAP server did not + * receive the request or the + * connection was lost + * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory + * @exception NS_ERROR_INVALID_ARG invalid argument + * @exception NS_ERROR_LDAP_NOT_SUPPORTED not supported in the version + * of the LDAP protocol that the + * client is using * @exception NS_ERROR_LDAP_FILTER_ERROR * @exception NS_ERROR_UNEXPECTED */ diff --git a/mozilla/directory/xpcom/base/src/Makefile.in b/mozilla/directory/xpcom/base/src/Makefile.in index d5ce06f34a6..e8677c50468 100644 --- a/mozilla/directory/xpcom/base/src/Makefile.in +++ b/mozilla/directory/xpcom/base/src/Makefile.in @@ -70,6 +70,7 @@ CPPSRCS = \ nsLDAPBERValue.cpp \ nsLDAPControl.cpp \ nsLDAPBERElement.cpp \ + nsLDAPModification.cpp \ $(NULL) ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL diff --git a/mozilla/directory/xpcom/base/src/nsLDAPBERValue.cpp b/mozilla/directory/xpcom/base/src/nsLDAPBERValue.cpp index 63c74f57d7d..8ffdde94770 100644 --- a/mozilla/directory/xpcom/base/src/nsLDAPBERValue.cpp +++ b/mozilla/directory/xpcom/base/src/nsLDAPBERValue.cpp @@ -130,12 +130,9 @@ nsLDAPBERValue::SetFromUTF8(const nsACString & aValue) // copy the data and return // - // XXXdmose should really be ToNewUTF8String, once the appropriate - // signature for that exists - // mSize = aValue.Length(); if (mSize) { - mValue = NS_REINTERPRET_CAST(PRUint8 *, ToNewCString(aValue)); + mValue = NS_REINTERPRET_CAST(PRUint8 *, ToNewCString(aValue)); } else { mValue = 0; } diff --git a/mozilla/directory/xpcom/base/src/nsLDAPModification.cpp b/mozilla/directory/xpcom/base/src/nsLDAPModification.cpp new file mode 100644 index 00000000000..8a45f1a1eeb --- /dev/null +++ b/mozilla/directory/xpcom/base/src/nsLDAPModification.cpp @@ -0,0 +1,200 @@ +/* -*- 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 the mozilla.org LDAP XPCOM SDK. + * + * The Initial Developer of the Original Code is + * Peter Van der Beken. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Peter Van der Beken. All Rights Reserved. + * + * Contributor(s): + * Peter Van der Beken + * Mark Banner + * + * 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 "nsLDAPModification.h" +#include "nsAutoLock.h" +#include "nsILDAPBERValue.h" +#include "nsISimpleEnumerator.h" +#include "nsServiceManagerUtils.h" + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsLDAPModification, nsILDAPModification) + +// constructor +// +nsLDAPModification::nsLDAPModification() : mValuesLock(nsnull) +{ +} + +// destructor +// +nsLDAPModification::~nsLDAPModification() +{ + if (mValuesLock) { + PR_DestroyLock(mValuesLock); + } +} + +nsresult +nsLDAPModification::Init() +{ + if (!mValuesLock) { + mValuesLock = PR_NewLock(); + if (!mValuesLock) { + NS_ERROR("nsLDAPModification::Init: out of memory"); + return NS_ERROR_OUT_OF_MEMORY; + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::GetOperation(PRInt32 *aOperation) +{ + NS_ENSURE_ARG_POINTER(aOperation); + + *aOperation = mOperation; + return NS_OK; +} + +NS_IMETHODIMP nsLDAPModification::SetOperation(PRInt32 aOperation) +{ + mOperation = aOperation; + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::GetType(nsACString& aType) +{ + aType.Assign(mType); + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::SetType(const nsACString& aType) +{ + mType.Assign(aType); + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::GetValues(nsIArray** aResult) +{ + NS_ENSURE_ARG_POINTER(aResult); + + nsAutoLock lock(mValuesLock); + + if (!mValues) + return NS_ERROR_NOT_INITIALIZED; + + NS_ADDREF(*aResult = mValues); + + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::SetValues(nsIArray* aValues) +{ + NS_ENSURE_ARG_POINTER(aValues); + + nsAutoLock lock(mValuesLock); + nsresult rv; + + if (!mValues) + mValues = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + else + rv = mValues->Clear(); + + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr enumerator; + rv = aValues->Enumerate(getter_AddRefs(enumerator)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool hasMoreElements; + rv = enumerator->HasMoreElements(&hasMoreElements); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr value; + + while (hasMoreElements) + { + rv = enumerator->GetNext(getter_AddRefs(value)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mValues->AppendElement(value, PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); + + rv = enumerator->HasMoreElements(&hasMoreElements); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsLDAPModification::SetUpModification(PRInt32 aOperation, + const nsACString &aType, + nsIArray *aValues) +{ + // Set the values using our local function before entering lock + // to avoid deadlocks due to holding the same lock twice. + nsresult rv = SetValues(aValues); + + nsAutoLock lock(mValuesLock); + + mOperation = aOperation; + mType.Assign(aType); + + return rv; +} + +NS_IMETHODIMP +nsLDAPModification::SetUpModificationOneValue(PRInt32 aOperation, + const nsACString &aType, + nsILDAPBERValue *aValue) +{ + NS_ENSURE_ARG_POINTER(aValue); + + nsAutoLock lock(mValuesLock); + + mOperation = aOperation; + mType.Assign(aType); + + nsresult rv; + + if (!mValues) + mValues = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + else + rv = mValues->Clear(); + + NS_ENSURE_SUCCESS(rv, rv); + + return mValues->AppendElement(aValue, PR_FALSE); +} diff --git a/mozilla/directory/xpcom/base/src/nsLDAPModification.h b/mozilla/directory/xpcom/base/src/nsLDAPModification.h new file mode 100644 index 00000000000..658fdb25b51 --- /dev/null +++ b/mozilla/directory/xpcom/base/src/nsLDAPModification.h @@ -0,0 +1,73 @@ +/* -*- 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 the mozilla.org LDAP XPCOM SDK. + * + * The Initial Developer of the Original Code is + * Peter Van der Beken. + * Portions created by the Initial Developer are Copyright (C) 2002 + * Peter Van der Beken. All Rights Reserved. + * + * Contributor(s): + * Peter Van der Beken + * + * 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 ***** */ + +#ifndef _nsLDAPModification_h_ +#define _nsLDAPModification_h_ + +#include "nsILDAPModification.h" +#include "nsIMutableArray.h" +#include "nsString.h" +#include "nsCOMPtr.h" + +// 5b0f4d00-062e-11d6-a7f2-fc943c3c039c +// +#define NS_LDAPMODIFICATION_CID \ +{ 0x5b0f4d00, 0x062e, 0x11d6, \ + { 0xa7, 0xf2, 0xfc, 0x94, 0x3c, 0x3c, 0x03, 0x9c }} + +class nsLDAPModification : public nsILDAPModification +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSILDAPMODIFICATION + + // constructor & destructor + // + nsLDAPModification(); + virtual ~nsLDAPModification(); + + nsresult Init(); + +private: + PRInt32 mOperation; + nsCString mType; + nsCOMPtr mValues; + PRLock* mValuesLock; +}; + +#endif // _nsLDAPModification_h_ diff --git a/mozilla/directory/xpcom/base/src/nsLDAPOperation.cpp b/mozilla/directory/xpcom/base/src/nsLDAPOperation.cpp index 9413f2a0616..2f0b6b1cf9e 100644 --- a/mozilla/directory/xpcom/base/src/nsLDAPOperation.cpp +++ b/mozilla/directory/xpcom/base/src/nsLDAPOperation.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- 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 @@ -39,15 +39,52 @@ #include "nsLDAPInternal.h" #include "nsLDAPOperation.h" +#include "nsLDAPBERValue.h" #include "nsLDAPConnection.h" #include "nsILDAPMessage.h" +#include "nsILDAPModification.h" #include "nsIComponentManager.h" -#include "nsXPIDLString.h" +#include "nsReadableUtils.h" #include "nspr.h" #include "nsISimpleEnumerator.h" #include "nsLDAPControl.h" #include "nsILDAPErrors.h" #include "nsIClassInfoImpl.h" +#include "nsArrayUtils.h" + +// Helper function +static nsresult TranslateLDAPErrorToNSError(const int ldapError) +{ + switch (ldapError) { + case LDAP_SUCCESS: + return NS_OK; + + case LDAP_ENCODING_ERROR: + return NS_ERROR_LDAP_ENCODING_ERROR; + + case LDAP_CONNECT_ERROR: + return NS_ERROR_LDAP_CONNECT_ERROR; + + case LDAP_SERVER_DOWN: + return NS_ERROR_LDAP_SERVER_DOWN; + + case LDAP_NO_MEMORY: + return NS_ERROR_OUT_OF_MEMORY; + + case LDAP_NOT_SUPPORTED: + return NS_ERROR_LDAP_NOT_SUPPORTED; + + case LDAP_PARAM_ERROR: + return NS_ERROR_INVALID_ARG; + + case LDAP_FILTER_ERROR: + return NS_ERROR_LDAP_FILTER_ERROR; + + default: + return NS_ERROR_UNEXPECTED; + } +} + // constructor nsLDAPOperation::nsLDAPOperation() @@ -69,7 +106,6 @@ NS_INTERFACE_MAP_BEGIN(nsLDAPOperation) NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_CI_INTERFACE_GETTER1(nsLDAPOperation, nsILDAPOperation) - /** * Initializes this operation. Must be called prior to use. * @@ -194,27 +230,9 @@ nsLDAPOperation::SimpleBind(const nsACString& passwd) PromiseFlatCString(mSavePassword).get()); if (mMsgID == -1) { - const int lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0); - - switch (lderrno) { - - case LDAP_ENCODING_ERROR: - return NS_ERROR_LDAP_ENCODING_ERROR; - - case LDAP_CONNECT_ERROR: - return NS_ERROR_LDAP_CONNECT_ERROR; - - case LDAP_SERVER_DOWN: - // XXXdmose rebind here? - return NS_ERROR_LDAP_SERVER_DOWN; - - case LDAP_NO_MEMORY: - return NS_ERROR_OUT_OF_MEMORY; - - default: - return NS_ERROR_UNEXPECTED; - } - + // XXX Should NS_ERROR_LDAP_SERVER_DOWN cause a rebind here? + return TranslateLDAPErrorToNSError(ldap_get_lderrno(mConnectionHandle, + 0, 0)); } // make sure the connection knows where to call back once the messages @@ -399,33 +417,8 @@ nsLDAPOperation::SearchExt(const nsACString& aBaseDn, PRInt32 aScope, nsMemory::Free(attrs); } - switch (retVal) { - - case LDAP_SUCCESS: - break; - - case LDAP_ENCODING_ERROR: - return NS_ERROR_LDAP_ENCODING_ERROR; - - case LDAP_SERVER_DOWN: - return NS_ERROR_LDAP_SERVER_DOWN; - - case LDAP_NO_MEMORY: - return NS_ERROR_OUT_OF_MEMORY; - - case LDAP_NOT_SUPPORTED: - return NS_ERROR_LDAP_NOT_SUPPORTED; - - case LDAP_PARAM_ERROR: - return NS_ERROR_INVALID_ARG; - - case LDAP_FILTER_ERROR: - return NS_ERROR_LDAP_FILTER_ERROR; - - default: - NS_ERROR("nsLDAPOperation::SearchExt(): unexpected return value"); - return NS_ERROR_UNEXPECTED; - } + rv = TranslateLDAPErrorToNSError(retVal); + NS_ENSURE_SUCCESS(rv, rv); // make sure the connection knows where to call back once the messages // for this operation start coming in @@ -481,30 +474,9 @@ nsLDAPOperation::AbandonExt() return NS_ERROR_NOT_IMPLEMENTED; } - rv = ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0); - switch (rv) { - - case LDAP_SUCCESS: - break; - - case LDAP_ENCODING_ERROR: - return NS_ERROR_LDAP_ENCODING_ERROR; - - case LDAP_SERVER_DOWN: - retStatus = NS_ERROR_LDAP_SERVER_DOWN; - break; - - case LDAP_NO_MEMORY: - return NS_ERROR_OUT_OF_MEMORY; - - case LDAP_PARAM_ERROR: - return NS_ERROR_INVALID_ARG; - - default: - NS_ERROR("nsLDAPOperation::AbandonExt(): unexpected return value from " - "ldap_abandon_ext"); - return NS_ERROR_UNEXPECTED; - } + rv = TranslateLDAPErrorToNSError(ldap_abandon_ext(mConnectionHandle, + mMsgID, 0, 0)); + NS_ENSURE_SUCCESS(rv, rv); // try to remove it from the pendingOperations queue, if it's there. // even if something goes wrong here, the abandon() has already succeeded @@ -559,3 +531,396 @@ NS_IMETHODIMP nsLDAPOperation::SetServerControls(nsIMutableArray *aControls) mServerControls = aControls; return NS_OK; } + +// wrappers for ldap_add_ext +// +nsresult +nsLDAPOperation::AddExt(const char *base, + nsIArray *mods, + LDAPControl **serverctrls, + LDAPControl **clientctrls) +{ + if (mMessageListener == 0) { + NS_ERROR("nsLDAPOperation::AddExt(): mMessageListener not set"); + return NS_ERROR_NOT_INITIALIZED; + } + + LDAPMod **attrs = 0; + int retVal = LDAP_SUCCESS; + PRUint32 modCount = 0; + nsresult rv = mods->GetLength(&modCount); + NS_ENSURE_SUCCESS(rv, rv); + + if (mods && modCount) { + attrs = NS_STATIC_CAST(LDAPMod **, nsMemory::Alloc((modCount + 1) * + sizeof(LDAPMod *))); + if (!attrs) { + NS_ERROR("nsLDAPOperation::AddExt: out of memory "); + return NS_ERROR_OUT_OF_MEMORY; + } + + nsCAutoString type; + PRUint32 index; + for (index = 0; index < modCount && NS_SUCCEEDED(rv); ++index) { + attrs[index] = new LDAPMod(); + + if (!attrs[index]) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr modif(do_QueryElementAt(mods, index, &rv)); + if (NS_FAILED(rv)) + break; + +#ifdef NS_DEBUG + PRInt32 operation; + NS_ASSERTION(NS_SUCCEEDED(modif->GetOperation(&operation)) && + (operation | nsILDAPModification::MOD_ADD), + "AddExt can only add."); +#endif + + attrs[index]->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; + + nsresult rv = modif->GetType(type); + if (NS_FAILED(rv)) + break; + + attrs[index]->mod_type = ToNewCString(type); + + rv = CopyValues(modif, &attrs[index]->mod_bvalues); + if (NS_FAILED(rv)) + break; + } + + if (NS_SUCCEEDED(rv)) { + attrs[modCount] = 0; + + retVal = ldap_add_ext(mConnectionHandle, base, attrs, + serverctrls, clientctrls, &mMsgID); + } + else + // reset the modCount so we correctly free the array. + modCount = index; + } + + for (PRUint32 counter = 0; counter < modCount; ++counter) + delete attrs[counter]; + + nsMemory::Free(attrs); + + return NS_FAILED(rv) ? rv : TranslateLDAPErrorToNSError(retVal); +} + +/** + * wrapper for ldap_add_ext(): kicks off an async add request. + * + * @param aBaseDn Base DN to search + * @param aModCount Number of modifications + * @param aMods Array of modifications + * + * XXX doesn't currently handle LDAPControl params + * + * void addExt (in AUTF8String aBaseDn, in unsigned long aModCount, + * [array, size_is (aModCount)] in nsILDAPModification aMods); + */ +NS_IMETHODIMP +nsLDAPOperation::AddExt(const nsACString& aBaseDn, + nsIArray *aMods) +{ + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::AddExt(): called with aBaseDn = '%s'", + PromiseFlatCString(aBaseDn).get())); + + nsresult rv = AddExt(PromiseFlatCString(aBaseDn).get(), aMods, 0, 0); + if (NS_FAILED(rv)) + return rv; + + // make sure the connection knows where to call back once the messages + // for this operation start coming in + rv = NS_STATIC_CAST(nsLDAPConnection *, NS_STATIC_CAST(nsILDAPConnection *, + mConnection.get()))->AddPendingOperation(this); + + if (NS_FAILED(rv)) { + (void*)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0); + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::AddExt(): abandoned due to rv %x", + rv)); + } + return rv; +} + +// wrappers for ldap_delete_ext +// +nsresult +nsLDAPOperation::DeleteExt(const char *base, + LDAPControl **serverctrls, + LDAPControl **clientctrls) +{ + if (mMessageListener == 0) { + NS_ERROR("nsLDAPOperation::DeleteExt(): mMessageListener not set"); + return NS_ERROR_NOT_INITIALIZED; + } + + return TranslateLDAPErrorToNSError(ldap_delete_ext(mConnectionHandle, base, + serverctrls, clientctrls, + &mMsgID)); +} + +/** + * wrapper for ldap_delete_ext(): kicks off an async delete request. + * + * @param aBaseDn Base DN to delete + * + * XXX doesn't currently handle LDAPControl params + * + * void deleteExt(in AUTF8String aBaseDn); + */ +NS_IMETHODIMP +nsLDAPOperation::DeleteExt(const nsACString& aBaseDn) +{ + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::DeleteExt(): called with aBaseDn = '%s'", + PromiseFlatCString(aBaseDn).get())); + + nsresult rv = DeleteExt(PromiseFlatCString(aBaseDn).get(), 0, 0); + if (NS_FAILED(rv)) + return rv; + + // make sure the connection knows where to call back once the messages + // for this operation start coming in + rv = NS_STATIC_CAST(nsLDAPConnection *, + NS_STATIC_CAST(nsILDAPConnection *, + mConnection.get()))->AddPendingOperation(this); + + if (NS_FAILED(rv)) { + (void*)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0); + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::AddExt(): abandoned due to rv %x", + rv)); + } + return rv; +} + +// wrappers for ldap_modify_ext +// +nsresult +nsLDAPOperation::ModifyExt(const char *base, + nsIArray *mods, + LDAPControl **serverctrls, + LDAPControl **clientctrls) +{ + if (mMessageListener == 0) { + NS_ERROR("nsLDAPOperation::ModifyExt(): mMessageListener not set"); + return NS_ERROR_NOT_INITIALIZED; + } + + LDAPMod **attrs = 0; + int retVal = 0; + PRUint32 modCount = 0; + nsresult rv = mods->GetLength(&modCount); + NS_ENSURE_SUCCESS(rv, rv); + if (modCount && mods) { + attrs = NS_STATIC_CAST(LDAPMod **, nsMemory::Alloc((modCount + 1) * + sizeof(LDAPMod *))); + if (!attrs) { + NS_ERROR("nsLDAPOperation::ModifyExt: out of memory "); + return NS_ERROR_OUT_OF_MEMORY; + } + + nsCAutoString type; + PRUint32 index; + for (index = 0; index < modCount && NS_SUCCEEDED(rv); ++index) { + attrs[index] = new LDAPMod(); + if (!attrs[index]) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr modif(do_QueryElementAt(mods, index, &rv)); + if (NS_FAILED(rv)) + break; + + PRInt32 operation; + nsresult rv = modif->GetOperation(&operation); + if (NS_FAILED(rv)) + break; + + attrs[index]->mod_op = operation | LDAP_MOD_BVALUES; + + rv = modif->GetType(type); + if (NS_FAILED(rv)) + break; + + attrs[index]->mod_type = ToNewCString(type); + + rv = CopyValues(modif, &attrs[index]->mod_bvalues); + if (NS_FAILED(rv)) + break; + } + + if (NS_SUCCEEDED(rv)) { + attrs[modCount] = 0; + + retVal = ldap_modify_ext(mConnectionHandle, base, attrs, + serverctrls, clientctrls, &mMsgID); + } + else + // reset the modCount so we correctly free the array. + modCount = index; + + } + + for (PRUint32 counter = 0; counter < modCount; ++counter) + delete attrs[counter]; + + nsMemory::Free(attrs); + + return NS_FAILED(rv) ? rv : TranslateLDAPErrorToNSError(retVal); +} + +/** + * wrapper for ldap_modify_ext(): kicks off an async modify request. + * + * @param aBaseDn Base DN to modify + * @param aModCount Number of modifications + * @param aMods Array of modifications + * + * XXX doesn't currently handle LDAPControl params + * + * void modifyExt (in AUTF8String aBaseDn, in unsigned long aModCount, + * [array, size_is (aModCount)] in nsILDAPModification aMods); + */ +NS_IMETHODIMP +nsLDAPOperation::ModifyExt(const nsACString& aBaseDn, + nsIArray *aMods) +{ + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::ModifyExt(): called with aBaseDn = '%s'", + PromiseFlatCString(aBaseDn).get())); + + nsresult rv = ModifyExt(PromiseFlatCString(aBaseDn).get(), + aMods, 0, 0); + if (NS_FAILED(rv)) + return rv; + + // make sure the connection knows where to call back once the messages + // for this operation start coming in + rv = NS_STATIC_CAST(nsLDAPConnection *, + NS_STATIC_CAST(nsILDAPConnection *, + mConnection.get()))->AddPendingOperation(this); + + if (NS_FAILED(rv)) { + (void*)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0); + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::AddExt(): abandoned due to rv %x", + rv)); + } + return rv; +} + +// wrappers for ldap_rename +// +nsresult +nsLDAPOperation::Rename(const char *base, + const char *newRDn, + const char *newParent, + PRBool deleteOldRDn, + LDAPControl **serverctrls, + LDAPControl **clientctrls) +{ + if (mMessageListener == 0) { + NS_ERROR("nsLDAPOperation::Rename(): mMessageListener not set"); + return NS_ERROR_NOT_INITIALIZED; + } + + return TranslateLDAPErrorToNSError(ldap_rename(mConnectionHandle, base, + newRDn, newParent, + deleteOldRDn, serverctrls, + clientctrls, &mMsgID)); +} + +/** + * wrapper for ldap_rename(): kicks off an async rename request. + * + * @param aBaseDn Base DN to rename + * @param aNewRDn New relative DN + * @param aNewParent DN of the new parent under which to move the + * + * XXX doesn't currently handle LDAPControl params + * + * void rename(in AUTF8String aBaseDn, in AUTF8String aNewRDn, + * in AUTF8String aNewParent, in boolean aDeleteOldRDn); + */ +NS_IMETHODIMP +nsLDAPOperation::Rename(const nsACString& aBaseDn, + const nsACString& aNewRDn, + const nsACString& aNewParent, + PRBool aDeleteOldRDn) +{ + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::Rename(): called with aBaseDn = '%s'", + PromiseFlatCString(aBaseDn).get())); + + nsresult rv = Rename(PromiseFlatCString(aBaseDn).get(), + PromiseFlatCString(aNewRDn).get(), + PromiseFlatCString(aNewParent).get(), + aDeleteOldRDn, 0, 0); + if (NS_FAILED(rv)) + return rv; + + // make sure the connection knows where to call back once the messages + // for this operation start coming in + rv = NS_STATIC_CAST(nsLDAPConnection *, + NS_STATIC_CAST(nsILDAPConnection *, + mConnection.get()))->AddPendingOperation(this); + + if (NS_FAILED(rv)) { + (void*)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0); + PR_LOG(gLDAPLogModule, PR_LOG_DEBUG, + ("nsLDAPOperation::AddExt(): abandoned due to rv %x", + rv)); + } + return rv; +} + +// wrappers for ldap_search_ext +// + +/* static */ +nsresult +nsLDAPOperation::CopyValues(nsILDAPModification* aMod, berval*** aBValues) +{ + nsCOMPtr values; + nsresult rv = aMod->GetValues(getter_AddRefs(values)); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 valuesCount; + rv = values->GetLength(&valuesCount); + NS_ENSURE_SUCCESS(rv, rv); + + *aBValues = NS_STATIC_CAST(berval **, + nsMemory::Alloc((valuesCount + 1) * + sizeof(berval *))); + if (!*aBValues) + return NS_ERROR_OUT_OF_MEMORY; + + PRUint32 valueIndex; + for (valueIndex = 0; valueIndex < valuesCount; ++valueIndex) { + nsCOMPtr value(do_QueryElementAt(values, valueIndex, &rv)); + + berval* bval = new berval; + if (NS_FAILED(rv) || !bval) { + for (PRUint32 counter = 0; + counter < valueIndex && counter < valuesCount; + ++counter) + delete (*aBValues)[valueIndex]; + + nsMemory::Free(*aBValues); + delete bval; + return NS_ERROR_OUT_OF_MEMORY; + } + value->Get((PRUint32*)&bval->bv_len, + (PRUint8**)&bval->bv_val); + (*aBValues)[valueIndex] = bval; + } + + (*aBValues)[valuesCount] = 0; + return NS_OK; +} diff --git a/mozilla/directory/xpcom/base/src/nsLDAPOperation.h b/mozilla/directory/xpcom/base/src/nsLDAPOperation.h index 78cd0d5cddc..72cb3707dc9 100644 --- a/mozilla/directory/xpcom/base/src/nsLDAPOperation.h +++ b/mozilla/directory/xpcom/base/src/nsLDAPOperation.h @@ -69,7 +69,54 @@ class nsLDAPOperation : public nsILDAPOperation * used to break cycles */ void Clear(); - protected: + + private: + /** + * wrapper for ldap_add_ext() + * + * XXX should move to idl, once LDAPControls have an IDL representation + */ + nsresult AddExt(const char *base, // base DN to add + nsIArray *mods, // Array of modifications + LDAPControl **serverctrls, + LDAPControl **clientctrls); + + /** + * wrapper for ldap_delete_ext() + * + * XXX should move to idl, once LDAPControls have an IDL representation + */ + nsresult DeleteExt(const char *base, // base DN to delete + LDAPControl **serverctrls, + LDAPControl **clientctrls); + + /** + * wrapper for ldap_modify_ext() + * + * XXX should move to idl, once LDAPControls have an IDL representation + */ + nsresult ModifyExt(const char *base, // base DN to modify + nsIArray *mods, // array of modifications + LDAPControl **serverctrls, + LDAPControl **clientctrls); + + /** + * wrapper for ldap_rename() + * + * XXX should move to idl, once LDAPControls have an IDL representation + */ + nsresult Rename(const char *base, // base DN to rename + const char *newRDn, // new RDN + const char *newParent, // DN of the new parent + PRBool deleteOldRDn, // remove old RDN in the entry? + LDAPControl **serverctrls, + LDAPControl **clientctrls); + + /** + * Helper function to copy the values of an nsILDAPModification into an + * array of berval's. + */ + static nsresult CopyValues(nsILDAPModification* aMod, berval*** aBValues); nsCOMPtr mMessageListener; // results go here nsCOMPtr mClosure; // private parameter (anything caller desires) diff --git a/mozilla/directory/xpcom/base/src/nsLDAPProtocolModule.cpp b/mozilla/directory/xpcom/base/src/nsLDAPProtocolModule.cpp index d8516ac0759..a6c5fb31270 100644 --- a/mozilla/directory/xpcom/base/src/nsLDAPProtocolModule.cpp +++ b/mozilla/directory/xpcom/base/src/nsLDAPProtocolModule.cpp @@ -46,6 +46,7 @@ #include "nsLDAPConnection.h" #include "nsLDAPOperation.h" #include "nsLDAPMessage.h" +#include "nsLDAPModification.h" #include "nsLDAPServer.h" #include "nsLDAPService.h" #include "nsLDAPBERValue.h" @@ -64,6 +65,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPConnection) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPOperation) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPMessage) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsLDAPModification, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLDAPServer) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsLDAPURL, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsLDAPService, Init) @@ -110,6 +112,8 @@ static const nsModuleComponentInfo components[] = nsnull, // no language helper &NS_CLASSINFO_NAME(nsLDAPMessage), nsIClassInfo::THREADSAFE }, + { "LDAP Modification", NS_LDAPMODIFICATION_CID, + "@mozilla.org/network/ldap-modification;1", nsLDAPModificationConstructor }, { "LDAP Server", NS_LDAPSERVER_CID, "@mozilla.org/network/ldap-server;1", nsLDAPServerConstructor }, { "LDAP Service", NS_LDAPSERVICE_CID,