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
This commit is contained in:
bugzilla%standard8.demon.co.uk 2007-03-09 16:33:49 +00:00
parent 5bbc610a60
commit e8a2b5393f
10 changed files with 980 additions and 87 deletions

View File

@ -58,6 +58,7 @@ XPIDLSRCS = \
nsILDAPBERValue.idl \
nsILDAPControl.idl \
nsILDAPBERElement.idl \
nsILDAPModification.idl \
$(NULL)
ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL

View File

@ -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 <peterv@propagandism.org>
* Mark Banner <mark@standard8.demon.co.uk>
*
* 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);
};

View File

@ -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
*/

View File

@ -70,6 +70,7 @@ CPPSRCS = \
nsLDAPBERValue.cpp \
nsLDAPControl.cpp \
nsLDAPBERElement.cpp \
nsLDAPModification.cpp \
$(NULL)
ifdef MOZ_LDAP_XPCOM_EXPERIMENTAL

View File

@ -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;
}

View File

@ -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 <peterv@propagandism.org>
* Mark Banner <mark@standard8.demon.co.uk>
*
* 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<nsISimpleEnumerator> enumerator;
rv = aValues->Enumerate(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMoreElements;
rv = enumerator->HasMoreElements(&hasMoreElements);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsISupports> 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);
}

View File

@ -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 <peterv@propagandism.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 ***** */
#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<nsIMutableArray> mValues;
PRLock* mValuesLock;
};
#endif // _nsLDAPModification_h_

View File

@ -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<nsILDAPModification> 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<nsILDAPModification> 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<nsIArray> 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<nsILDAPBERValue> 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;
}

View File

@ -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<nsILDAPMessageListener> mMessageListener; // results go here
nsCOMPtr<nsISupports> mClosure; // private parameter (anything caller desires)

View File

@ -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,