mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 20:07:30 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
24
ldap/xpcom/README.txt
Normal file
24
ldap/xpcom/README.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
This is the home for XPCOM modules that implement LDAP functionality.
|
||||
|
||||
What's Here
|
||||
-----------
|
||||
base/
|
||||
Implements a wrapper around the LDAP C SDK, as well as support
|
||||
for ldap: URLs in the browser. Written entirely in C++;
|
||||
theoretically only depends on necko, xpcom, nspr, and the LDAP
|
||||
C SDK.
|
||||
|
||||
datasource/
|
||||
An RDF datasource, written in Javascript.
|
||||
|
||||
tests/
|
||||
Some basic tests to help ensure that things don't break as
|
||||
development proceeds. Currently, there is only some stuff for
|
||||
testing the datasource.
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
See <http://www.mozilla.org/directory/xpcom.html>.
|
||||
|
||||
Dan Mosedale <dmose@mozilla.org>
|
||||
155
ldap/xpcom/TODO.txt
Normal file
155
ldap/xpcom/TODO.txt
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
housecleaning for first 0.x release
|
||||
-----------------------------------
|
||||
* error handling: sort out what should be NS_ASSERTIONs vs. normal
|
||||
error conditions (eg network & data errors), especially in nsLDAPChannel.
|
||||
also shouldn't be casting results of nsILDAPConnection::GetErrorString to
|
||||
void in ldapSearch. (ideally this would use xpidl nsresult decls
|
||||
(bug 13423), but that's not done yet). This also requires some
|
||||
threadsafety work related to the data and interfaces touched by
|
||||
nsLDAPChannel::Cancel, since these are used in the connection
|
||||
callbacks, and we also need to be able to cancel from the connection
|
||||
callbacks themselves.
|
||||
|
||||
* audit for and fix leaks / bloat
|
||||
|
||||
* destroy connection & thread when done with it; deal with timeouts
|
||||
(blocked on LDAP C SDK 4.1, in the hopes that the NSPR
|
||||
binding of the IO functions will provide us with some way to pop out
|
||||
of the select() that's called under ldap_result(). It may not be worth
|
||||
implementing this until nsLDAPService is resurrected. If this
|
||||
doesn't work, we may have to give nsLDAPConnection an event queue &
|
||||
loop of its own, instead of using the LDAP C SDK as a vector to get
|
||||
events over there.
|
||||
|
||||
items blocked waiting for other work
|
||||
------------------------------------
|
||||
* go through the various options that can be used with the SDK function
|
||||
ldap_set_options() and decide if and where the various functions should
|
||||
be used. This will include memory allocator settings, and possibly
|
||||
threadsafety callbacks (if necessary). (blocked waiting on LDAP C
|
||||
SDK 4.1 to land, since it contains NSPR bindings for some of this).
|
||||
|
||||
* searches that return lots of entries to the nsLDAPChannel
|
||||
(eg (sn=Smith) at netcenter) mostly stall out the UI. moving most of the
|
||||
callback work off the UI thread to the LDAP connection thread didn't
|
||||
help; so this seems to be lossage in the event system itself (bug 50104).
|
||||
|
||||
* deal with race condition that happens if data comes back after
|
||||
nsLDAPChannel::Cancel is called. AsyncStreamListener expects
|
||||
GetStatus to return OK, and asserts when it doesn't. (blocked waiting
|
||||
on insight from Warren about nsSocketTransport's use of mCancelStatus).
|
||||
|
||||
* ensure that multiple calls to Cancel don't do the wrong thing
|
||||
|
||||
* move the ldap_unbind() call out of the nsLDAPConnection destructor,
|
||||
since nsLDAPConnection will soon go back to being callable from the
|
||||
UI thread, and ldap_unbind() is actually synchronous. additionally,
|
||||
arrange for the connection thread to shutdown. (waiting for
|
||||
nsILDAPService to be implemented on the theory that nsILDAPService
|
||||
might have it's own thread and it would be reasonable to call
|
||||
ldap_unbind() from that thread).
|
||||
|
||||
* currently nsILDAPOperation::SimpleBind is called as though it were
|
||||
asynchronous (ie from the UI thread), which it mostly is -- the call
|
||||
to connect() can stall. We could use the ASYNC_CONNECT flag, but it
|
||||
seems to do weird stuff on Linux, and mcs says it isn't well tested
|
||||
anyway. At the moment, my feeling is that fixing ASYNC_CONNECT is
|
||||
probably the right thing to do, but the bind could actually be
|
||||
pushed from nsILDAPOperation into nsILDAPConnection and then called
|
||||
after the thread for the connection is spun up (waiting on help from
|
||||
the LDAP SDK folks: bug 50074).
|
||||
|
||||
misc
|
||||
----
|
||||
* verify that ldap_parse_result() and ldap_get_ldaperrno() aren't
|
||||
required to be called from the same thread as ldap_result() and
|
||||
before the thread-specific ldaperrno has a chance to change. Note:
|
||||
now that ldap_parse_result is only called inside the initializer
|
||||
nsLDAPMessage::Init(), this is probably no longer an issue there at
|
||||
least. Need to confirm.
|
||||
|
||||
* replace instances of (obsolete) |static NS_DEFINE_IID| variables
|
||||
with direct calls to NS_GET_IID in the code.
|
||||
|
||||
* investigate use of DNS in LDAP sdk. I think sync functions used in the
|
||||
wrong places (eg they end up getting called from Mozilla on the UI thread)?
|
||||
|
||||
* audit for and implement any appropriate NOT_IMPLEMENTED functions
|
||||
|
||||
* re-read the IDL for interfaces implemented by nsLDAPChannel.cpp make sure
|
||||
all interfaces are implemented correctly
|
||||
|
||||
* implement progress info interfaces, if possible (% done)
|
||||
|
||||
* investigate the MOZILLA_CLIENT define as used by the SDK. eg do we still
|
||||
want the reference to "xp_sort.h"?
|
||||
|
||||
* i18n / l10n (any text strings)
|
||||
|
||||
* cachability of nsILDAPChannel content: browser cache? ldap_memcache? both?
|
||||
|
||||
* use a rebind_proc?
|
||||
|
||||
* HTMLize nsLDAPChannel output for linkification
|
||||
* the LDAP SDK returns UTF8, but I think nsILDAPChannel is handing it
|
||||
off to callers as ASCII. How does this all relate to the stated
|
||||
UCS2 policy in Mozilla?
|
||||
|
||||
* all attributes are assumed to be strings right now. This probably
|
||||
needs to change: assume all attributes are binary, use some
|
||||
heuristic to figure out if they're a string. I wonder how
|
||||
ldapsearch does this.
|
||||
|
||||
* grep for XXXs and fix the issues
|
||||
|
||||
rdf datasource
|
||||
--------------
|
||||
|
||||
* revamp nsILDAPService (currently unused code) to manage LDAP
|
||||
connections and allow for sharing connections between browser
|
||||
clients. I think this should obviate the need to hold onto the
|
||||
connection with a delegate factory.
|
||||
|
||||
* non-anonymous binding (ie nsLDAPURL supports x-bind-name -- I
|
||||
suspect this may come with the LDAP C SDK version after 4.1,
|
||||
though.)
|
||||
|
||||
testing
|
||||
-------
|
||||
* see how the browser copes when it does such a big search that the server
|
||||
only returns partial results and an error.
|
||||
|
||||
perf
|
||||
----
|
||||
* rather than having one thread per nsILDAPConnection, have multiple
|
||||
nsILDAPConnections share the same thread. possibly pre-spin up a
|
||||
thread-pool to handle this?
|
||||
|
||||
* nsLDAPService: assuming that we do the above and start using
|
||||
nsLDAPService again, need to implement shutdown for nsLDAPService
|
||||
(probably analogous to the way nsSocketTransportService shuts down.
|
||||
but how does nsIShutdownListener fit in here? and CanUnload?)
|
||||
|
||||
* remove any unnecessary thread-safety code (NS_IMPL_THREADSAFE) to avoid
|
||||
locking overhead. need to figure out if everything must be
|
||||
threadsafe or not.
|
||||
|
||||
later
|
||||
-----
|
||||
* rationalize the logging strategy. right now there is a mix of
|
||||
PR_LOG/NS{WARNING|ERROR} and nsIConsoleService and non-logging,
|
||||
as I have been vacillating on how much logging it's really important to have
|
||||
(part of my thought process about the XPCOM-wrapper being part of
|
||||
Mozilla-as-platform)
|
||||
* get rid of inappropriate use of nsVoidKey by implementing an nsPRInt32Key
|
||||
* handle referrals
|
||||
* failover
|
||||
* addressbook/mail UI glue
|
||||
* PSM certs from directory glue(?)
|
||||
* secure (& proxied/socksified?) ldap
|
||||
* make the LDAP C SDK autoconf glue not be a shim and not require
|
||||
nsprpub build infrastructure. requires work with the LDAP C SDK
|
||||
owners, and shouldn't this shouldn't happen until after the most
|
||||
current ldap SDK code lands in mozilla.org anyway.
|
||||
* figure out our strategy for LDAPv2 vs. LDAPv3. right now, the code just
|
||||
uses the C SDK's default of always advertising itself as LDAPv2.
|
||||
9
ldap/xpcom/moz.build
Normal file
9
ldap/xpcom/moz.build
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'public',
|
||||
'src',
|
||||
]
|
||||
27
ldap/xpcom/public/moz.build
Normal file
27
ldap/xpcom/public/moz.build
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsILDAPBERElement.idl',
|
||||
'nsILDAPBERValue.idl',
|
||||
'nsILDAPConnection.idl',
|
||||
'nsILDAPControl.idl',
|
||||
'nsILDAPErrors.idl',
|
||||
'nsILDAPMessage.idl',
|
||||
'nsILDAPMessageListener.idl',
|
||||
'nsILDAPModification.idl',
|
||||
'nsILDAPOperation.idl',
|
||||
'nsILDAPServer.idl',
|
||||
'nsILDAPService.idl',
|
||||
'nsILDAPURL.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PREF_EXTENSIONS']:
|
||||
XPIDL_SOURCES += [
|
||||
'nsILDAPSyncQuery.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'mozldap'
|
||||
|
||||
122
ldap/xpcom/public/nsILDAPBERElement.idl
Normal file
122
ldap/xpcom/public/nsILDAPBERElement.idl
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILDAPBERValue;
|
||||
|
||||
|
||||
/**
|
||||
* nsILDAPBERElement is a wrapper interface for a C-SDK BerElement object.
|
||||
* Typically, this is used as an intermediate object to aid in the manual
|
||||
* construction of a BER value. Once the construction is completed by calling
|
||||
* methods on this object, an nsILDAPBERValue can be retrieved from the
|
||||
* asValue attribute on this interface.
|
||||
*
|
||||
* <http://www.mozilla.org/directory/ietf-docs/draft-ietf-ldapext-ldap-c-api-05.txt>
|
||||
* contains some documentation that mostly (but not exactly) matches
|
||||
* the code that this wraps in section 17.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(409f5b31-c062-4d11-a35b-0a09e7967bf2)]
|
||||
interface nsILDAPBERElement : nsISupports
|
||||
{
|
||||
/**
|
||||
* Initialize this object. Must be called before calling any other method
|
||||
* on this interface.
|
||||
*
|
||||
* @param aValue value to preinitialize with; 0 for a new empty object
|
||||
*
|
||||
* @exception NS_ERROR_NOT_IMPLEMENTED preinitialization is currently
|
||||
* not implemented
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY unable to allocate the internal
|
||||
* BerElement
|
||||
*/
|
||||
void init(in nsILDAPBERValue aValue);
|
||||
|
||||
/**
|
||||
* Most TAG_* constants can be used in the construction or passing in of
|
||||
* values to the aTag arguments to most of the methods in this interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* When returned from a parsing method, 0xffffffff is referred to
|
||||
* has the parse-error semantic (ie TAG_LBER_ERROR); when passing it to
|
||||
* a construction method, it is used to mean "pick the default tag for
|
||||
* this type" (ie TAG_LBER_DEFAULT).
|
||||
*/
|
||||
const unsigned long TAG_LBER_ERROR = 0xffffffff;
|
||||
const unsigned long TAG_LBER_DEFAULT = 0xffffffff;
|
||||
const unsigned long TAG_LBER_END_OF_SEQORSET = 0xfffffffe;
|
||||
|
||||
/**
|
||||
* BER encoding types and masks
|
||||
*/
|
||||
const unsigned long TAG_LBER_PRIMITIVE = 0x00;
|
||||
|
||||
/**
|
||||
* The following two tags are carried over from the LDAP C SDK; their
|
||||
* exact purpose there is not well documented. They both have
|
||||
* the same value there as well.
|
||||
*/
|
||||
const unsigned long TAG_LBER_CONSTRUCTED = 0x20;
|
||||
const unsigned long TAG_LBER_ENCODING_MASK = 0x20;
|
||||
|
||||
const unsigned long TAG_LBER_BIG_TAG_MASK = 0x1f;
|
||||
const unsigned long TAG_LBER_MORE_TAG_MASK = 0x80;
|
||||
|
||||
/**
|
||||
* general BER types we know about
|
||||
*/
|
||||
const unsigned long TAG_LBER_BOOLEAN = 0x01;
|
||||
const unsigned long TAG_LBER_INTEGER = 0x02;
|
||||
const unsigned long TAG_LBER_BITSTRING = 0x03;
|
||||
const unsigned long TAG_LBER_OCTETSTRING = 0x04;
|
||||
const unsigned long TAG_LBER_NULL = 0x05;
|
||||
const unsigned long TAG_LBER_ENUMERATED = 0x0a;
|
||||
const unsigned long TAG_LBER_SEQUENCE = 0x30;
|
||||
const unsigned long TAG_LBER_SET = 0x31;
|
||||
|
||||
/**
|
||||
* Write a string to this element.
|
||||
*
|
||||
* @param aString string to write
|
||||
* @param aTag tag for this string (if TAG_LBER_DEFAULT is used,
|
||||
* TAG_LBER_OCTETSTRING will be written).
|
||||
*
|
||||
* @return number of bytes written
|
||||
*
|
||||
* @exception NS_ERROR_FAILUE C-SDK returned error
|
||||
*/
|
||||
unsigned long putString(in AUTF8String aString, in unsigned long aTag);
|
||||
|
||||
/**
|
||||
* Start a set. Sets may be nested.
|
||||
*
|
||||
* @param aTag tag for this set (if TAG_LBER_DEFAULT is used,
|
||||
* TAG_LBER_SET will be written).
|
||||
*
|
||||
* @exception NS_ERROR_FAILUE C-SDK returned an error
|
||||
*/
|
||||
void startSet(in unsigned long aTag);
|
||||
|
||||
/**
|
||||
* Cause the entire set started by the last startSet() call to be written.
|
||||
*
|
||||
* @exception NS_ERROR_FAILUE C-SDK returned an error
|
||||
*
|
||||
* @return number of bytes written
|
||||
*/
|
||||
unsigned long putSet();
|
||||
|
||||
/**
|
||||
* an nsILDAPBERValue version of this element. Calls ber_flatten() under
|
||||
* the hood.
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
readonly attribute nsILDAPBERValue asValue;
|
||||
};
|
||||
44
ldap/xpcom/public/nsILDAPBERValue.idl
Normal file
44
ldap/xpcom/public/nsILDAPBERValue.idl
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Representation of a BER value as an interface containing an array of
|
||||
* bytes. Someday this should perhaps be obsoleted by a better, more
|
||||
* generalized version of nsIByteBuffer, but that's currently not even
|
||||
* scriptable (see bug 125596).
|
||||
*/
|
||||
[scriptable, uuid(c817c5fe-1dd1-11b2-a10b-ae9885762ea9)]
|
||||
interface nsILDAPBERValue : nsISupports
|
||||
{
|
||||
/**
|
||||
* Set the BER value from an array of bytes (copies).
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY couldn't allocate buffer to copy to
|
||||
*/
|
||||
void set(in unsigned long aCount,
|
||||
[array, size_is(aCount)] in octet aValue);
|
||||
|
||||
/**
|
||||
* Set the BER value from a UTF8 string (copies).
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY couldn't allocate buffer to copy to
|
||||
*/
|
||||
void setFromUTF8(in AUTF8String aValue);
|
||||
|
||||
/**
|
||||
* Get the BER value as an array of bytes. Note that if this value is
|
||||
* zero-length, aCount and aRetVal will both be 0. This means that
|
||||
* (in C++ anyway) the caller MUST test either aCount or aRetval before
|
||||
* dereferencing aRetVal.
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY couldn't allocate buffer to copy to
|
||||
*/
|
||||
void get(out unsigned long aCount,
|
||||
[retval, array, size_is(aCount)] out octet aRetVal);
|
||||
};
|
||||
|
||||
77
ldap/xpcom/public/nsILDAPConnection.idl
Normal file
77
ldap/xpcom/public/nsILDAPConnection.idl
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILDAPOperation;
|
||||
interface nsILDAPMessageListener;
|
||||
interface nsILDAPURL;
|
||||
|
||||
%{C++
|
||||
#define NS_LDAPCONNECTION_CONTRACTID "@mozilla.org/network/ldap-connection;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(360c1ff7-15e3-4ffe-b4b8-0eda72ebc096)]
|
||||
interface nsILDAPConnection : nsISupports
|
||||
{
|
||||
/**
|
||||
* the string version of lderrno
|
||||
*/
|
||||
readonly attribute wstring errorString;
|
||||
|
||||
/**
|
||||
* DN to bind as. use the init() method to set this.
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
readonly attribute AUTF8String bindName;
|
||||
|
||||
/**
|
||||
* private parameter (anything caller desires)
|
||||
*/
|
||||
attribute nsISupports closure;
|
||||
|
||||
/**
|
||||
* Set up the connection. Note that init() must be called on a thread
|
||||
* that already has an nsIEventQueue.
|
||||
*
|
||||
* @param aUrl A URL for the ldap server. The host, port and
|
||||
* ssl connection type will be extracted from this
|
||||
* @param aBindName DN to bind as
|
||||
* @param aMessageListener Callback for DNS resolution completion
|
||||
* @param aClosure private parameter (anything caller desires)
|
||||
* @param aVersion LDAP version to use (currently VERSION2 or
|
||||
* VERSION3)
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer or invalid version
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
* @exception NS_ERROR_OFFLINE we are in off-line mode
|
||||
* @exception NS_ERROR_FAILURE
|
||||
* @exception NS_ERROR_UNEXPECTED internal error
|
||||
*/
|
||||
void init(in nsILDAPURL aUrl,
|
||||
in AUTF8String aBindName,
|
||||
in nsILDAPMessageListener aMessageListener,
|
||||
in nsISupports aClosure, in unsigned long aVersion);
|
||||
|
||||
const unsigned long VERSION2 = 2;
|
||||
const unsigned long VERSION3 = 3;
|
||||
|
||||
/**
|
||||
* Get information about the last error that occured on this connection.
|
||||
*
|
||||
* @param matched if the server is returning LDAP_NO_SUCH_OBJECT,
|
||||
* LDAP_ALIAS_PROBLEM, LDAP_INVALID_DN_SYNTAX,
|
||||
* or LDAP_ALIAS_DEREF_PROBLEM, this will contain
|
||||
* the portion of DN that matches the entry that is
|
||||
* closest to the requested entry
|
||||
*
|
||||
* @param s additional error information from the server
|
||||
*
|
||||
* @return the error code, as defined in nsILDAPErrors.idl
|
||||
*/
|
||||
long getLdErrno(out AUTF8String matched, out AUTF8String s);
|
||||
};
|
||||
45
ldap/xpcom/public/nsILDAPControl.idl
Normal file
45
ldap/xpcom/public/nsILDAPControl.idl
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILDAPBERValue;
|
||||
|
||||
/**
|
||||
* XPCOM representation of the C SDK LDAPControl structure.
|
||||
*/
|
||||
[scriptable, uuid(3a7ceb8e-482a-4a4f-9aa4-26b9a69a3595)]
|
||||
interface nsILDAPControl : nsISupports
|
||||
{
|
||||
/**
|
||||
* Control type, represented as a string.
|
||||
*
|
||||
* @exceptions none
|
||||
*/
|
||||
attribute ACString oid;
|
||||
|
||||
/**
|
||||
* The data associated with a control, if any. To specify that no data
|
||||
* is to be associated with the control, don't set this at all (which
|
||||
* is equivalent to setting it to null).
|
||||
*
|
||||
* @note Specifying a zero-length value is not currently supported. At some
|
||||
* date, setting this to an nsILDAPBERValue which has not had any of the
|
||||
* set methods called will be the appropriate way to do that.
|
||||
*
|
||||
* @exceptions none
|
||||
*/
|
||||
attribute nsILDAPBERValue value;
|
||||
|
||||
/**
|
||||
* Should the client or server abort if the control is not understood?
|
||||
* Should be set to false for server controls used in abandon and unbind
|
||||
* operations, since those have no server response.
|
||||
*
|
||||
* @exceptions none
|
||||
*/
|
||||
attribute boolean isCritical;
|
||||
};
|
||||
447
ldap/xpcom/public/nsILDAPErrors.idl
Normal file
447
ldap/xpcom/public/nsILDAPErrors.idl
Normal file
|
|
@ -0,0 +1,447 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Error codes used in the LDAP XPCOM SDK.
|
||||
*
|
||||
* Taken from the Mozilla C SDK's ldap.h include file, these should be
|
||||
* the same as those specified in the draft-ietf-ldapext-ldap-c-api-04.txt
|
||||
* Internet Draft.
|
||||
*
|
||||
* The only good documentation I'm aware of for these error codes is
|
||||
* at <http://docs.iplanet.com/docs/manuals/directory.html#SDKC>.
|
||||
* Unfortunately, this does not currently seem to be available under any
|
||||
* open source license, so I can't include that documentation here as
|
||||
* doxygen comments.
|
||||
*
|
||||
*/
|
||||
[scriptable, uuid(f9ac10fa-1dd1-11b2-9798-8d5cbda95d74)]
|
||||
interface nsILDAPErrors : nsISupports
|
||||
{
|
||||
|
||||
const long SUCCESS = 0x00;
|
||||
|
||||
const long OPERATIONS_ERROR = 0x01;
|
||||
|
||||
const long PROTOCOL_ERROR = 0x02;
|
||||
|
||||
const long TIMELIMIT_EXCEEDED = 0x03;
|
||||
|
||||
const long SIZELIMIT_EXCEEDED = 0x04;
|
||||
|
||||
const long COMPARE_FALSE = 0x05;
|
||||
|
||||
const long COMPARE_TRUE = 0x06;
|
||||
|
||||
const long STRONG_AUTH_NOT_SUPPORTED = 0x07;
|
||||
|
||||
const long STRONG_AUTH_REQUIRED = 0x08;
|
||||
|
||||
|
||||
/**
|
||||
* UMich LDAPv2 extension
|
||||
*/
|
||||
const long PARTIAL_RESULTS = 0x09;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long REFERRAL = 0x0a;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long ADMINLIMIT_EXCEEDED = 0x0b;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long UNAVAILABLE_CRITICAL_EXTENSION = 0x0c;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long CONFIDENTIALITY_REQUIRED = 0x0d;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long SASL_BIND_IN_PROGRESS = 0x0e;
|
||||
|
||||
const long NO_SUCH_ATTRIBUTE = 0x10;
|
||||
|
||||
const long UNDEFINED_TYPE = 0x11;
|
||||
|
||||
const long INAPPROPRIATE_MATCHING = 0x12;
|
||||
|
||||
const long CONSTRAINT_VIOLATION = 0x13;
|
||||
|
||||
const long TYPE_OR_VALUE_EXISTS = 0x14;
|
||||
|
||||
const long INVALID_SYNTAX = 0x15;
|
||||
|
||||
const long NO_SUCH_OBJECT = 0x20;
|
||||
|
||||
const long ALIAS_PROBLEM = 0x21;
|
||||
|
||||
const long INVALID_DN_SYNTAX = 0x22;
|
||||
|
||||
/**
|
||||
* not used in LDAPv3
|
||||
*/
|
||||
const long IS_LEAF = 0x23;
|
||||
|
||||
const long ALIAS_DEREF_PROBLEM = 0x24;
|
||||
|
||||
const long INAPPROPRIATE_AUTH = 0x30;
|
||||
|
||||
const long INVALID_CREDENTIALS = 0x31;
|
||||
|
||||
const long INSUFFICIENT_ACCESS = 0x32;
|
||||
|
||||
const long BUSY = 0x33;
|
||||
|
||||
const long UNAVAILABLE = 0x34;
|
||||
|
||||
const long UNWILLING_TO_PERFORM = 0x35;
|
||||
|
||||
const long LOOP_DETECT = 0x36;
|
||||
|
||||
/**
|
||||
* server side sort extension
|
||||
*/
|
||||
const long SORT_CONTROL_MISSING = 0x3C;
|
||||
|
||||
/**
|
||||
* VLV extension
|
||||
*/
|
||||
const long INDEX_RANGE_ERROR = 0x3D;
|
||||
|
||||
const long NAMING_VIOLATION = 0x40;
|
||||
|
||||
const long OBJECT_CLASS_VIOLATION = 0x41;
|
||||
|
||||
const long NOT_ALLOWED_ON_NONLEAF = 0x42;
|
||||
|
||||
const long NOT_ALLOWED_ON_RDN = 0x43;
|
||||
|
||||
const long ALREADY_EXISTS = 0x44;
|
||||
|
||||
const long NO_OBJECT_CLASS_MODS = 0x45;
|
||||
|
||||
/**
|
||||
* reserved CLDAP
|
||||
*/
|
||||
const long RESULTS_TOO_LARGE = 0x46;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long AFFECTS_MULTIPLE_DSAS = 0x47;
|
||||
|
||||
const long OTHER = 0x50;
|
||||
|
||||
const long SERVER_DOWN = 0x51;
|
||||
|
||||
const long LOCAL_ERROR = 0x52;
|
||||
|
||||
const long ENCODING_ERROR = 0x53;
|
||||
|
||||
const long DECODING_ERROR = 0x54;
|
||||
|
||||
const long TIMEOUT = 0x55;
|
||||
|
||||
const long AUTH_UNKNOWN = 0x56;
|
||||
|
||||
const long FILTER_ERROR = 0x57;
|
||||
|
||||
const long USER_CANCELLED = 0x58;
|
||||
|
||||
const long PARAM_ERROR = 0x59;
|
||||
|
||||
const long NO_MEMORY = 0x5a;
|
||||
|
||||
const long CONNECT_ERROR = 0x5b;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long NOT_SUPPORTED = 0x5c;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long CONTROL_NOT_FOUND = 0x5d;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long NO_RESULTS_RETURNED = 0x5e;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long MORE_RESULTS_TO_RETURN = 0x5f;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long CLIENT_LOOP = 0x60;
|
||||
|
||||
/**
|
||||
* new in LDAPv3
|
||||
*/
|
||||
const long REFERRAL_LIMIT_EXCEEDED = 0x61;
|
||||
};
|
||||
|
||||
/*
|
||||
* Map these errors codes into the nsresult namespace in C++
|
||||
*/
|
||||
%{C++
|
||||
|
||||
#define NS_ERROR_LDAP_OPERATIONS_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::OPERATIONS_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_PROTOCOL_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::PROTOCOL_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_TIMELIMIT_EXCEEDED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::TIMELIMIT_EXCEEDED)
|
||||
|
||||
#define NS_ERROR_LDAP_SIZELIMIT_EXCEEDED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::SIZELIMIT_EXCEEDED)
|
||||
|
||||
#define NS_ERROR_LDAP_COMPARE_FALSE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::COMPARE_FALSE)
|
||||
|
||||
#define NS_ERROR_LDAP_COMPARE_TRUE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::COMPARE_TRUE)
|
||||
|
||||
#define NS_ERROR_LDAP_STRONG_AUTH_NOT_SUPPORTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::STRONG_AUTH_NOT_SUPPORTED)
|
||||
|
||||
#define NS_ERROR_LDAP_STRONG_AUTH_REQUIRED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::STRONG_AUTH_REQUIRED)
|
||||
|
||||
#define NS_ERROR_LDAP_PARTIAL_RESULTS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::PARTIAL_RESULTS)
|
||||
|
||||
#define NS_ERROR_LDAP_REFERRAL \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::REFERRAL)
|
||||
|
||||
#define NS_ERROR_LDAP_ADMINLIMIT_EXCEEDED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::ADMINLIMIT_EXCEEDED)
|
||||
|
||||
#define NS_ERROR_LDAP_UNAVAILABLE_CRITICAL_EXTENSION \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::UNAVAILABLE_CRITICAL_EXTENSION)
|
||||
|
||||
#define NS_ERROR_LDAP_CONFIDENTIALITY_REQUIRED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::CONFIDENTIALITY_REQUIRED)
|
||||
|
||||
#define NS_ERROR_LDAP_SASL_BIND_IN_PROGRESS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::SASL_BIND_IN_PROGRESS)
|
||||
|
||||
#define NS_ERROR_LDAP_NO_SUCH_ATTRIBUTE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NO_SUCH_ATTRIBUTE)
|
||||
|
||||
#define NS_ERROR_LDAP_UNDEFINED_TYPE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::UNDEFINED_TYPE)
|
||||
|
||||
#define NS_ERROR_LDAP_INAPPROPRIATE_MATCHING \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INAPPROPRIATE_MATCHING)
|
||||
|
||||
#define NS_ERROR_LDAP_CONSTRAINT_VIOLATION \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::CONSTRAINT_VIOLATION)
|
||||
|
||||
#define NS_ERROR_LDAP_TYPE_OR_VALUE_EXISTS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::TYPE_OR_VALUE_EXISTS)
|
||||
|
||||
#define NS_ERROR_LDAP_INVALID_SYNTAX \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INVALID_SYNTAX)
|
||||
|
||||
#define NS_ERROR_LDAP_NO_SUCH_OBJECT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NO_SUCH_OBJECT)
|
||||
|
||||
#define NS_ERROR_LDAP_ALIAS_PROBLEM \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::ALIAS_PROBLEM)
|
||||
|
||||
#define NS_ERROR_LDAP_INVALID_DN_SYNTAX \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INVALID_DN_SYNTAX)
|
||||
|
||||
#define NS_ERROR_LDAP_IS_LEAF \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::IS_LEAF)
|
||||
|
||||
#define NS_ERROR_LDAP_ALIAS_DEREF_PROBLEM \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::ALIAS_DEREF_PROBLEM)
|
||||
|
||||
#define NS_ERROR_LDAP_INAPPROPRIATE_AUTH \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INAPPROPRIATE_AUTH)
|
||||
|
||||
#define NS_ERROR_LDAP_INVALID_CREDENTIALS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INVALID_CREDENTIALS)
|
||||
|
||||
#define NS_ERROR_LDAP_INSUFFICIENT_ACCESS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INSUFFICIENT_ACCESS)
|
||||
|
||||
#define NS_ERROR_LDAP_BUSY \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::BUSY)
|
||||
|
||||
#define NS_ERROR_LDAP_UNAVAILABLE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::UNAVAILABLE)
|
||||
|
||||
#define NS_ERROR_LDAP_UNWILLING_TO_PERFORM \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::UNWILLING_TO_PERFORM)
|
||||
|
||||
#define NS_ERROR_LDAP_LOOP_DETECT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::LOOP_DETECT)
|
||||
|
||||
#define NS_ERROR_LDAP_SORT_CONTROL_MISSING \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::SORT_CONTROL_MISSING)
|
||||
|
||||
#define NS_ERROR_LDAP_INDEX_RANGE_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::INDEX_RANGE_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_NAMING_VIOLATION \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NAMING_VIOLATION)
|
||||
|
||||
#define NS_ERROR_LDAP_OBJECT_CLASS_VIOLATION \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::OBJECT_CLASS_VIOLATION)
|
||||
|
||||
#define NS_ERROR_LDAP_NOT_ALLOWED_ON_NONLEAF \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NOT_ALLOWED_ON_NONLEAF)
|
||||
|
||||
#define NS_ERROR_LDAP_NOT_ALLOWED_ON_RDN \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NOT_ALLOWED_ON_RDN)
|
||||
|
||||
#define NS_ERROR_LDAP_ALREADY_EXISTS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::ALREADY_EXISTS)
|
||||
|
||||
#define NS_ERROR_LDAP_NO_OBJECT_CLASS_MODS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NO_OBJECT_CLASS_MODS)
|
||||
|
||||
#define NS_ERROR_LDAP_RESULTS_TOO_LARGE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::RESULTS_TOO_LARGE)
|
||||
|
||||
#define NS_ERROR_LDAP_AFFECTS_MULTIPLE_DSAS \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::AFFECTS_MULTIPLE_DSAS)
|
||||
|
||||
#define NS_ERROR_LDAP_OTHER \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::OTHER)
|
||||
|
||||
#define NS_ERROR_LDAP_SERVER_DOWN \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::SERVER_DOWN)
|
||||
|
||||
#define NS_ERROR_LDAP_LOCAL_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::LOCAL_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_ENCODING_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::ENCODING_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_DECODING_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::DECODING_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_TIMEOUT \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::TIMEOUT)
|
||||
|
||||
#define NS_ERROR_LDAP_AUTH_UNKNOWN \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::AUTH_UNKNOWN)
|
||||
|
||||
#define NS_ERROR_LDAP_FILTER_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::FILTER_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_USER_CANCELLED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::USER_CANCELLED)
|
||||
|
||||
#define NS_ERROR_LDAP_PARAM_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::PARAM_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_NO_MEMORY \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NO_MEMORY)
|
||||
|
||||
#define NS_ERROR_LDAP_CONNECT_ERROR \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::CONNECT_ERROR)
|
||||
|
||||
#define NS_ERROR_LDAP_NOT_SUPPORTED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NOT_SUPPORTED)
|
||||
|
||||
#define NS_ERROR_LDAP_CONTROL_NOT_FOUND \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::CONTROL_NOT_FOUND)
|
||||
|
||||
#define NS_ERROR_LDAP_NO_RESULTS_RETURNED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::NO_RESULTS_RETURNED)
|
||||
|
||||
#define NS_ERROR_LDAP_MORE_RESULTS_TO_RETURN \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::MORE_RESULTS_TO_RETURN)
|
||||
|
||||
#define NS_ERROR_LDAP_CLIENT_LOOP \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::CLIENT_LOOP)
|
||||
|
||||
#define NS_ERROR_LDAP_REFERRAL_LIMIT_EXCEEDED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LDAP, \
|
||||
nsILDAPErrors::REFERRAL_LIMIT_EXCEEDED)
|
||||
|
||||
%}
|
||||
170
ldap/xpcom/public/nsILDAPMessage.idl
Normal file
170
ldap/xpcom/public/nsILDAPMessage.idl
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILDAPBERValue;
|
||||
interface nsILDAPOperation;
|
||||
|
||||
%{C++
|
||||
#define NS_LDAPMESSAGE_CONTRACTID "@mozilla.org/network/ldap-message;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(973ff50f-2002-4f0c-b57d-2242156139a2)]
|
||||
interface nsILDAPMessage : nsISupports
|
||||
{
|
||||
/**
|
||||
* The Distinguished Name of the entry associated with this message.
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
* @exception NS_ERROR_LDAP_DECODING_ERROR problem during BER-decoding
|
||||
* @exception NS_ERROR_UNEXPECTED bug or memory corruption
|
||||
*/
|
||||
readonly attribute AUTF8String dn;
|
||||
|
||||
/**
|
||||
* Get all the attributes in this message.
|
||||
*
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
* @exception NS_ERROR_UNEXPECTED bug or memory corruption
|
||||
* @exception NS_ERROR_LDAP_DECODING_ERROR problem during BER decoding
|
||||
*
|
||||
* @return array of all attributes in the current message
|
||||
*/
|
||||
void getAttributes(out unsigned long count,
|
||||
[retval, array, size_is(count)] out string aAttributes);
|
||||
|
||||
/**
|
||||
* Get an array of all the attribute values in this message.
|
||||
*
|
||||
* @param attr The attribute whose values are to be returned
|
||||
* @param count Number of values in the outbound array.
|
||||
* @param values Array of values
|
||||
*
|
||||
* @exception NS_ERROR_UNEXPECTED Bug or memory corruption
|
||||
* @exception NS_ERROR_LDAP_DECODING_ERROR Attribute not found or other
|
||||
* decoding error.
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
void getValues(in string attr, out unsigned long count,
|
||||
[retval, array, size_is(count)] out wstring values);
|
||||
|
||||
/**
|
||||
* The operation this message originated from
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to getter
|
||||
*/
|
||||
readonly attribute nsILDAPOperation operation;
|
||||
|
||||
/**
|
||||
* The result code (aka lderrno) for this message.
|
||||
*
|
||||
* IDL definitions for these constants live in nsILDAPErrors.idl.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
*/
|
||||
readonly attribute long errorCode;
|
||||
|
||||
/**
|
||||
* The result type of this message. Possible types listed below, the
|
||||
* values chosen are taken from the draft-ietf-ldapext-ldap-c-api-04.txt
|
||||
* and are the same ones used in the ldap.h include file from the Mozilla
|
||||
* LDAP C SDK.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
* @exception NS_ERROR_UNEXPECTED internal error (possible memory
|
||||
* corruption)
|
||||
*/
|
||||
readonly attribute long type;
|
||||
|
||||
/**
|
||||
* Result of a bind operation
|
||||
*/
|
||||
const long RES_BIND = 0x61;
|
||||
|
||||
/**
|
||||
* An entry found in an search operation.
|
||||
*/
|
||||
const long RES_SEARCH_ENTRY = 0x64;
|
||||
|
||||
/**
|
||||
* An LDAPv3 search reference (a referral to another server)
|
||||
*/
|
||||
const long RES_SEARCH_REFERENCE = 0x73;
|
||||
|
||||
/**
|
||||
* The result of a search operation (i.e. the search is done; no more
|
||||
* entries to follow).
|
||||
*/
|
||||
const long RES_SEARCH_RESULT = 0x65;
|
||||
|
||||
/**
|
||||
* The result of a modify operation.
|
||||
*/
|
||||
const long RES_MODIFY = 0x67;
|
||||
|
||||
/**
|
||||
* The result of an add operation
|
||||
*/
|
||||
const long RES_ADD = 0x69;
|
||||
|
||||
/**
|
||||
* The result of a delete operation
|
||||
*/
|
||||
const long RES_DELETE = 0x6B;
|
||||
|
||||
/**
|
||||
* The result of an modify DN operation
|
||||
*/
|
||||
const long RES_MODDN = 0x6D;
|
||||
|
||||
/**
|
||||
* The result of a compare operation
|
||||
*/
|
||||
const long RES_COMPARE = 0x6F;
|
||||
|
||||
/**
|
||||
* The result of an LDAPv3 extended operation
|
||||
*/
|
||||
const long RES_EXTENDED = 0x78;
|
||||
|
||||
/**
|
||||
* get an LDIF-like string representation of this message
|
||||
*
|
||||
* @return unicode encoded string representation.
|
||||
*/
|
||||
wstring toUnicode();
|
||||
|
||||
/**
|
||||
* Additional error information optionally sent by the server.
|
||||
*/
|
||||
readonly attribute AUTF8String errorMessage;
|
||||
|
||||
/**
|
||||
* In LDAPv3, when the server returns any of the following errors:
|
||||
* NO_SUCH_OBJECT, ALIAS_PROBLEM, INVALID_DN_SYNTAX, ALIAS_DEREF_PROBLEM,
|
||||
* it also returns the closest existing DN to the entry requested.
|
||||
*/
|
||||
readonly attribute AUTF8String matchedDn;
|
||||
|
||||
/**
|
||||
* Get an array of all the attribute values in this message (a wrapper
|
||||
* around the LDAP C SDK's get_values_len()).
|
||||
*
|
||||
* @param attr The attribute whose values are to be returned
|
||||
* @param count Number of values in the outbound array.
|
||||
* @param values Array of nsILDAPBERValue objects
|
||||
*
|
||||
* @exception NS_ERROR_UNEXPECTED Bug or memory corruption
|
||||
* @exception NS_ERROR_LDAP_DECODING_ERROR Attribute not found or other
|
||||
* decoding error.
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
void getBinaryValues(in string attr, out unsigned long count,
|
||||
[retval, array, size_is(count)] out nsILDAPBERValue values);
|
||||
};
|
||||
40
ldap/xpcom/public/nsILDAPMessageListener.idl
Normal file
40
ldap/xpcom/public/nsILDAPMessageListener.idl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsILDAPMessage;
|
||||
|
||||
interface nsILDAPConnection;
|
||||
|
||||
/**
|
||||
* A callback interface to be implemented by any objects that want to
|
||||
* receive results from an nsILDAPOperation (ie nsILDAPMessages) as they
|
||||
* come in.
|
||||
*/
|
||||
[scriptable, uuid(dc721d4b-3ff2-4387-a80c-5e29545f774a)]
|
||||
interface nsILDAPMessageListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Messages received are passed back via this function.
|
||||
*
|
||||
* @arg aMessage The message that was returned, NULL if none was.
|
||||
*
|
||||
* XXX semantics of NULL?
|
||||
*/
|
||||
void onLDAPMessage(in nsILDAPMessage aMessage);
|
||||
|
||||
/**
|
||||
* Notify the listener that the Init has completed, passing
|
||||
* in the results from the connection initialization. The
|
||||
* Reason for this is to allow us to do asynchronous DNS
|
||||
* lookups, preresolving hostnames.
|
||||
*
|
||||
* @arg aConn The LDAP connection in question
|
||||
* @arg aStatus The result from the LDAP connection init
|
||||
*/
|
||||
void onLDAPInit(in nsILDAPConnection aConn, in nsresult aStatus);
|
||||
};
|
||||
58
ldap/xpcom/public/nsILDAPModification.idl
Normal file
58
ldap/xpcom/public/nsILDAPModification.idl
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#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);
|
||||
};
|
||||
275
ldap/xpcom/public/nsILDAPOperation.idl
Normal file
275
ldap/xpcom/public/nsILDAPOperation.idl
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsILDAPConnection.idl"
|
||||
#include "nsIAuthModule.idl"
|
||||
|
||||
interface nsILDAPMessage;
|
||||
interface nsILDAPMessageListener;
|
||||
interface nsILDAPModification;
|
||||
interface nsIMutableArray;
|
||||
interface nsIArray;
|
||||
|
||||
%{C++
|
||||
#define NS_LDAPOPERATION_CONTRACTID "@mozilla.org/network/ldap-operation;1"
|
||||
%}
|
||||
|
||||
// XXXdmose check to make sure ctl-related err codes documented
|
||||
|
||||
typedef uint32_t PRIntervalTime;
|
||||
|
||||
[scriptable, uuid(4dfb1b19-fc8f-4525-92e7-f97b78a9747a)]
|
||||
interface nsILDAPOperation : nsISupports
|
||||
{
|
||||
/**
|
||||
* The connection this operation is on.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE a NULL pointer was passed in
|
||||
*/
|
||||
readonly attribute nsILDAPConnection connection;
|
||||
|
||||
/**
|
||||
* Callback for individual result messages related to this operation (set
|
||||
* by the init() method). This is actually an nsISupports proxy object,
|
||||
* as the callback will happen from another thread.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE a NULL pointer was passed in
|
||||
*/
|
||||
readonly attribute nsILDAPMessageListener messageListener;
|
||||
|
||||
/**
|
||||
* The message-id associated with this operation.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE a NULL pointer was passed in
|
||||
*/
|
||||
readonly attribute long messageID;
|
||||
|
||||
/**
|
||||
* private parameter (anything caller desires)
|
||||
*/
|
||||
attribute nsISupports closure;
|
||||
|
||||
/**
|
||||
* No time and/or size limit specified
|
||||
*/
|
||||
const long NO_LIMIT = 0;
|
||||
|
||||
/**
|
||||
* If specified, these arrays of nsILDAPControls are passed into the LDAP
|
||||
* C SDK for any extended operations (ie method calls on this interface
|
||||
* ending in "Ext").
|
||||
*/
|
||||
attribute nsIMutableArray serverControls;
|
||||
attribute nsIMutableArray clientControls;
|
||||
|
||||
/**
|
||||
* Initializes this operation. Must be called prior to initiating
|
||||
* any actual operations. Note that by default, the aMessageListener
|
||||
* callbacks happen on the LDAP connection thread. If you need them
|
||||
* to happen on the main thread (or any other thread), then you should
|
||||
* created an nsISupports proxy object and pass that in.
|
||||
*
|
||||
* @param aConnection connection this operation should use
|
||||
* @param aMessageListener interface used to call back the results.
|
||||
* @param aClosure private parameter (anything caller desires)
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE a NULL pointer was passed in
|
||||
* @exception NS_ERROR_UNEXPECTED failed to get connection handle
|
||||
*/
|
||||
void init(in nsILDAPConnection aConnection,
|
||||
in nsILDAPMessageListener aMessageListener,
|
||||
in nsISupports aClosure);
|
||||
|
||||
/**
|
||||
* Asynchronously authenticate to the LDAP server.
|
||||
*
|
||||
* @param passwd the password used for binding; NULL for anon-binds
|
||||
*
|
||||
* @exception NS_ERROR_LDAP_ENCODING_ERROR problem encoding bind request
|
||||
* @exception NS_ERROR_LDAP_SERVER_DOWN server down (XXX rebinds?)
|
||||
* @exception NS_ERROR_LDAP_CONNECT_ERROR connection failed or lost
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
* @exception NS_ERROR_UNEXPECTED internal error
|
||||
*/
|
||||
void simpleBind(in AUTF8String passwd);
|
||||
|
||||
/**
|
||||
* Asynchronously perform a SASL bind against the LDAP server
|
||||
*
|
||||
* @param service the host name of the service being connected to
|
||||
* @param mechanism the name of the SASL mechanism in use
|
||||
* @param authModule the nsIAuthModule to be used to perform the operation
|
||||
*
|
||||
*/
|
||||
void saslBind(in ACString service, in ACString mechanism,
|
||||
in nsIAuthModule authModule);
|
||||
|
||||
/**
|
||||
* Continue a SASL bind operation
|
||||
*
|
||||
* @param token the next SASL token to send to the server
|
||||
* @param tokenLen the length of the token to send
|
||||
*
|
||||
*/
|
||||
void saslStep(in string token, in unsigned long tokenLen);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* eventually support the extensions described in the
|
||||
* draft-ietf-ldapext-ldap-c-api-04.txt Internet Draft.
|
||||
*
|
||||
* @param aBaseDn Base DN to search
|
||||
* @param aScope One of SCOPE_{BASE,ONELEVEL,SUBTREE}
|
||||
* @param aFilter Search filter
|
||||
* @param aAttributes Comma separated list of values, holding the
|
||||
* attributes we need
|
||||
* @param aTimeOut How long to wait
|
||||
* @param aSizeLimit Maximum number of entries to return.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
void searchExt(in AUTF8String aBaseDn, in int32_t aScope,
|
||||
in AUTF8String aFilter, in ACString aAttributes,
|
||||
in PRIntervalTime aTimeOut, in int32_t aSizeLimit);
|
||||
|
||||
/**
|
||||
* Cancels an async operation that is in progress.
|
||||
*
|
||||
* XXX controls not supported yet
|
||||
*
|
||||
* @exception NS_ERROR_NOT_IMPLEMENTED server or client controls
|
||||
* were set on this object
|
||||
* @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 out of memory
|
||||
* @exception NS_ERROR_INVALID_ARG invalid argument
|
||||
* @exception NS_ERROR_UNEXPECTED internal error
|
||||
*/
|
||||
void abandonExt();
|
||||
};
|
||||
86
ldap/xpcom/public/nsILDAPServer.idl
Normal file
86
ldap/xpcom/public/nsILDAPServer.idl
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsILDAPConnection.idl"
|
||||
|
||||
interface nsILDAPURL;
|
||||
|
||||
/**
|
||||
* this interface provides a way to store, retrieve and manipulate
|
||||
* information related to a specific LDAP server. This includes the
|
||||
* LDAP URL, as well as certain user specific data (e.g. credentials).
|
||||
*
|
||||
* The implementation of nsILDAPService relies heavily on this
|
||||
* interface, managing all LDAP connections (nsILDAPConnection).
|
||||
* The Service manages LDAP connections (connect and disconnect etc.),
|
||||
* using the information available from these LDAP Server objects.
|
||||
*/
|
||||
|
||||
|
||||
[scriptable, uuid(8aa717a4-1dd2-11b2-99c7-f01e2d449ded)]
|
||||
interface nsILDAPServer : nsISupports {
|
||||
|
||||
/**
|
||||
* unique identifier for this server, used (typically) to identify a
|
||||
* particular server object in a list of servers. This key can be
|
||||
* any "string", but in our case it will most likely be the same
|
||||
* identifier as used in a Mozilla preferences files.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
attribute wstring key;
|
||||
|
||||
/**
|
||||
* the password string used to bind to this server. An empty
|
||||
* string here implies binding as anonymous.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
attribute AUTF8String password;
|
||||
|
||||
/**
|
||||
* the user name to authenticate as. An empty string here would
|
||||
* imply binding as anonymous.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
attribute AUTF8String username;
|
||||
|
||||
/**
|
||||
* the bind DN (Distinguished Name).
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
attribute AUTF8String binddn;
|
||||
|
||||
/** maximum number of hits we want to accept from an LDAP search
|
||||
* operation.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
*/
|
||||
attribute unsigned long sizelimit;
|
||||
|
||||
/**
|
||||
* the URL for this server.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
*/
|
||||
attribute nsILDAPURL url;
|
||||
|
||||
/**
|
||||
* protocol version to be used (see nsILDAPConnection.idl for constants)
|
||||
* Defaults to 3.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer passed to getter
|
||||
* @exception NS_ERROR_INVALID_ARG Invalid version passed to setter
|
||||
*/
|
||||
attribute unsigned long protocolVersion;
|
||||
};
|
||||
197
ldap/xpcom/public/nsILDAPService.idl
Normal file
197
ldap/xpcom/public/nsILDAPService.idl
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
interface nsILDAPServer;
|
||||
interface nsILDAPConnection;
|
||||
interface nsILDAPMessageListener;
|
||||
|
||||
/**
|
||||
* This interface provides an LDAP connection management service.
|
||||
* It's used to cache already established LDAP connections, as well
|
||||
* as reaping unused connections after a certain time period. This
|
||||
* is done completely asynchronously, using callback functions.
|
||||
*/
|
||||
|
||||
|
||||
[scriptable, uuid(69de6fbc-2e8c-4482-bf14-358d68b785d1)]
|
||||
interface nsILDAPService : nsISupports {
|
||||
|
||||
/**
|
||||
* Add a (possibly) new LDAP server entry to the service. A
|
||||
* server entry holds information about the host, port and
|
||||
* other components of the LDAP URL, as well as information
|
||||
* used for binding a connection to the LDAP server.
|
||||
*
|
||||
* An LDAP Server entry (nsILDAPServer) contains the URL,
|
||||
* user credentials, and other information related to the actual
|
||||
* server itself. It is used for connecting, binding, rebinding,
|
||||
* setting timeouts and so forth.
|
||||
*
|
||||
* @param aServer an nsILDAPServer object
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE the server has already been
|
||||
* added to the service
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
void addServer(in nsILDAPServer aServer);
|
||||
|
||||
/**
|
||||
* Mark an LDAP server, in the Service, as a candidate for
|
||||
* deletion. If there are still leases ("users") of this server,
|
||||
* the operation fails.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE either the server doesn't
|
||||
* exist, or there are still
|
||||
* leases oustanding
|
||||
*/
|
||||
void deleteServer(in wstring aKey);
|
||||
|
||||
/**
|
||||
* Get the nsILDAPServer object for the specified server entry
|
||||
* in the service.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there is no server registered
|
||||
* in the service with this key
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer
|
||||
*/
|
||||
nsILDAPServer getServer(in wstring aKey);
|
||||
|
||||
/**
|
||||
* Request a connection from the service, asynchronously. If there is
|
||||
* one "cached" already, we will actually call the callback function
|
||||
* before returning from this function. This might be considered a bug,
|
||||
* but for now be aware of this (see Bugzilla bug #75989).
|
||||
*
|
||||
* Calling this method does not increment the leases on this connection,
|
||||
* you'll have to use the getConnection() method to actually get the
|
||||
* connection itself (presumably from the callback/listener object).
|
||||
* The listener needs to implement nsILDAPMessageListener, providing
|
||||
* the OnLDAPMessage() method.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
* @param aMessageListener the listener object, which we will call
|
||||
* when the LDAP bind message is available
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there is no server registered
|
||||
* in the service with this key,
|
||||
* or we were unable to get a
|
||||
* connection properly to the server
|
||||
* @exception NS_ERROR_NOT_AVAILABLE couldn't create connection thread
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
* @exception NS_ERROR_UNEXPECTED unknown or unexpected error...
|
||||
*/
|
||||
void requestConnection(in wstring aKey,
|
||||
in nsILDAPMessageListener aListener);
|
||||
|
||||
/**
|
||||
* This is the nsLDAPConnection object related to this server.
|
||||
* This does increase the lease counter on the object, so you have
|
||||
* to call the releaseConnection() method to return it. It is
|
||||
* important that you do this in matching pairs, and that you do
|
||||
* not keep any dangling references to an object around after you
|
||||
* have called the releaseConnection() method.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there is no server registered
|
||||
* in the service with this key
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer
|
||||
*/
|
||||
nsILDAPConnection getConnection(in wstring aKey);
|
||||
|
||||
/**
|
||||
* Release the lease on a (cached) LDAP connection, making it a
|
||||
* potential candidate for disconnection. Note that this will not
|
||||
* delete the actual LDAP server entry in the service, it's still
|
||||
* registered and can be used in future calls to requestConnection().
|
||||
*
|
||||
* This API might be deprecated in the future, once we figure out how
|
||||
* to use weak references to support our special needs for reference
|
||||
* counting. For the time being, it is vital that you call this function
|
||||
* when you're done with a Connection, and that you do not keep any
|
||||
* copies of the Connection object lingering around.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there is no server registered
|
||||
* in the service with this key
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
void releaseConnection(in wstring aKey);
|
||||
|
||||
/**
|
||||
* If we detect that a connection is broken (server disconnected us,
|
||||
* or any other problem with the link), we need to try to reestablish
|
||||
* the connection. This is very similar to requestConnection(),
|
||||
* except you use this when detecting an error with a connection
|
||||
* that is being cached.
|
||||
*
|
||||
* @param aKey unique key identifying the server entry
|
||||
* @param aMessageListener the listener object, which we will call
|
||||
* when the LDAP bind message is available
|
||||
*
|
||||
* @exception NS_ERROR_FAILURE there is no server registered
|
||||
* in the service with this key,
|
||||
* or we were unable to get a
|
||||
* connection properly to the server
|
||||
* @exception NS_ERROR_NOT_AVAILABLE couldn't create connection thread
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
* @exception NS_ERROR_UNEXPECTED unknown or unexpected error...
|
||||
*/
|
||||
void reconnectConnection(in wstring aKey,
|
||||
in nsILDAPMessageListener aListener);
|
||||
|
||||
/**
|
||||
* Generates and returns an LDAP search filter by substituting
|
||||
* aValue, aAttr, aPrefix, and aSuffix into aPattern.
|
||||
*
|
||||
* The only good documentation I'm aware of for this function is
|
||||
* at <http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/filter.htm>
|
||||
* and
|
||||
* <http://docs.iplanet.com/docs/manuals/dirsdk/csdk41/html/function.htm#17835>
|
||||
* Unfortunately, this does not currently seem to be available
|
||||
* under any open source license, so I can't include that
|
||||
* documentation here in the doxygen comments.
|
||||
*
|
||||
* @param aMaxSize maximum size (in char) of string to be
|
||||
* created and returned (including final \0)
|
||||
* @param aPattern pattern to be used for the filter
|
||||
* @param aPrefix prefix to prepend to the filter
|
||||
* @param aSuffix suffix to be appended to the filer
|
||||
* @param aAttr replacement for %a in the pattern
|
||||
* @param aValue replacement for %v in the pattern
|
||||
*
|
||||
* @exception NS_ERROR_INVALID_ARG invalid parameter passed in
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY allocation failed
|
||||
* @exception NS_ERROR_NOT_AVAILABLE filter longer than maxsiz chars
|
||||
* @exception NS_ERROR_UNEXPECTED ldap_create_filter returned
|
||||
* unexpected error code
|
||||
*/
|
||||
AUTF8String createFilter(in unsigned long aMaxSize, in AUTF8String aPattern,
|
||||
in AUTF8String aPrefix, in AUTF8String aSuffix,
|
||||
in AUTF8String aAttr, in AUTF8String aValue);
|
||||
|
||||
/**
|
||||
* Parses a distinguished name (DN) and returns the relative DN,
|
||||
* base DN and the list of attributes that make up the relative DN.
|
||||
*
|
||||
* @param dn DN to parse
|
||||
* @param rdn The relative DN for the given DN
|
||||
* @param baseDn The base DN for the given DN
|
||||
* @param rdnCount Number of values in the outbound attributes array.
|
||||
* @param rdnAttrs Array of attribute names
|
||||
*
|
||||
*/
|
||||
void parseDn(in string dn, out AUTF8String rdn, out AUTF8String baseDn,
|
||||
out unsigned long rdnCount,
|
||||
[retval, array, size_is(rdnCount)] out string rdnAttrs);
|
||||
};
|
||||
27
ldap/xpcom/public/nsILDAPSyncQuery.idl
Normal file
27
ldap/xpcom/public/nsILDAPSyncQuery.idl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#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);
|
||||
|
||||
};
|
||||
132
ldap/xpcom/public/nsILDAPURL.idl
Normal file
132
ldap/xpcom/public/nsILDAPURL.idl
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIURI.idl"
|
||||
|
||||
%{C++
|
||||
#define NS_LDAPURL_CONTRACTID "@mozilla.org/network/ldap-url;1"
|
||||
%}
|
||||
|
||||
/**
|
||||
* Strings in methods inherited from nsIURI, which are using XPIDL
|
||||
* |string| types, are expected to be UTF8 encoded. All such strings
|
||||
* in this interface, except attribute types (e.g. "cn"), should in fact
|
||||
* be UTF8. It's important to remember that attributes can not be UTF8,
|
||||
* they can only be of a limited subset of ASCII (see RFC 2251).
|
||||
*/
|
||||
|
||||
[scriptable, uuid(8e3a6d33-2e68-40ba-8f94-6ac03f69066e)]
|
||||
interface nsILDAPURL : nsIURI {
|
||||
/**
|
||||
* Initialize an LDAP URL
|
||||
*
|
||||
* @param aUrlType - one of the URLTYPE_ flags @seealso nsIStandardURL
|
||||
* @param aDefaultPort - if the port parsed from the URL string matches
|
||||
* this port, then the port will be removed from the
|
||||
* canonical form of the URL.
|
||||
* @param aSpec - URL string.
|
||||
* @param aOriginCharset - the charset from which this URI string
|
||||
* originated. this corresponds to the charset
|
||||
* that should be used when communicating this
|
||||
* URI to an origin server, for example. if
|
||||
* null, then provide aBaseURI implements this
|
||||
* interface, the origin charset of aBaseURI will
|
||||
* be assumed, otherwise defaulting to UTF-8 (i.e.,
|
||||
* no charset transformation from aSpec).
|
||||
* @param aBaseURI - if null, aSpec must specify an absolute URI.
|
||||
* otherwise, aSpec will be resolved relative
|
||||
* to aBaseURI.
|
||||
*/
|
||||
void init(in unsigned long aUrlType,
|
||||
in long aDefaultPort,
|
||||
in AUTF8String aSpec,
|
||||
in string aOriginCharset,
|
||||
in nsIURI aBaseURI);
|
||||
|
||||
/**
|
||||
* The distinguished name of the URL (ie the base DN for the search).
|
||||
* This string is expected to be a valid UTF8 string.
|
||||
*
|
||||
* for the getter:
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY Ran out of memory
|
||||
*/
|
||||
attribute AUTF8String dn;
|
||||
|
||||
/**
|
||||
* The attributes to get for this URL, in comma-separated format. If the
|
||||
* list is empty, all attributes are requested.
|
||||
*/
|
||||
attribute ACString attributes;
|
||||
|
||||
/**
|
||||
* Add one attribute to the array of attributes to request. If the
|
||||
* attribute is already in our array, this becomes a noop.
|
||||
*
|
||||
* @param aAttribute An LDAP attribute (e.g. "cn")
|
||||
*/
|
||||
void addAttribute(in ACString aAttribute);
|
||||
|
||||
/**
|
||||
* Remove one attribute from the array of attributes to request. If
|
||||
* the attribute didn't exist in the array, this becomes a noop.
|
||||
*
|
||||
* @param aAttribute An LDAP attribute (e.g. "cn")
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY Ran out of memory
|
||||
*/
|
||||
void removeAttribute(in ACString aAttribute);
|
||||
|
||||
/**
|
||||
* Test if an attribute is in our list of attributes already
|
||||
*
|
||||
* @param aAttribute An LDAP attribute (e.g. "cn")
|
||||
* @return boolean Truth value
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
*/
|
||||
boolean hasAttribute(in ACString aAttribute);
|
||||
|
||||
/**
|
||||
* The scope of the search. defaults to SCOPE_BASE.
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_MALFORMED_URI Illegal base to SET method
|
||||
*/
|
||||
attribute long scope;
|
||||
|
||||
/**
|
||||
* Search just the base object
|
||||
*/
|
||||
const long SCOPE_BASE = 0;
|
||||
|
||||
/**
|
||||
* Search only the children of the base object
|
||||
*/
|
||||
const long SCOPE_ONELEVEL = 1;
|
||||
|
||||
/**
|
||||
* Search the entire subtree under and including the base object
|
||||
*/
|
||||
const long SCOPE_SUBTREE = 2;
|
||||
|
||||
/**
|
||||
* The search filter. "(objectClass=*)" is the default.
|
||||
*/
|
||||
attribute AUTF8String filter;
|
||||
|
||||
/**
|
||||
* Any options defined for this URL (check options using a bitwise and)
|
||||
*
|
||||
* @exception NS_ERROR_NULL_POINTER NULL pointer to GET method
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY Ran out of memory
|
||||
*/
|
||||
attribute unsigned long options;
|
||||
|
||||
/**
|
||||
* If this is set/true, this is an ldaps: URL, not an ldap: URL
|
||||
*/
|
||||
const unsigned long OPT_SECURE = 0x01;
|
||||
};
|
||||
5
ldap/xpcom/src/ldapComponents.manifest
Normal file
5
ldap/xpcom/src/ldapComponents.manifest
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
component {b3de9249-b0e5-4c12-8d91-c9a434fd80f5} nsLDAPProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=ldap {b3de9249-b0e5-4c12-8d91-c9a434fd80f5}
|
||||
|
||||
component {c85a5ef2-9c56-445f-b029-76889f2dd29b} nsLDAPProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=ldaps {c85a5ef2-9c56-445f-b029-76889f2dd29b}
|
||||
53
ldap/xpcom/src/moz.build
Normal file
53
ldap/xpcom/src/moz.build
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
SOURCES += [
|
||||
'nsLDAPBERElement.cpp',
|
||||
'nsLDAPBERValue.cpp',
|
||||
'nsLDAPConnection.cpp',
|
||||
'nsLDAPControl.cpp',
|
||||
'nsLDAPMessage.cpp',
|
||||
'nsLDAPModification.cpp',
|
||||
'nsLDAPOperation.cpp',
|
||||
'nsLDAPProtocolModule.cpp',
|
||||
'nsLDAPSecurityGlue.cpp',
|
||||
'nsLDAPServer.cpp',
|
||||
'nsLDAPService.cpp',
|
||||
'nsLDAPURL.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_PREF_EXTENSIONS']:
|
||||
SOURCES += ['nsLDAPSyncQuery.cpp']
|
||||
DEFINES['MOZ_PREF_EXTENSIONS'] = True
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'ldapComponents.manifest',
|
||||
'nsLDAPProtocolHandler.js',
|
||||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'ldapsdks',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INCOMPLETE_EXTERNAL_LINKAGE']:
|
||||
XPCOMBinaryComponent('mozldap')
|
||||
USE_LIBS += [
|
||||
'nspr',
|
||||
'xpcomglue_s',
|
||||
'xul',
|
||||
]
|
||||
# js needs to come after xul for now, because it is an archive and its content
|
||||
# is discarded when it comes first.
|
||||
USE_LIBS += [
|
||||
'js',
|
||||
]
|
||||
else:
|
||||
Library('mozldap')
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/ldap/c-sdk/include',
|
||||
]
|
||||
|
||||
117
ldap/xpcom/src/nsLDAPBERElement.cpp
Normal file
117
ldap/xpcom/src/nsLDAPBERElement.cpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPBERElement.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsLDAPBERValue.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPBERElement, nsILDAPBERElement)
|
||||
|
||||
nsLDAPBERElement::nsLDAPBERElement()
|
||||
: mElement(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPBERElement::~nsLDAPBERElement()
|
||||
{
|
||||
if (mElement) {
|
||||
// anything inside here is not something that we own separately from
|
||||
// this object, so free it
|
||||
ber_free(mElement, 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPBERElement::Init(nsILDAPBERValue *aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
mElement = ber_alloc_t(LBER_USE_DER);
|
||||
return mElement ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* void putString (in AUTF8String aString, in unsigned long aTag); */
|
||||
NS_IMETHODIMP
|
||||
nsLDAPBERElement::PutString(const nsACString & aString, uint32_t aTag,
|
||||
uint32_t *aBytesWritten)
|
||||
{
|
||||
// XXX if the string translation feature of the C SDK is ever used,
|
||||
// this const_cast will break
|
||||
int i = ber_put_ostring(mElement,
|
||||
const_cast<char *>(PromiseFlatCString(aString).get()),
|
||||
aString.Length(), aTag);
|
||||
|
||||
if (i < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aBytesWritten = i;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void startSet (); */
|
||||
NS_IMETHODIMP nsLDAPBERElement::StartSet(uint32_t aTag)
|
||||
{
|
||||
int i = ber_start_set(mElement, aTag);
|
||||
|
||||
if (i < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void putSet (); */
|
||||
NS_IMETHODIMP nsLDAPBERElement::PutSet(uint32_t *aBytesWritten)
|
||||
{
|
||||
int i = ber_put_set(mElement);
|
||||
|
||||
if (i < 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aBytesWritten = i;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsILDAPBERValue flatten (); */
|
||||
NS_IMETHODIMP nsLDAPBERElement::GetAsValue(nsILDAPBERValue **_retval)
|
||||
{
|
||||
// create the value object
|
||||
nsCOMPtr<nsILDAPBERValue> berValue = new nsLDAPBERValue();
|
||||
|
||||
if (!berValue) {
|
||||
NS_ERROR("nsLDAPBERElement::GetAsValue(): out of memory"
|
||||
" creating nsLDAPBERValue object");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
struct berval *bv;
|
||||
if ( ber_flatten(mElement, &bv) < 0 ) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = berValue->Set(bv->bv_len,
|
||||
reinterpret_cast<uint8_t *>(bv->bv_val));
|
||||
|
||||
// whether or not we've succeeded, we're done with the ldap c sdk struct
|
||||
ber_bvfree(bv);
|
||||
|
||||
// as of this writing, this error can only be NS_ERROR_OUT_OF_MEMORY
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// return the raw interface pointer
|
||||
NS_ADDREF(*_retval = berValue.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
30
ldap/xpcom/src/nsLDAPBERElement.h
Normal file
30
ldap/xpcom/src/nsLDAPBERElement.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "lber.h"
|
||||
#include "nsILDAPBERElement.h"
|
||||
|
||||
// 070af769-b7f5-40e7-81be-196155ead84c
|
||||
#define NS_LDAPBERELEMENT_CID \
|
||||
{ 0x070af769, 0xb7f5, 0x40e7, \
|
||||
{ 0x81, 0xbe, 0x19, 0x61, 0x55, 0xea, 0xd8, 0x4c }}
|
||||
|
||||
class nsLDAPBERElement final : public nsILDAPBERElement
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSILDAPBERELEMENT
|
||||
|
||||
nsLDAPBERElement();
|
||||
|
||||
private:
|
||||
~nsLDAPBERElement();
|
||||
|
||||
BerElement *mElement;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
106
ldap/xpcom/src/nsLDAPBERValue.cpp
Normal file
106
ldap/xpcom/src/nsLDAPBERValue.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPBERValue.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPBERValue, nsILDAPBERValue)
|
||||
|
||||
nsLDAPBERValue::nsLDAPBERValue() : mValue(0), mSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPBERValue::~nsLDAPBERValue()
|
||||
{
|
||||
if (mValue) {
|
||||
free(mValue);
|
||||
}
|
||||
}
|
||||
|
||||
// void get (out unsigned long aCount,
|
||||
// [array, size_is (aCount), retval] out octet aRetVal); */
|
||||
NS_IMETHODIMP
|
||||
nsLDAPBERValue::Get(uint32_t *aCount, uint8_t **aRetVal)
|
||||
{
|
||||
// if mSize = 0, return a count of a 0 and a null pointer
|
||||
|
||||
if (mSize) {
|
||||
// get a buffer to hold a copy of the data
|
||||
//
|
||||
uint8_t *array = static_cast<uint8_t *>(moz_xmalloc(mSize));
|
||||
|
||||
if (!array) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// copy and return
|
||||
//
|
||||
memcpy(array, mValue, mSize);
|
||||
*aRetVal = array;
|
||||
} else {
|
||||
*aRetVal = 0;
|
||||
}
|
||||
|
||||
*aCount = mSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void set(in unsigned long aCount,
|
||||
// [array, size_is(aCount)] in octet aValue);
|
||||
NS_IMETHODIMP
|
||||
nsLDAPBERValue::Set(uint32_t aCount, uint8_t *aValue)
|
||||
{
|
||||
// get rid of any old value being held here
|
||||
//
|
||||
if (mValue) {
|
||||
free(mValue);
|
||||
}
|
||||
|
||||
// if this is a non-zero value, allocate a buffer and copy
|
||||
//
|
||||
if (aCount) {
|
||||
// get a buffer to hold a copy of this data
|
||||
//
|
||||
mValue = static_cast<uint8_t *>(moz_xmalloc(aCount));
|
||||
if (!mValue) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// copy the data and return
|
||||
//
|
||||
memcpy(mValue, aValue, aCount);
|
||||
} else {
|
||||
// otherwise just set it to null
|
||||
//
|
||||
mValue = 0;
|
||||
}
|
||||
|
||||
mSize = aCount;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void setFromUTF8(in AUTF8String aValue);
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPBERValue::SetFromUTF8(const nsACString & aValue)
|
||||
{
|
||||
// get rid of any old value being held here
|
||||
//
|
||||
if (mValue) {
|
||||
free(mValue);
|
||||
}
|
||||
|
||||
// copy the data and return
|
||||
//
|
||||
mSize = aValue.Length();
|
||||
if (mSize) {
|
||||
mValue = reinterpret_cast<uint8_t *>(ToNewCString(aValue));
|
||||
} else {
|
||||
mValue = 0;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
40
ldap/xpcom/src/nsLDAPBERValue.h
Normal file
40
ldap/xpcom/src/nsLDAPBERValue.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsLDAPBERValue_h_
|
||||
#define _nsLDAPBERValue_h_
|
||||
|
||||
#include "ldap.h"
|
||||
#include "nsILDAPBERValue.h"
|
||||
|
||||
// 7c9fa10e-1dd2-11b2-a097-ac379e6803b2
|
||||
//
|
||||
#define NS_LDAPBERVALUE_CID \
|
||||
{ 0x7c9fa10e, 0x1dd2, 0x11b2, \
|
||||
{0xa0, 0x97, 0xac, 0x37, 0x9e, 0x68, 0x03, 0xb2 }}
|
||||
|
||||
class nsLDAPBERValue : public nsILDAPBERValue
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPBERVALUE
|
||||
|
||||
nsLDAPBERValue();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPBERValue();
|
||||
|
||||
/**
|
||||
* nsLDAPControl needs to be able to grovel through this without an
|
||||
* an extra copy
|
||||
*/
|
||||
friend class nsLDAPControl;
|
||||
|
||||
uint8_t *mValue; // pointer to an array
|
||||
uint32_t mSize; // size of the value, in bytes
|
||||
};
|
||||
|
||||
#endif // _nsLDAPBERValue_h_
|
||||
737
ldap/xpcom/src/nsLDAPConnection.cpp
Normal file
737
ldap/xpcom/src/nsLDAPConnection.cpp
Normal file
|
|
@ -0,0 +1,737 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIDNSRecord.h"
|
||||
#include "nsLDAPConnection.h"
|
||||
#include "nsLDAPMessage.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsINetAddr.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsError.h"
|
||||
#include "nsLDAPOperation.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsLDAPUtils.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
const char kDNSServiceContractId[] = "@mozilla.org/network/dns-service;1";
|
||||
|
||||
// constructor
|
||||
//
|
||||
nsLDAPConnection::nsLDAPConnection()
|
||||
: mConnectionHandle(nullptr),
|
||||
mPendingOperationsMutex("nsLDAPConnection.mPendingOperationsMutex"),
|
||||
mPendingOperations(10),
|
||||
mSSL(false),
|
||||
mVersion(nsILDAPConnection::VERSION3),
|
||||
mDNSRequest(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
//
|
||||
nsLDAPConnection::~nsLDAPConnection()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
if (obsServ)
|
||||
obsServ->RemoveObserver(this, "profile-change-net-teardown");
|
||||
Close();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsLDAPConnection)
|
||||
NS_IMPL_RELEASE(nsLDAPConnection)
|
||||
NS_IMPL_CLASSINFO(nsLDAPConnection, NULL, nsIClassInfo::THREADSAFE,
|
||||
NS_LDAPCONNECTION_CID)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsLDAPConnection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsILDAPConnection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDNSListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILDAPConnection)
|
||||
NS_IMPL_QUERY_CLASSINFO(nsLDAPConnection)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
NS_IMPL_CI_INTERFACE_GETTER(nsLDAPConnection, nsILDAPConnection,
|
||||
nsISupportsWeakReference, nsIDNSListener,
|
||||
nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::Init(nsILDAPURL *aUrl, const nsACString &aBindName,
|
||||
nsILDAPMessageListener *aMessageListener,
|
||||
nsISupports *aClosure, uint32_t aVersion)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUrl);
|
||||
NS_ENSURE_ARG_POINTER(aMessageListener);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We have to abort all LDAP pending operation before shutdown.
|
||||
obsServ->AddObserver(this, "profile-change-net-teardown", true);
|
||||
|
||||
// Save various items that we'll use later
|
||||
mBindName.Assign(aBindName);
|
||||
mClosure = aClosure;
|
||||
mInitListener = aMessageListener;
|
||||
|
||||
// Make sure we haven't called Init earlier, i.e. there's a DNS
|
||||
// request pending.
|
||||
NS_ASSERTION(!mDNSRequest, "nsLDAPConnection::Init() "
|
||||
"Connection was already initialized\n");
|
||||
|
||||
// Check and save the version number
|
||||
if (aVersion != nsILDAPConnection::VERSION2 &&
|
||||
aVersion != nsILDAPConnection::VERSION3) {
|
||||
NS_ERROR("nsLDAPConnection::Init(): illegal version");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
mVersion = aVersion;
|
||||
|
||||
// Get the port number, SSL flag for use later, once the DNS server(s)
|
||||
// has resolved the host part.
|
||||
rv = aUrl->GetPort(&mPort);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t options;
|
||||
rv = aUrl->GetOptions(&options);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mSSL = options & nsILDAPURL::OPT_SECURE;
|
||||
|
||||
nsCOMPtr<nsIThread> curThread = do_GetCurrentThread();
|
||||
if (!curThread) {
|
||||
NS_ERROR("nsLDAPConnection::Init(): couldn't get current thread");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Do the pre-resolve of the hostname, using the DNS service. This
|
||||
// will also initialize the LDAP connection properly, once we have
|
||||
// the IPs resolved for the hostname. This includes creating the
|
||||
// new thread for this connection.
|
||||
//
|
||||
// XXX - What return codes can we expect from the DNS service?
|
||||
//
|
||||
nsCOMPtr<nsIDNSService>
|
||||
pDNSService(do_GetService(kDNSServiceContractId, &rv));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPConnection::Init(): couldn't create the DNS Service object");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = aUrl->GetAsciiHost(mDNSHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if the caller has passed in a space-delimited set of hosts, as the
|
||||
// ldap c-sdk allows, strip off the trailing hosts for now.
|
||||
// Soon, we'd like to make multiple hosts work, but now make
|
||||
// at least the first one work.
|
||||
LdapCompressWhitespace(mDNSHost);
|
||||
|
||||
int32_t spacePos = mDNSHost.FindChar(' ');
|
||||
// trim off trailing host(s)
|
||||
if (spacePos != kNotFound)
|
||||
mDNSHost.SetLength(spacePos);
|
||||
|
||||
rv = pDNSService->AsyncResolve(mDNSHost, 0, this, curThread,
|
||||
getter_AddRefs(mDNSRequest));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
switch (rv) {
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
case NS_ERROR_UNKNOWN_HOST:
|
||||
case NS_ERROR_FAILURE:
|
||||
case NS_ERROR_OFFLINE:
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
mDNSHost.Truncate();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// this might get exposed to clients, so we've broken it
|
||||
// out of the destructor.
|
||||
void
|
||||
nsLDAPConnection::Close()
|
||||
{
|
||||
int rc;
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug, ("unbinding\n"));
|
||||
|
||||
if (mConnectionHandle) {
|
||||
// note that the ldap_unbind() call in the 5.0 version of the LDAP C SDK
|
||||
// appears to be exactly identical to ldap_unbind_s(), so it may in fact
|
||||
// still be synchronous
|
||||
//
|
||||
rc = ldap_unbind(mConnectionHandle);
|
||||
#ifdef PR_LOGGING
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Warning,
|
||||
("nsLDAPConnection::Close(): %s\n",
|
||||
ldap_err2string(rc)));
|
||||
}
|
||||
#endif
|
||||
mConnectionHandle = nullptr;
|
||||
}
|
||||
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug, ("unbound\n"));
|
||||
|
||||
NS_ASSERTION(!mThread || NS_SUCCEEDED(mThread->Shutdown()),
|
||||
"Failed to shutdown thread cleanly");
|
||||
|
||||
// Cancel the DNS lookup if needed, and also drop the reference to the
|
||||
// Init listener (if still there).
|
||||
//
|
||||
if (mDNSRequest) {
|
||||
mDNSRequest->Cancel(NS_ERROR_ABORT);
|
||||
mDNSRequest = nullptr;
|
||||
}
|
||||
mInitListener = nullptr;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "profile-change-net-teardown")) {
|
||||
// Abort all ldap requests.
|
||||
/* We cannot use enumerate function to abort operations because
|
||||
* nsILDAPOperation::AbandonExt() is modifying list of operations
|
||||
* and this leads to starvation.
|
||||
* We have to do a copy of pending operations.
|
||||
*/
|
||||
nsTArray<nsILDAPOperation*> pending_operations;
|
||||
{
|
||||
MutexAutoLock lock(mPendingOperationsMutex);
|
||||
for (auto iter = mPendingOperations.Iter(); !iter.Done(); iter.Next()) {
|
||||
pending_operations.AppendElement(iter.UserData());
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < pending_operations.Length(); i++) {
|
||||
pending_operations[i]->AbandonExt();
|
||||
}
|
||||
Close();
|
||||
} else {
|
||||
NS_NOTREACHED("unexpected topic");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::GetClosure(nsISupports **_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
NS_IF_ADDREF(*_retval = mClosure);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::SetClosure(nsISupports *aClosure)
|
||||
{
|
||||
mClosure = aClosure;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// who we're binding as
|
||||
//
|
||||
// readonly attribute AUTF8String bindName
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::GetBindName(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mBindName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// wrapper for ldap_get_lderrno
|
||||
// XXX should copy before returning
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::GetLdErrno(nsACString& matched, nsACString& errString,
|
||||
int32_t *_retval)
|
||||
{
|
||||
char *match, *err;
|
||||
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
*_retval = ldap_get_lderrno(mConnectionHandle, &match, &err);
|
||||
matched.Assign(match);
|
||||
errString.Assign(err);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// return the error string corresponding to GetLdErrno.
|
||||
//
|
||||
// XXX - deal with optional params
|
||||
// XXX - how does ldap_perror know to look at the global errno?
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::GetErrorString(char16_t **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
// get the error string
|
||||
//
|
||||
char *rv = ldap_err2string(ldap_get_lderrno(mConnectionHandle, 0, 0));
|
||||
if (!rv) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// make a copy using the XPCOM shared allocator
|
||||
//
|
||||
*_retval = ToNewUnicode(NS_ConvertUTF8toUTF16(rv));
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an nsILDAPOperation to the list of operations pending on
|
||||
* this connection. This is also mainly intended for use by the
|
||||
* nsLDAPOperation code.
|
||||
*/
|
||||
nsresult
|
||||
nsLDAPConnection::AddPendingOperation(uint32_t aOperationID, nsILDAPOperation *aOperation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOperation);
|
||||
|
||||
nsIRunnable* runnable = new nsLDAPConnectionRunnable(aOperationID, aOperation,
|
||||
this);
|
||||
{
|
||||
MutexAutoLock lock(mPendingOperationsMutex);
|
||||
mPendingOperations.Put((uint32_t)aOperationID, aOperation);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("pending operation added; total pending operations now = %d\n",
|
||||
mPendingOperations.Count()));
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (!mThread)
|
||||
{
|
||||
rv = NS_NewThread(getter_AddRefs(mThread), runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = mThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an nsILDAPOperation from the list of operations pending on this
|
||||
* connection. Mainly intended for use by the nsLDAPOperation code.
|
||||
*
|
||||
* @param aOperation operation to add
|
||||
* @exception NS_ERROR_INVALID_POINTER aOperation was NULL
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY out of memory
|
||||
* @exception NS_ERROR_FAILURE could not delete the operation
|
||||
*
|
||||
* void removePendingOperation(in nsILDAPOperation aOperation);
|
||||
*/
|
||||
nsresult
|
||||
nsLDAPConnection::RemovePendingOperation(uint32_t aOperationID)
|
||||
{
|
||||
NS_ENSURE_TRUE(aOperationID > 0, NS_ERROR_UNEXPECTED);
|
||||
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPConnection::RemovePendingOperation(): operation removed\n"));
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mPendingOperationsMutex);
|
||||
mPendingOperations.Remove(aOperationID);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPConnection::RemovePendingOperation(): operation "
|
||||
"removed; total pending operations now = %d\n",
|
||||
mPendingOperations.Count()));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsOnLDAPMessageRunnable : public Runnable
|
||||
{
|
||||
public:
|
||||
nsOnLDAPMessageRunnable(nsLDAPMessage *aMsg, bool aClear)
|
||||
: m_msg(aMsg)
|
||||
, m_clear(aClear)
|
||||
{}
|
||||
NS_DECL_NSIRUNNABLE
|
||||
private:
|
||||
RefPtr<nsLDAPMessage> m_msg;
|
||||
bool m_clear;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP nsOnLDAPMessageRunnable::Run()
|
||||
{
|
||||
// get the message listener object.
|
||||
nsLDAPOperation *nsoperation = static_cast<nsLDAPOperation *>(m_msg->mOperation.get());
|
||||
nsCOMPtr<nsILDAPMessageListener> listener;
|
||||
nsresult rv = nsoperation->GetMessageListener(getter_AddRefs(listener));
|
||||
|
||||
if (m_clear)
|
||||
{
|
||||
// try to break cycles
|
||||
nsoperation->Clear();
|
||||
}
|
||||
|
||||
if (!listener)
|
||||
{
|
||||
NS_ERROR("nsLDAPConnection::InvokeMessageCallback(): probable "
|
||||
"memory corruption: GetMessageListener() returned nullptr");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return listener->OnLDAPMessage(m_msg);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLDAPConnection::InvokeMessageCallback(LDAPMessage *aMsgHandle,
|
||||
nsILDAPMessage *aMsg,
|
||||
int32_t aOperation,
|
||||
bool aRemoveOpFromConnQ)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
// We only want this being logged for debug builds so as not to affect performance too much.
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug, ("InvokeMessageCallback entered\n"));
|
||||
#endif
|
||||
|
||||
// Get the operation.
|
||||
nsCOMPtr<nsILDAPOperation> operation;
|
||||
{
|
||||
MutexAutoLock lock(mPendingOperationsMutex);
|
||||
mPendingOperations.Get((uint32_t)aOperation, getter_AddRefs(operation));
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(operation, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsLDAPMessage *msg = static_cast<nsLDAPMessage *>(aMsg);
|
||||
msg->mOperation = operation;
|
||||
|
||||
// proxy the listener callback to the ui thread.
|
||||
RefPtr<nsOnLDAPMessageRunnable> runnable =
|
||||
new nsOnLDAPMessageRunnable(msg, aRemoveOpFromConnQ);
|
||||
// invoke the callback
|
||||
NS_DispatchToMainThread(runnable);
|
||||
|
||||
// if requested (ie the operation is done), remove the operation
|
||||
// from the connection queue.
|
||||
if (aRemoveOpFromConnQ)
|
||||
{
|
||||
MutexAutoLock lock(mPendingOperationsMutex);
|
||||
mPendingOperations.Remove(aOperation);
|
||||
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("pending operation removed; total pending operations now ="
|
||||
" %d\n", mPendingOperations.Count()));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::OnLookupComplete(nsICancelable *aRequest,
|
||||
nsIDNSRecord *aRecord,
|
||||
nsresult aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (aRecord) {
|
||||
// Build mResolvedIP list
|
||||
//
|
||||
mResolvedIP.Truncate();
|
||||
|
||||
int32_t index = 0;
|
||||
nsCString addrbuf;
|
||||
nsCOMPtr<nsINetAddr> addr;
|
||||
|
||||
while (NS_SUCCEEDED(aRecord->GetScriptableNextAddr(0, getter_AddRefs(addr)))) {
|
||||
// We can only use v4 addresses
|
||||
//
|
||||
uint16_t family = 0;
|
||||
bool v4mapped = false;
|
||||
addr->GetFamily(&family);
|
||||
addr->GetIsV4Mapped(&v4mapped);
|
||||
if (family == nsINetAddr::FAMILY_INET || v4mapped) {
|
||||
// If there are more IPs in the list, we separate them with
|
||||
// a space, as supported/used by the LDAP C-SDK.
|
||||
//
|
||||
if (index++)
|
||||
mResolvedIP.Append(' ');
|
||||
|
||||
// Convert the IPv4 address to a string, and append it to our
|
||||
// list of IPs. Strip leading '::FFFF:' (the IPv4-mapped-IPv6
|
||||
// indicator) if present.
|
||||
//
|
||||
addr->GetAddress(addrbuf);
|
||||
if (addrbuf[0] == ':' && addrbuf.Length() > 7)
|
||||
mResolvedIP.Append(Substring(addrbuf, 7));
|
||||
else
|
||||
mResolvedIP.Append(addrbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
// The DNS service failed, lets pass something reasonable
|
||||
// back to the listener.
|
||||
//
|
||||
switch (aStatus) {
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
case NS_ERROR_UNKNOWN_HOST:
|
||||
case NS_ERROR_FAILURE:
|
||||
case NS_ERROR_OFFLINE:
|
||||
rv = aStatus;
|
||||
break;
|
||||
|
||||
default:
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
} else if (!mResolvedIP.Length()) {
|
||||
// We have no host resolved, that is very bad, and should most
|
||||
// likely have been caught earlier.
|
||||
//
|
||||
NS_ERROR("nsLDAPConnection::OnStopLookup(): the resolved IP "
|
||||
"string is empty.\n");
|
||||
|
||||
rv = NS_ERROR_UNKNOWN_HOST;
|
||||
} else {
|
||||
// We've got the IP(s) for the hostname, now lets setup the
|
||||
// LDAP connection using this information. Note that if the
|
||||
// LDAP server returns a referral, the C-SDK will perform a
|
||||
// new, synchronous DNS lookup, which might hang (but hopefully
|
||||
// if we've come this far, DNS is working properly).
|
||||
//
|
||||
mConnectionHandle = ldap_init(mResolvedIP.get(),
|
||||
mPort == -1 ?
|
||||
(mSSL ? LDAPS_PORT : LDAP_PORT) : mPort);
|
||||
// Check that we got a proper connection, and if so, setup the
|
||||
// threading functions for this connection.
|
||||
//
|
||||
if ( !mConnectionHandle ) {
|
||||
rv = NS_ERROR_FAILURE; // LDAP C SDK API gives no useful error
|
||||
} else {
|
||||
#if defined(DEBUG_dmose) || defined(DEBUG_bienvenu)
|
||||
const int lDebug = 0;
|
||||
ldap_set_option(mConnectionHandle, LDAP_OPT_DEBUG_LEVEL, &lDebug);
|
||||
#endif
|
||||
|
||||
// the C SDK currently defaults to v2. if we're to use v3,
|
||||
// tell it so.
|
||||
//
|
||||
int version;
|
||||
switch (mVersion) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
version = LDAP_VERSION3;
|
||||
ldap_set_option(mConnectionHandle, LDAP_OPT_PROTOCOL_VERSION,
|
||||
&version);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("nsLDAPConnection::OnLookupComplete(): mVersion"
|
||||
" invalid");
|
||||
}
|
||||
|
||||
// This code sets up the current connection to use PSM for SSL
|
||||
// functionality. Making this use libssldap instead for
|
||||
// non-browser user shouldn't be hard.
|
||||
|
||||
extern nsresult nsLDAPInstallSSL(LDAP *ld, const char *aHostName);
|
||||
|
||||
if (mSSL) {
|
||||
if (ldap_set_option(mConnectionHandle, LDAP_OPT_SSL,
|
||||
LDAP_OPT_ON) != LDAP_SUCCESS ) {
|
||||
NS_ERROR("nsLDAPConnection::OnStopLookup(): Error"
|
||||
" configuring connection to use SSL");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = nsLDAPInstallSSL(mConnectionHandle, mDNSHost.get());
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPConnection::OnStopLookup(): Error"
|
||||
" installing secure LDAP routines for"
|
||||
" connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the DNS request object, we no longer need it, and set the flag
|
||||
// indicating that DNS has finished.
|
||||
//
|
||||
mDNSRequest = nullptr;
|
||||
mDNSHost.Truncate();
|
||||
|
||||
// Call the listener, and then we can release our reference to it.
|
||||
//
|
||||
mInitListener->OnLDAPInit(this, rv);
|
||||
mInitListener = nullptr;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsLDAPConnectionRunnable::nsLDAPConnectionRunnable(int32_t aOperationID,
|
||||
nsILDAPOperation *aOperation,
|
||||
nsLDAPConnection *aConnection)
|
||||
: mOperationID(aOperationID), mConnection(aConnection)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPConnectionRunnable::~nsLDAPConnectionRunnable()
|
||||
{
|
||||
if (mConnection) {
|
||||
NS_ReleaseOnMainThread(mConnection.forget());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPConnectionRunnable, nsIRunnable)
|
||||
|
||||
NS_IMETHODIMP nsLDAPConnectionRunnable::Run()
|
||||
{
|
||||
if (!mOperationID) {
|
||||
NS_ERROR("mOperationID is null");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
LDAPMessage *msgHandle;
|
||||
bool operationFinished = true;
|
||||
RefPtr<nsLDAPMessage> msg;
|
||||
|
||||
struct timeval timeout = { 0, 0 };
|
||||
|
||||
nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
|
||||
int32_t returnCode = ldap_result(mConnection->mConnectionHandle, mOperationID, LDAP_MSG_ONE, &timeout, &msgHandle);
|
||||
switch (returnCode)
|
||||
{
|
||||
// timeout
|
||||
case 0:
|
||||
// XXX do we need a timer?
|
||||
return thread->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
|
||||
case -1:
|
||||
NS_ERROR("We don't know what went wrong with the ldap operation");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
// XXX what should we do with LDAP_RES_SEARCH_EXTENDED
|
||||
operationFinished = false;
|
||||
MOZ_FALLTHROUGH;
|
||||
default:
|
||||
{
|
||||
msg = new nsLDAPMessage;
|
||||
if (!msg)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// initialize the message, using a protected method not available
|
||||
// through nsILDAPMessage (which is why we need the raw pointer)
|
||||
nsresult rv = msg->Init(mConnection, msgHandle);
|
||||
|
||||
switch (rv)
|
||||
{
|
||||
case NS_OK:
|
||||
{
|
||||
int32_t errorCode;
|
||||
msg->GetErrorCode(&errorCode);
|
||||
|
||||
// maybe a version error, e.g., using v3 on a v2 server.
|
||||
// if we're using v3, try v2.
|
||||
if (errorCode == LDAP_PROTOCOL_ERROR &&
|
||||
mConnection->mVersion == nsILDAPConnection::VERSION3)
|
||||
{
|
||||
nsAutoCString password;
|
||||
mConnection->mVersion = nsILDAPConnection::VERSION2;
|
||||
ldap_set_option(mConnection->mConnectionHandle,
|
||||
LDAP_OPT_PROTOCOL_VERSION, &mConnection->mVersion);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
// We don't want to notify callers that we are done, so
|
||||
// redispatch the runnable.
|
||||
// XXX do we need a timer?
|
||||
rv = thread->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
// If we're midway through a SASL Bind, we need to continue
|
||||
// without letting our caller know what we're up to!
|
||||
//
|
||||
if (errorCode == LDAP_SASL_BIND_IN_PROGRESS) {
|
||||
struct berval *creds;
|
||||
ldap_parse_sasl_bind_result(
|
||||
mConnection->mConnectionHandle, msgHandle,
|
||||
&creds, 0);
|
||||
|
||||
nsCOMPtr<nsILDAPOperation> operation;
|
||||
{
|
||||
MutexAutoLock lock(mConnection->mPendingOperationsMutex);
|
||||
mConnection->mPendingOperations.Get((uint32_t)mOperationID, getter_AddRefs(operation));
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(operation, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsresult rv = operation->SaslStep(creds->bv_val, creds->bv_len);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return NS_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Error code handling in here
|
||||
default:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// invoke the callback on the nsILDAPOperation corresponding to
|
||||
// this message
|
||||
rv = mConnection->InvokeMessageCallback(msgHandle, msg, mOperationID,
|
||||
operationFinished);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_ERROR("CheckLDAPOperationResult(): error invoking message"
|
||||
" callback");
|
||||
// punt and hope things work out better next time around
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!operationFinished)
|
||||
{
|
||||
// XXX do we need a timer?
|
||||
rv = thread->Dispatch(this, nsIEventTarget::DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
139
ldap/xpcom/src/nsLDAPConnection.h
Normal file
139
ldap/xpcom/src/nsLDAPConnection.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsLDAPConnection_h_
|
||||
#define _nsLDAPConnection_h_
|
||||
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "ldap.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nspr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
/**
|
||||
* Casting nsILDAPConnection to nsISupports is ambiguous.
|
||||
* This method handles that.
|
||||
*/
|
||||
inline nsISupports*
|
||||
ToSupports(nsILDAPConnection* p)
|
||||
{
|
||||
return NS_ISUPPORTS_CAST(nsILDAPConnection*, p);
|
||||
}
|
||||
|
||||
// 0d871e30-1dd2-11b2-8ea9-831778c78e93
|
||||
//
|
||||
#define NS_LDAPCONNECTION_CID \
|
||||
{ 0x0d871e30, 0x1dd2, 0x11b2, \
|
||||
{ 0x8e, 0xa9, 0x83, 0x17, 0x78, 0xc7, 0x8e, 0x93 }}
|
||||
|
||||
class nsLDAPConnection : public nsILDAPConnection,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIDNSListener,
|
||||
public nsIObserver
|
||||
|
||||
{
|
||||
friend class nsLDAPOperation;
|
||||
friend class nsLDAPMessage;
|
||||
friend class nsLDAPConnectionRunnable;
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPCONNECTION
|
||||
NS_DECL_NSIDNSLISTENER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// constructor & destructor
|
||||
//
|
||||
nsLDAPConnection();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPConnection();
|
||||
// invoke the callback associated with a given message, and possibly
|
||||
// delete it from the connection queue
|
||||
//
|
||||
nsresult InvokeMessageCallback(LDAPMessage *aMsgHandle,
|
||||
nsILDAPMessage *aMsg,
|
||||
int32_t aOperation,
|
||||
bool aRemoveOpFromConnQ);
|
||||
/**
|
||||
* Add an nsILDAPOperation to the list of operations pending on
|
||||
* this connection. This is mainly intended for use by the
|
||||
* nsLDAPOperation code. Used so that the thread waiting on messages
|
||||
* for this connection has an operation to callback to.
|
||||
*
|
||||
* @param aOperation operation to add
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE aOperation was NULL
|
||||
* @exception NS_ERROR_UNEXPECTED this operation's msgId was not
|
||||
* unique to this connection
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY out of memory
|
||||
*/
|
||||
nsresult AddPendingOperation(uint32_t aOperationID, nsILDAPOperation *aOperation);
|
||||
|
||||
/**
|
||||
* Remove an nsILDAPOperation from the list of operations pending on this
|
||||
* connection. Mainly intended for use by the nsLDAPOperation code.
|
||||
*
|
||||
* @param aOperation operation to add
|
||||
* @exception NS_ERROR_INVALID_POINTER aOperation was NULL
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY out of memory
|
||||
* @exception NS_ERROR_FAILURE could not delete the operation
|
||||
*/
|
||||
nsresult RemovePendingOperation(uint32_t aOperationID);
|
||||
|
||||
void Close(); // close the connection
|
||||
LDAP *mConnectionHandle; // the LDAP C SDK's connection object
|
||||
nsCString mBindName; // who to bind as
|
||||
nsCOMPtr<nsIThread> mThread; // thread which marshals results
|
||||
|
||||
Mutex mPendingOperationsMutex;
|
||||
nsInterfaceHashtable<nsUint32HashKey, nsILDAPOperation> mPendingOperations;
|
||||
|
||||
int32_t mPort; // The LDAP port we're binding to
|
||||
bool mSSL; // the options
|
||||
uint32_t mVersion; // LDAP protocol version
|
||||
|
||||
nsCString mResolvedIP; // Preresolved list of host IPs
|
||||
nsCOMPtr<nsILDAPMessageListener> mInitListener; // Init callback
|
||||
nsCOMPtr<nsICancelable> mDNSRequest; // The "active" DNS request
|
||||
nsCString mDNSHost; // The hostname being resolved
|
||||
nsCOMPtr<nsISupports> mClosure; // private parameter (anything caller desires)
|
||||
};
|
||||
|
||||
class nsLDAPConnectionRunnable : public nsIRunnable
|
||||
{
|
||||
friend class nsLDAPConnection;
|
||||
friend class nsLDAPMessage;
|
||||
|
||||
public:
|
||||
nsLDAPConnectionRunnable(int32_t aOperationID,
|
||||
nsILDAPOperation *aOperation,
|
||||
nsLDAPConnection *aConnection);
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
int32_t mOperationID;
|
||||
RefPtr<nsLDAPConnection> mConnection;
|
||||
|
||||
private:
|
||||
virtual ~nsLDAPConnectionRunnable();
|
||||
};
|
||||
|
||||
#endif // _nsLDAPConnection_h_
|
||||
122
ldap/xpcom/src/nsLDAPControl.cpp
Normal file
122
ldap/xpcom/src/nsLDAPControl.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPControl.h"
|
||||
#include "prmem.h"
|
||||
#include "plstr.h"
|
||||
#include "nsLDAPBERValue.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPControl, nsILDAPControl)
|
||||
|
||||
nsLDAPControl::nsLDAPControl()
|
||||
: mIsCritical(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPControl::~nsLDAPControl()
|
||||
{
|
||||
}
|
||||
|
||||
/* attribute ACString oid; */
|
||||
NS_IMETHODIMP nsLDAPControl::GetOid(nsACString & aOid)
|
||||
{
|
||||
aOid.Assign(mOid);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPControl::SetOid(const nsACString & aOid)
|
||||
{
|
||||
mOid = aOid;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute nsILDAPBERValue value; */
|
||||
NS_IMETHODIMP
|
||||
nsLDAPControl::GetValue(nsILDAPBERValue * *aValue)
|
||||
{
|
||||
NS_IF_ADDREF(*aValue = mValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPControl::SetValue(nsILDAPBERValue * aValue)
|
||||
{
|
||||
mValue = aValue;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* attribute boolean isCritical; */
|
||||
NS_IMETHODIMP
|
||||
nsLDAPControl::GetIsCritical(bool *aIsCritical)
|
||||
{
|
||||
*aIsCritical = mIsCritical;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsLDAPControl::SetIsCritical(bool aIsCritical)
|
||||
{
|
||||
mIsCritical = aIsCritical;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* utility routine for use inside the LDAP XPCOM SDK
|
||||
*/
|
||||
nsresult
|
||||
nsLDAPControl::ToLDAPControl(LDAPControl **control)
|
||||
{
|
||||
// because nsLDAPProtocolModule::Init calls prldap_install_routines we know
|
||||
// that the C SDK will be using the NSPR allocator under the hood, so our
|
||||
// callers will therefore be able to use ldap_control_free() and friends on
|
||||
// this control.
|
||||
LDAPControl *ctl = static_cast<LDAPControl *>(PR_Calloc(1, sizeof(LDAPControl)));
|
||||
if (!ctl) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// need to ensure that this string is also alloced by PR_Alloc
|
||||
ctl->ldctl_oid = PL_strdup(mOid.get());
|
||||
if (!ctl->ldctl_oid) {
|
||||
PR_Free(ctl);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
ctl->ldctl_iscritical = mIsCritical;
|
||||
|
||||
if (!mValue) {
|
||||
// no data associated with this control
|
||||
ctl->ldctl_value.bv_len = 0;
|
||||
ctl->ldctl_value.bv_val = 0;
|
||||
} else {
|
||||
|
||||
// just to make the code below a bit more readable
|
||||
nsLDAPBERValue *nsBerVal =
|
||||
static_cast<nsLDAPBERValue *>(static_cast<nsILDAPBERValue *>
|
||||
(mValue.get()));
|
||||
ctl->ldctl_value.bv_len = nsBerVal->mSize;
|
||||
|
||||
if (!nsBerVal->mSize) {
|
||||
// a zero-length value is associated with this control
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
} else {
|
||||
|
||||
// same for the berval itself
|
||||
ctl->ldctl_value.bv_len = nsBerVal->mSize;
|
||||
ctl->ldctl_value.bv_val = static_cast<char *>
|
||||
(PR_Malloc(nsBerVal->mSize));
|
||||
if (!ctl->ldctl_value.bv_val) {
|
||||
ldap_control_free(ctl);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(ctl->ldctl_value.bv_val, nsBerVal->mValue,
|
||||
ctl->ldctl_value.bv_len);
|
||||
}
|
||||
}
|
||||
|
||||
*control = ctl;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
42
ldap/xpcom/src/nsLDAPControl.h
Normal file
42
ldap/xpcom/src/nsLDAPControl.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsILDAPControl.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPBERValue.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "ldap.h"
|
||||
|
||||
// {5B608BBE-C0EA-4f74-B209-9CDCD79EC401}
|
||||
#define NS_LDAPCONTROL_CID \
|
||||
{ 0x5b608bbe, 0xc0ea, 0x4f74, \
|
||||
{ 0xb2, 0x9, 0x9c, 0xdc, 0xd7, 0x9e, 0xc4, 0x1 } }
|
||||
|
||||
class nsLDAPControl final : public nsILDAPControl
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSILDAPCONTROL
|
||||
|
||||
nsLDAPControl();
|
||||
|
||||
/**
|
||||
* return a pointer to C-SDK compatible LDAPControl structure. Note that
|
||||
* this is allocated with NS_Alloc and must be freed with NS_Free, both by
|
||||
* ldap_control_free() and friends.
|
||||
*
|
||||
* @exception null pointer return if allocation failed
|
||||
*/
|
||||
nsresult ToLDAPControl(LDAPControl **aControl);
|
||||
|
||||
private:
|
||||
~nsLDAPControl();
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsILDAPBERValue> mValue; // the value portion of this control
|
||||
bool mIsCritical; // should server abort if control not understood?
|
||||
nsCString mOid; // Object ID for this control
|
||||
};
|
||||
11
ldap/xpcom/src/nsLDAPInternal.h
Normal file
11
ldap/xpcom/src/nsLDAPInternal.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "prlog.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
extern PRLogModuleInfo *gLDAPLogModule; // defn in nsLDAPProtocolModule.cpp
|
||||
#endif
|
||||
649
ldap/xpcom/src/nsLDAPMessage.cpp
Normal file
649
ldap/xpcom/src/nsLDAPMessage.cpp
Normal file
|
|
@ -0,0 +1,649 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsLDAPMessage.h"
|
||||
#include "nspr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsLDAPConnection.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsLDAPBERValue.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsLDAPUtils.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
NS_IMPL_CLASSINFO(nsLDAPMessage, NULL, nsIClassInfo::THREADSAFE,
|
||||
NS_LDAPMESSAGE_CID)
|
||||
|
||||
NS_IMPL_ADDREF(nsLDAPMessage)
|
||||
NS_IMPL_RELEASE(nsLDAPMessage)
|
||||
NS_INTERFACE_MAP_BEGIN(nsLDAPMessage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsILDAPMessage)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILDAPMessage)
|
||||
NS_IMPL_QUERY_CLASSINFO(nsLDAPMessage)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
NS_IMPL_CI_INTERFACE_GETTER(nsLDAPMessage, nsILDAPMessage)
|
||||
|
||||
|
||||
// constructor
|
||||
//
|
||||
nsLDAPMessage::nsLDAPMessage()
|
||||
: mMsgHandle(0),
|
||||
mErrorCode(LDAP_SUCCESS),
|
||||
mMatchedDn(0),
|
||||
mErrorMessage(0),
|
||||
mReferrals(0),
|
||||
mServerControls(0)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
//
|
||||
nsLDAPMessage::~nsLDAPMessage(void)
|
||||
{
|
||||
if (mMsgHandle) {
|
||||
int rc = ldap_msgfree(mMsgHandle);
|
||||
|
||||
// If you are having problems compiling the following code on a Solaris
|
||||
// machine with the Forte 6 Update 1 compilers, then you need to make
|
||||
// sure you have applied all the required patches. See:
|
||||
// http://www.mozilla.org/unix/solaris-build.html for more details.
|
||||
|
||||
switch(rc) {
|
||||
case LDAP_RES_BIND:
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
case LDAP_RES_MODIFY:
|
||||
case LDAP_RES_ADD:
|
||||
case LDAP_RES_DELETE:
|
||||
case LDAP_RES_MODRDN:
|
||||
case LDAP_RES_COMPARE:
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
case LDAP_RES_EXTENDED:
|
||||
case LDAP_RES_ANY:
|
||||
// success
|
||||
break;
|
||||
|
||||
case LDAP_SUCCESS:
|
||||
// timed out (dunno why LDAP_SUCCESS is used to indicate this)
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Warning,
|
||||
("nsLDAPMessage::~nsLDAPMessage: ldap_msgfree() "
|
||||
"timed out\n"));
|
||||
break;
|
||||
|
||||
default:
|
||||
// other failure
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Warning,
|
||||
("nsLDAPMessage::~nsLDAPMessage: ldap_msgfree() "
|
||||
"failed: %s\n", ldap_err2string(rc)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMatchedDn) {
|
||||
ldap_memfree(mMatchedDn);
|
||||
}
|
||||
|
||||
if (mErrorMessage) {
|
||||
ldap_memfree(mErrorMessage);
|
||||
}
|
||||
|
||||
if (mReferrals) {
|
||||
ldap_value_free(mReferrals);
|
||||
}
|
||||
|
||||
if (mServerControls) {
|
||||
ldap_controls_free(mServerControls);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a message.
|
||||
*
|
||||
* @param aConnection The nsLDAPConnection this message is on
|
||||
* @param aMsgHandle The native LDAPMessage to be wrapped.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
* @exception NS_ERROR_UNEXPECTED internal err; shouldn't happen
|
||||
* @exception NS_ERROR_LDAP_DECODING_ERROR problem during BER decoding
|
||||
* @exception NS_ERROR_OUT_OF_MEMORY ran out of memory
|
||||
*/
|
||||
nsresult
|
||||
nsLDAPMessage::Init(nsILDAPConnection *aConnection, LDAPMessage *aMsgHandle)
|
||||
{
|
||||
int parseResult;
|
||||
|
||||
if (!aConnection || !aMsgHandle) {
|
||||
NS_WARNING("Null pointer passed in to nsLDAPMessage::Init()");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// initialize the appropriate member vars
|
||||
//
|
||||
mConnection = aConnection;
|
||||
mMsgHandle = aMsgHandle;
|
||||
|
||||
// cache the connection handle. we're violating the XPCOM type-system
|
||||
// here since we're a friend of the connection class and in the
|
||||
// same module.
|
||||
//
|
||||
mConnectionHandle = static_cast<nsLDAPConnection *>(aConnection)->mConnectionHandle;
|
||||
|
||||
// do any useful message parsing
|
||||
//
|
||||
const int msgType = ldap_msgtype(mMsgHandle);
|
||||
if ( msgType == -1) {
|
||||
NS_ERROR("nsLDAPMessage::Init(): ldap_msgtype() failed");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
switch (msgType) {
|
||||
|
||||
case LDAP_RES_SEARCH_REFERENCE:
|
||||
// XXX should do something here?
|
||||
break;
|
||||
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
// nothing to do here
|
||||
break;
|
||||
|
||||
case LDAP_RES_EXTENDED:
|
||||
// XXX should do something here?
|
||||
break;
|
||||
|
||||
case LDAP_RES_BIND:
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
case LDAP_RES_MODIFY:
|
||||
case LDAP_RES_ADD:
|
||||
case LDAP_RES_DELETE:
|
||||
case LDAP_RES_MODRDN:
|
||||
case LDAP_RES_COMPARE:
|
||||
parseResult = ldap_parse_result(mConnectionHandle,
|
||||
mMsgHandle, &mErrorCode, &mMatchedDn,
|
||||
&mErrorMessage,&mReferrals,
|
||||
&mServerControls, 0);
|
||||
switch (parseResult) {
|
||||
case LDAP_SUCCESS:
|
||||
// we're good
|
||||
break;
|
||||
|
||||
case LDAP_DECODING_ERROR:
|
||||
NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() hit a "
|
||||
"decoding error");
|
||||
return NS_ERROR_LDAP_DECODING_ERROR;
|
||||
|
||||
case LDAP_NO_MEMORY:
|
||||
NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() ran out "
|
||||
"of memory");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
case LDAP_PARAM_ERROR:
|
||||
case LDAP_MORE_RESULTS_TO_RETURN:
|
||||
case LDAP_NO_RESULTS_RETURNED:
|
||||
default:
|
||||
NS_ERROR("nsLDAPMessage::Init(): ldap_parse_result returned "
|
||||
"unexpected return code");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("nsLDAPMessage::Init(): unexpected message type");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* The result code of the (possibly partial) operation.
|
||||
*
|
||||
* @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in
|
||||
*
|
||||
* readonly attribute long errorCode;
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetErrorCode(int32_t *aErrorCode)
|
||||
{
|
||||
if (!aErrorCode) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aErrorCode = mErrorCode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetType(int32_t *aType)
|
||||
{
|
||||
if (!aType) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aType = ldap_msgtype(mMsgHandle);
|
||||
if (*aType == -1) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
};
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// we don't get to use exceptions, so we'll fake it. this is an error
|
||||
// handler for IterateAttributes().
|
||||
//
|
||||
nsresult
|
||||
nsLDAPMessage::IterateAttrErrHandler(int32_t aLderrno, uint32_t *aAttrCount,
|
||||
char** *aAttributes, BerElement *position)
|
||||
{
|
||||
|
||||
// if necessary, free the position holder used by
|
||||
// ldap_{first,next}_attribute()
|
||||
//
|
||||
if (position) {
|
||||
ldap_ber_free(position, 0);
|
||||
}
|
||||
|
||||
// deallocate any entries in the array that have been allocated, then
|
||||
// the array itself
|
||||
//
|
||||
if (*aAttributes) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aAttrCount, *aAttributes);
|
||||
}
|
||||
|
||||
// possibly spit out a debugging message, then return an appropriate
|
||||
// error code
|
||||
//
|
||||
switch (aLderrno) {
|
||||
|
||||
case LDAP_PARAM_ERROR:
|
||||
NS_WARNING("nsLDAPMessage::IterateAttributes() failure; probable bug "
|
||||
"or memory corruption encountered");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
|
||||
case LDAP_DECODING_ERROR:
|
||||
NS_WARNING("nsLDAPMessage::IterateAttributes(): decoding error");
|
||||
return NS_ERROR_LDAP_DECODING_ERROR;
|
||||
break;
|
||||
|
||||
case LDAP_NO_MEMORY:
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
NS_WARNING("nsLDAPMessage::IterateAttributes(): LDAP C SDK returned "
|
||||
"unexpected value; possible bug or memory corruption");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
// wrapper for ldap_first_attribute
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetAttributes(uint32_t *aAttrCount, char** *aAttributes)
|
||||
{
|
||||
return IterateAttributes(aAttrCount, aAttributes, true);
|
||||
}
|
||||
|
||||
// if getP is true, we get the attributes by recursing once
|
||||
// (without getP set) in order to fill in *attrCount, then allocate
|
||||
// and fill in the *aAttributes.
|
||||
//
|
||||
// if getP is false, just fill in *attrCount and return
|
||||
//
|
||||
nsresult
|
||||
nsLDAPMessage::IterateAttributes(uint32_t *aAttrCount, char** *aAttributes,
|
||||
bool getP)
|
||||
{
|
||||
BerElement *position;
|
||||
nsresult rv;
|
||||
|
||||
if (!aAttrCount || !aAttributes ) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// if we've been called from GetAttributes, recurse once in order to
|
||||
// count the elements in this message.
|
||||
//
|
||||
if (getP) {
|
||||
*aAttributes = 0;
|
||||
*aAttrCount = 0;
|
||||
|
||||
rv = IterateAttributes(aAttrCount, aAttributes, false);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// create an array of the appropriate size
|
||||
//
|
||||
*aAttributes = static_cast<char **>(moz_xmalloc(*aAttrCount *
|
||||
sizeof(char *)));
|
||||
if (!*aAttributes) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// get the first attribute
|
||||
//
|
||||
char *attr = ldap_first_attribute(mConnectionHandle,
|
||||
mMsgHandle,
|
||||
&position);
|
||||
if (!attr) {
|
||||
return IterateAttrErrHandler(ldap_get_lderrno(mConnectionHandle, 0, 0),
|
||||
aAttrCount, aAttributes, position);
|
||||
}
|
||||
|
||||
// if we're getting attributes, try and fill in the first field
|
||||
//
|
||||
if (getP) {
|
||||
(*aAttributes)[0] = NS_strdup(attr);
|
||||
if (!(*aAttributes)[0]) {
|
||||
ldap_memfree(attr);
|
||||
free(*aAttributes);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// note that we start counting again, in order to keep our place in
|
||||
// the array so that we can unwind gracefully and avoid leakage if
|
||||
// we hit an error as we're filling in the array
|
||||
//
|
||||
*aAttrCount = 1;
|
||||
} else {
|
||||
|
||||
// otherwise just update the count
|
||||
//
|
||||
*aAttrCount = 1;
|
||||
}
|
||||
ldap_memfree(attr);
|
||||
|
||||
while (1) {
|
||||
|
||||
// get the next attribute
|
||||
//
|
||||
attr = ldap_next_attribute(mConnectionHandle, mMsgHandle, position);
|
||||
|
||||
// check to see if there is an error, or if we're just done iterating
|
||||
//
|
||||
if (!attr) {
|
||||
|
||||
// bail out if there's an error
|
||||
//
|
||||
int32_t lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
|
||||
if (lderrno != LDAP_SUCCESS) {
|
||||
return IterateAttrErrHandler(lderrno, aAttrCount, aAttributes,
|
||||
position);
|
||||
}
|
||||
|
||||
// otherwise, there are no more attributes; we're done with
|
||||
// the while loop
|
||||
//
|
||||
break;
|
||||
|
||||
} else if (getP) {
|
||||
|
||||
// if ldap_next_attribute did return successfully, and
|
||||
// we're supposed to fill in a value, do so.
|
||||
//
|
||||
(*aAttributes)[*aAttrCount] = NS_strdup(attr);
|
||||
if (!(*aAttributes)[*aAttrCount]) {
|
||||
ldap_memfree(attr);
|
||||
return IterateAttrErrHandler(LDAP_NO_MEMORY, aAttrCount,
|
||||
aAttributes, position);
|
||||
}
|
||||
|
||||
}
|
||||
ldap_memfree(attr);
|
||||
|
||||
// we're done using *aAttrCount as a c-style array index (ie starting
|
||||
// at 0). update it to reflect the number of elements now in the array
|
||||
//
|
||||
*aAttrCount += 1;
|
||||
}
|
||||
|
||||
// free the position pointer, if necessary
|
||||
//
|
||||
if (position) {
|
||||
ldap_ber_free(position, 0);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// readonly attribute wstring dn;
|
||||
NS_IMETHODIMP nsLDAPMessage::GetDn(nsACString& aDn)
|
||||
{
|
||||
char *rawDn = ldap_get_dn(mConnectionHandle, mMsgHandle);
|
||||
|
||||
if (!rawDn) {
|
||||
int32_t lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
|
||||
|
||||
switch (lderrno) {
|
||||
|
||||
case LDAP_DECODING_ERROR:
|
||||
NS_WARNING("nsLDAPMessage::GetDn(): ldap decoding error");
|
||||
return NS_ERROR_LDAP_DECODING_ERROR;
|
||||
|
||||
case LDAP_PARAM_ERROR:
|
||||
default:
|
||||
NS_ERROR("nsLDAPMessage::GetDn(): internal error");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPMessage::GetDn(): dn = '%s'", rawDn));
|
||||
|
||||
aDn.Assign(rawDn);
|
||||
ldap_memfree(rawDn);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// wrapper for ldap_get_values()
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetValues(const char *aAttr, uint32_t *aCount,
|
||||
char16_t ***aValues)
|
||||
{
|
||||
char **values;
|
||||
|
||||
#if defined(DEBUG)
|
||||
// We only want this being logged for debug builds so as not to affect performance too much.
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPMessage::GetValues(): called with aAttr = '%s'", aAttr));
|
||||
#endif
|
||||
|
||||
values = ldap_get_values(mConnectionHandle, mMsgHandle, aAttr);
|
||||
|
||||
// bail out if there was a problem
|
||||
//
|
||||
if (!values) {
|
||||
int32_t lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
|
||||
|
||||
if ( lderrno == LDAP_DECODING_ERROR ) {
|
||||
// this may not be an error; it could just be that the
|
||||
// caller has asked for an attribute that doesn't exist.
|
||||
//
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Warning,
|
||||
("nsLDAPMessage::GetValues(): ldap_get_values returned "
|
||||
"LDAP_DECODING_ERROR"));
|
||||
return NS_ERROR_LDAP_DECODING_ERROR;
|
||||
|
||||
} else if ( lderrno == LDAP_PARAM_ERROR ) {
|
||||
NS_ERROR("nsLDAPMessage::GetValues(): internal error: 1");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
} else {
|
||||
NS_ERROR("nsLDAPMessage::GetValues(): internal error: 2");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// count the values
|
||||
//
|
||||
uint32_t numVals = ldap_count_values(values);
|
||||
|
||||
// create an array of the appropriate size
|
||||
//
|
||||
*aValues = static_cast<char16_t **>(moz_xmalloc(numVals * sizeof(char16_t *)));
|
||||
if (!*aValues) {
|
||||
ldap_value_free(values);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// clone the array (except for the trailing NULL entry) using the
|
||||
// shared allocator for XPCOM correctness
|
||||
//
|
||||
uint32_t i;
|
||||
for ( i = 0 ; i < numVals ; i++ ) {
|
||||
nsDependentCString sValue(values[i]);
|
||||
if (IsUTF8(sValue))
|
||||
(*aValues)[i] = ToNewUnicode(NS_ConvertUTF8toUTF16(sValue));
|
||||
else
|
||||
(*aValues)[i] = ToNewUnicode(NS_ConvertASCIItoUTF16(sValue));
|
||||
if ( ! (*aValues)[i] ) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, aValues);
|
||||
ldap_value_free(values);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
// now free our value array since we already cloned the values array
|
||||
// to the 'aValues' results array.
|
||||
ldap_value_free(values);
|
||||
|
||||
*aCount = numVals;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// wrapper for get_values_len
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetBinaryValues(const char *aAttr, uint32_t *aCount,
|
||||
nsILDAPBERValue ***aValues)
|
||||
{
|
||||
struct berval **values;
|
||||
|
||||
#if defined(DEBUG)
|
||||
// We only want this being logged for debug builds so as not to affect performance too much.
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPMessage::GetBinaryValues(): called with aAttr = '%s'",
|
||||
aAttr));
|
||||
#endif
|
||||
|
||||
values = ldap_get_values_len(mConnectionHandle, mMsgHandle, aAttr);
|
||||
|
||||
// bail out if there was a problem
|
||||
//
|
||||
if (!values) {
|
||||
int32_t lderrno = ldap_get_lderrno(mConnectionHandle, 0, 0);
|
||||
|
||||
if ( lderrno == LDAP_DECODING_ERROR ) {
|
||||
// this may not be an error; it could just be that the
|
||||
// caller has asked for an attribute that doesn't exist.
|
||||
//
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Warning,
|
||||
("nsLDAPMessage::GetBinaryValues(): ldap_get_values "
|
||||
"returned LDAP_DECODING_ERROR"));
|
||||
return NS_ERROR_LDAP_DECODING_ERROR;
|
||||
|
||||
} else if ( lderrno == LDAP_PARAM_ERROR ) {
|
||||
NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 1");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
} else {
|
||||
NS_ERROR("nsLDAPMessage::GetBinaryValues(): internal error: 2");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// count the values
|
||||
//
|
||||
uint32_t numVals = ldap_count_values_len(values);
|
||||
|
||||
// create the out array
|
||||
//
|
||||
*aValues =
|
||||
static_cast<nsILDAPBERValue **>(moz_xmalloc(numVals * sizeof(nsILDAPBERValue)));
|
||||
if (!aValues) {
|
||||
ldap_value_free_len(values);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// clone the array (except for the trailing NULL entry) using the
|
||||
// shared allocator for XPCOM correctness
|
||||
//
|
||||
uint32_t i;
|
||||
nsresult rv;
|
||||
for ( i = 0 ; i < numVals ; i++ ) {
|
||||
|
||||
// create an nsBERValue object
|
||||
//
|
||||
nsCOMPtr<nsILDAPBERValue> berValue = new nsLDAPBERValue();
|
||||
if (!berValue) {
|
||||
NS_ERROR("nsLDAPMessage::GetBinaryValues(): out of memory"
|
||||
" creating nsLDAPBERValue object");
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, aValues);
|
||||
ldap_value_free_len(values);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// copy the value from the struct into the nsBERValue
|
||||
//
|
||||
rv = berValue->Set(values[i]->bv_len,
|
||||
reinterpret_cast<uint8_t *>(values[i]->bv_val));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPMessage::GetBinaryValues(): error setting"
|
||||
" nsBERValue");
|
||||
ldap_value_free_len(values);
|
||||
return rv == NS_ERROR_OUT_OF_MEMORY ? rv : NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// put the nsIBERValue object into the out array
|
||||
//
|
||||
NS_ADDREF( (*aValues)[i] = berValue.get() );
|
||||
}
|
||||
|
||||
*aCount = numVals;
|
||||
ldap_value_free_len(values);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// readonly attribute nsILDAPOperation operation;
|
||||
NS_IMETHODIMP nsLDAPMessage::GetOperation(nsILDAPOperation **_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPMessage::GetOperation: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*_retval = mOperation);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::ToUnicode(char16_t* *aString)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetErrorMessage(nsACString & aErrorMessage)
|
||||
{
|
||||
aErrorMessage.Assign(mErrorMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPMessage::GetMatchedDn(nsACString & aMatchedDn)
|
||||
{
|
||||
aMatchedDn.Assign(mMatchedDn);
|
||||
return NS_OK;
|
||||
}
|
||||
66
ldap/xpcom/src/nsLDAPMessage.h
Normal file
66
ldap/xpcom/src/nsLDAPMessage.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsLDAPMessage_h_
|
||||
#define _nsLDAPMessage_h_
|
||||
|
||||
#include "ldap.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// 76e061ad-a59f-43b6-b812-ee6e8e69423f
|
||||
//
|
||||
#define NS_LDAPMESSAGE_CID \
|
||||
{ 0x76e061ad, 0xa59f, 0x43b6, \
|
||||
{ 0xb8, 0x12, 0xee, 0x6e, 0x8e, 0x69, 0x42, 0x3f }}
|
||||
|
||||
class nsLDAPMessage : public nsILDAPMessage
|
||||
{
|
||||
friend class nsLDAPOperation;
|
||||
friend class nsLDAPConnection;
|
||||
friend class nsLDAPConnectionRunnable;
|
||||
friend class nsOnLDAPMessageRunnable;
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPMESSAGE
|
||||
|
||||
// constructor & destructor
|
||||
//
|
||||
nsLDAPMessage();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPMessage();
|
||||
|
||||
nsresult IterateAttrErrHandler(int32_t aLderrno, uint32_t *aAttrCount,
|
||||
char** *aAttributes, BerElement *position);
|
||||
nsresult IterateAttributes(uint32_t *aAttrCount, char** *aAttributes,
|
||||
bool getP);
|
||||
nsresult Init(nsILDAPConnection *aConnection,
|
||||
LDAPMessage *aMsgHandle);
|
||||
LDAPMessage *mMsgHandle; // the message we're wrapping
|
||||
nsCOMPtr<nsILDAPOperation> mOperation; // operation this msg relates to
|
||||
|
||||
LDAP *mConnectionHandle; // cached connection this op is on
|
||||
|
||||
// since we're caching the connection handle (above), we need to
|
||||
// hold an owning ref to the relevant nsLDAPConnection object as long
|
||||
// as we're around
|
||||
//
|
||||
nsCOMPtr<nsILDAPConnection> mConnection;
|
||||
|
||||
// the next five member vars are returned by ldap_parse_result()
|
||||
//
|
||||
int mErrorCode;
|
||||
char *mMatchedDn;
|
||||
char *mErrorMessage;
|
||||
char **mReferrals;
|
||||
LDAPControl **mServerControls;
|
||||
};
|
||||
|
||||
#endif // _nsLDAPMessage_h
|
||||
158
ldap/xpcom/src/nsLDAPModification.cpp
Normal file
158
ldap/xpcom/src/nsLDAPModification.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPModification.h"
|
||||
#include "nsILDAPBERValue.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPModification, nsILDAPModification)
|
||||
|
||||
// constructor
|
||||
//
|
||||
nsLDAPModification::nsLDAPModification()
|
||||
: mValuesLock("nsLDAPModification.mValuesLock")
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
//
|
||||
nsLDAPModification::~nsLDAPModification()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLDAPModification::Init()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPModification::GetOperation(int32_t *aOperation)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOperation);
|
||||
|
||||
*aOperation = mOperation;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPModification::SetOperation(int32_t 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);
|
||||
|
||||
MutexAutoLock 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);
|
||||
|
||||
MutexAutoLock 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);
|
||||
|
||||
bool 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, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = enumerator->HasMoreElements(&hasMoreElements);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPModification::SetUpModification(int32_t 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);
|
||||
|
||||
MutexAutoLock lock(mValuesLock);
|
||||
|
||||
mOperation = aOperation;
|
||||
mType.Assign(aType);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPModification::SetUpModificationOneValue(int32_t aOperation,
|
||||
const nsACString &aType,
|
||||
nsILDAPBERValue *aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aValue);
|
||||
|
||||
MutexAutoLock 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, false);
|
||||
}
|
||||
42
ldap/xpcom/src/nsLDAPModification.h
Normal file
42
ldap/xpcom/src/nsLDAPModification.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsLDAPModification_h_
|
||||
#define _nsLDAPModification_h_
|
||||
|
||||
#include "nsILDAPModification.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Mutex.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_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPMODIFICATION
|
||||
|
||||
// constructor & destructor
|
||||
//
|
||||
nsLDAPModification();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
private:
|
||||
virtual ~nsLDAPModification();
|
||||
|
||||
int32_t mOperation;
|
||||
nsCString mType;
|
||||
nsCOMPtr<nsIMutableArray> mValues;
|
||||
mozilla::Mutex mValuesLock;
|
||||
};
|
||||
|
||||
#endif // _nsLDAPModification_h_
|
||||
975
ldap/xpcom/src/nsLDAPOperation.cpp
Normal file
975
ldap/xpcom/src/nsLDAPOperation.cpp
Normal file
|
|
@ -0,0 +1,975 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsLDAPOperation.h"
|
||||
#include "nsLDAPBERValue.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPModification.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nspr.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsLDAPControl.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsIAuthModule.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsMemory.h"
|
||||
#include "mozilla/Logging.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:
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Error,
|
||||
("TranslateLDAPErrorToNSError: "
|
||||
"Do not know how to translate LDAP error: 0x%x", ldapError));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// constructor
|
||||
nsLDAPOperation::nsLDAPOperation()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
nsLDAPOperation::~nsLDAPOperation()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_CLASSINFO(nsLDAPOperation, NULL, nsIClassInfo::THREADSAFE,
|
||||
NS_LDAPOPERATION_CID)
|
||||
|
||||
NS_IMPL_ADDREF(nsLDAPOperation)
|
||||
NS_IMPL_RELEASE(nsLDAPOperation)
|
||||
NS_INTERFACE_MAP_BEGIN(nsLDAPOperation)
|
||||
NS_INTERFACE_MAP_ENTRY(nsILDAPOperation)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsILDAPOperation)
|
||||
NS_IMPL_QUERY_CLASSINFO(nsLDAPOperation)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
NS_IMPL_CI_INTERFACE_GETTER(nsLDAPOperation, nsILDAPOperation)
|
||||
|
||||
/**
|
||||
* Initializes this operation. Must be called prior to use.
|
||||
*
|
||||
* @param aConnection connection this operation should use
|
||||
* @param aMessageListener where are the results are called back to.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::Init(nsILDAPConnection *aConnection,
|
||||
nsILDAPMessageListener *aMessageListener,
|
||||
nsISupports *aClosure)
|
||||
{
|
||||
if (!aConnection) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
// so we know that the operation is not yet running (and therefore don't
|
||||
// try and call ldap_abandon_ext() on it) or remove it from the queue.
|
||||
//
|
||||
mMsgID = 0;
|
||||
|
||||
// set the member vars
|
||||
//
|
||||
mConnection = static_cast<nsLDAPConnection*>(aConnection);
|
||||
mMessageListener = aMessageListener;
|
||||
mClosure = aClosure;
|
||||
|
||||
// cache the connection handle
|
||||
//
|
||||
mConnectionHandle =
|
||||
mConnection->mConnectionHandle;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::GetClosure(nsISupports **_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
NS_IF_ADDREF(*_retval = mClosure);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SetClosure(nsISupports *aClosure)
|
||||
{
|
||||
mClosure = aClosure;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::GetConnection(nsILDAPConnection* *aConnection)
|
||||
{
|
||||
if (!aConnection) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aConnection = mConnection;
|
||||
NS_IF_ADDREF(*aConnection);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsLDAPOperation::Clear()
|
||||
{
|
||||
mMessageListener = nullptr;
|
||||
mClosure = nullptr;
|
||||
mConnection = nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::GetMessageListener(nsILDAPMessageListener **aMessageListener)
|
||||
{
|
||||
if (!aMessageListener) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aMessageListener = mMessageListener;
|
||||
NS_IF_ADDREF(*aMessageListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SaslBind(const nsACString &service,
|
||||
const nsACString &mechanism,
|
||||
nsIAuthModule *authModule)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoCString bindName;
|
||||
struct berval creds;
|
||||
unsigned int credlen;
|
||||
|
||||
mAuthModule = authModule;
|
||||
mMechanism.Assign(mechanism);
|
||||
|
||||
rv = mConnection->GetBindName(bindName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
creds.bv_val = NULL;
|
||||
mAuthModule->Init(PromiseFlatCString(service).get(),
|
||||
nsIAuthModule::REQ_DEFAULT, nullptr,
|
||||
NS_ConvertUTF8toUTF16(bindName).get(), nullptr);
|
||||
|
||||
rv = mAuthModule->GetNextToken(nullptr, 0, (void **)&creds.bv_val,
|
||||
&credlen);
|
||||
if (NS_FAILED(rv) || !creds.bv_val)
|
||||
return rv;
|
||||
|
||||
creds.bv_len = credlen;
|
||||
const int lderrno = ldap_sasl_bind(mConnectionHandle, bindName.get(),
|
||||
mMechanism.get(), &creds, NULL, NULL,
|
||||
&mMsgID);
|
||||
free(creds.bv_val);
|
||||
|
||||
if (lderrno != LDAP_SUCCESS)
|
||||
return TranslateLDAPErrorToNSError(lderrno);
|
||||
|
||||
// make sure the connection knows where to call back once the messages
|
||||
// for this operation start coming in
|
||||
rv = mConnection->AddPendingOperation(mMsgID, this);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SaslStep(const char *token, uint32_t tokenLen)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoCString bindName;
|
||||
struct berval clientCreds;
|
||||
struct berval serverCreds;
|
||||
unsigned int credlen;
|
||||
|
||||
rv = mConnection->RemovePendingOperation(mMsgID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
serverCreds.bv_val = (char *) token;
|
||||
serverCreds.bv_len = tokenLen;
|
||||
|
||||
rv = mConnection->GetBindName(bindName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mAuthModule->GetNextToken(serverCreds.bv_val, serverCreds.bv_len,
|
||||
(void **) &clientCreds.bv_val, &credlen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
clientCreds.bv_len = credlen;
|
||||
|
||||
const int lderrno = ldap_sasl_bind(mConnectionHandle, bindName.get(),
|
||||
mMechanism.get(), &clientCreds, NULL,
|
||||
NULL, &mMsgID);
|
||||
|
||||
free(clientCreds.bv_val);
|
||||
|
||||
if (lderrno != LDAP_SUCCESS)
|
||||
return TranslateLDAPErrorToNSError(lderrno);
|
||||
|
||||
// make sure the connection knows where to call back once the messages
|
||||
// for this operation start coming in
|
||||
rv = mConnection->AddPendingOperation(mMsgID, this);
|
||||
if (NS_FAILED(rv))
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// wrapper for ldap_simple_bind()
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SimpleBind(const nsACString& passwd)
|
||||
{
|
||||
RefPtr<nsLDAPConnection> connection = mConnection;
|
||||
// There is a possibilty that mConnection can be cleared by another
|
||||
// thread. Grabbing a local reference to mConnection may avoid this.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=557928#c1
|
||||
nsresult rv;
|
||||
nsAutoCString bindName;
|
||||
int32_t originalMsgID = mMsgID;
|
||||
// Ugly hack alert:
|
||||
// the first time we get called with a passwd, remember it.
|
||||
// Then, if we get called again w/o a password, use the
|
||||
// saved one. Getting called again means we're trying to
|
||||
// fall back to VERSION2.
|
||||
// Since LDAP operations are thrown away when done, it won't stay
|
||||
// around in memory.
|
||||
if (!passwd.IsEmpty())
|
||||
mSavePassword = passwd;
|
||||
|
||||
NS_PRECONDITION(mMessageListener, "MessageListener not set");
|
||||
|
||||
rv = connection->GetBindName(bindName);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPOperation::SimpleBind(): called; bindName = '%s'; ",
|
||||
bindName.get()));
|
||||
|
||||
// this (nsLDAPOperation) may be released by RemovePendingOperation()
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1063829.
|
||||
RefPtr<nsLDAPOperation> kungFuDeathGrip = this;
|
||||
|
||||
// If this is a second try at binding, remove the operation from pending ops
|
||||
// because msg id has changed...
|
||||
if (originalMsgID)
|
||||
connection->RemovePendingOperation(originalMsgID);
|
||||
|
||||
mMsgID = ldap_simple_bind(mConnectionHandle, bindName.get(),
|
||||
mSavePassword.get());
|
||||
|
||||
if (mMsgID == -1) {
|
||||
// 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
|
||||
// for this operation start coming in
|
||||
rv = connection->AddPendingOperation(mMsgID, this);
|
||||
switch (rv) {
|
||||
case NS_OK:
|
||||
break;
|
||||
|
||||
// note that the return value of ldap_abandon_ext() is ignored, as
|
||||
// there's nothing useful to do with it
|
||||
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
|
||||
case NS_ERROR_UNEXPECTED:
|
||||
case NS_ERROR_ILLEGAL_VALUE:
|
||||
default:
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an nsIArray of nsILDAPControls, return the appropriate
|
||||
* zero-terminated array of LDAPControls ready to pass in to the C SDK.
|
||||
*/
|
||||
static nsresult
|
||||
convertControlArray(nsIArray *aXpcomArray, LDAPControl ***aArray)
|
||||
{
|
||||
// get the size of the original array
|
||||
uint32_t length;
|
||||
nsresult rv = aXpcomArray->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// don't allocate an array if someone passed us in an empty one
|
||||
if (!length) {
|
||||
*aArray = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// allocate a local array of the form understood by the C-SDK;
|
||||
// +1 is to account for the final null terminator. PR_Calloc is
|
||||
// is used so that ldap_controls_free will work anywhere during the
|
||||
// iteration
|
||||
LDAPControl **controls =
|
||||
static_cast<LDAPControl **>
|
||||
(PR_Calloc(length+1, sizeof(LDAPControl)));
|
||||
|
||||
// prepare to enumerate the array
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
rv = aXpcomArray->Enumerate(getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool moreElements;
|
||||
rv = enumerator->HasMoreElements(&moreElements);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t i = 0;
|
||||
while (moreElements) {
|
||||
|
||||
// get the next array element
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = enumerator->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) {
|
||||
ldap_controls_free(controls);
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsILDAPControl> control = do_QueryInterface(isupports, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
ldap_controls_free(controls);
|
||||
return NS_ERROR_INVALID_ARG; // bogus element in the array
|
||||
}
|
||||
nsLDAPControl *ctl = static_cast<nsLDAPControl *>
|
||||
(static_cast<nsILDAPControl *>
|
||||
(control.get()));
|
||||
|
||||
// convert it to an LDAPControl structure placed in the new array
|
||||
rv = ctl->ToLDAPControl(&controls[i]);
|
||||
if (NS_FAILED(rv)) {
|
||||
ldap_controls_free(controls);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// on to the next element
|
||||
rv = enumerator->HasMoreElements(&moreElements);
|
||||
if (NS_FAILED(rv)) {
|
||||
ldap_controls_free(controls);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
*aArray = controls;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SearchExt(const nsACString& aBaseDn, int32_t aScope,
|
||||
const nsACString& aFilter,
|
||||
const nsACString &aAttributes,
|
||||
PRIntervalTime aTimeOut, int32_t aSizeLimit)
|
||||
{
|
||||
if (!mMessageListener) {
|
||||
NS_ERROR("nsLDAPOperation::SearchExt(): mMessageListener not set");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX add control logging
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPOperation::SearchExt(): called with aBaseDn = '%s'; "
|
||||
"aFilter = '%s'; aAttributes = %s; aSizeLimit = %d",
|
||||
PromiseFlatCString(aBaseDn).get(),
|
||||
PromiseFlatCString(aFilter).get(),
|
||||
PromiseFlatCString(aAttributes).get(), aSizeLimit));
|
||||
|
||||
LDAPControl **serverctls = 0;
|
||||
nsresult rv;
|
||||
if (mServerControls) {
|
||||
rv = convertControlArray(mServerControls, &serverctls);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Error,
|
||||
("nsLDAPOperation::SearchExt(): error converting server "
|
||||
"control array: %x", rv));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
LDAPControl **clientctls = 0;
|
||||
if (mClientControls) {
|
||||
rv = convertControlArray(mClientControls, &clientctls);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Error,
|
||||
("nsLDAPOperation::SearchExt(): error converting client "
|
||||
"control array: %x", rv));
|
||||
ldap_controls_free(serverctls);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert our comma separated string to one that the C-SDK will like, i.e.
|
||||
// convert to a char array and add a last NULL element.
|
||||
nsTArray<nsCString> attrArray;
|
||||
ParseString(aAttributes, ',', attrArray);
|
||||
char **attrs = nullptr;
|
||||
uint32_t origLength = attrArray.Length();
|
||||
if (origLength)
|
||||
{
|
||||
attrs = static_cast<char **> (NS_Alloc((origLength + 1) * sizeof(char *)));
|
||||
if (!attrs)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (uint32_t i = 0; i < origLength; ++i)
|
||||
attrs[i] = ToNewCString(attrArray[i]);
|
||||
|
||||
attrs[origLength] = 0;
|
||||
}
|
||||
|
||||
// XXX deal with timeout here
|
||||
int retVal = ldap_search_ext(mConnectionHandle,
|
||||
PromiseFlatCString(aBaseDn).get(),
|
||||
aScope, PromiseFlatCString(aFilter).get(),
|
||||
attrs, 0, serverctls, clientctls, 0,
|
||||
aSizeLimit, &mMsgID);
|
||||
|
||||
// clean up
|
||||
ldap_controls_free(serverctls);
|
||||
ldap_controls_free(clientctls);
|
||||
// The last entry is null, so no need to free that.
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(origLength, attrs);
|
||||
|
||||
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
|
||||
//
|
||||
rv = mConnection->AddPendingOperation(mMsgID, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
switch (rv) {
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
default:
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
NS_ERROR("nsLDAPOperation::SearchExt(): unexpected error in "
|
||||
"mConnection->AddPendingOperation");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::GetMessageID(int32_t *aMsgID)
|
||||
{
|
||||
if (!aMsgID) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aMsgID = mMsgID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// as far as I can tell from reading the LDAP C SDK code, abandoning something
|
||||
// that has already been abandoned does not return an error
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::AbandonExt()
|
||||
{
|
||||
nsresult rv;
|
||||
nsresult retStatus = NS_OK;
|
||||
|
||||
if (!mMessageListener || mMsgID == 0) {
|
||||
NS_ERROR("nsLDAPOperation::AbandonExt(): mMessageListener or "
|
||||
"mMsgId not initialized");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// XXX handle controls here
|
||||
if (mServerControls || mClientControls) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
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
|
||||
// succeeded (and there's nothing else the caller can reasonably do),
|
||||
// so we only pay attention to this in debug builds.
|
||||
//
|
||||
// check mConnection in case we're getting bit by
|
||||
// http://bugzilla.mozilla.org/show_bug.cgi?id=239729, wherein we
|
||||
// theorize that ::Clearing the operation is nulling out the mConnection
|
||||
// from another thread.
|
||||
if (mConnection)
|
||||
{
|
||||
rv = mConnection->RemovePendingOperation(mMsgID);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXXdmose should we keep AbandonExt from happening on multiple
|
||||
// threads at the same time? that's when this condition is most
|
||||
// likely to occur. i _think_ the LDAP C SDK is ok with this; need
|
||||
// to verify.
|
||||
//
|
||||
NS_WARNING("nsLDAPOperation::AbandonExt: "
|
||||
"mConnection->RemovePendingOperation(this) failed.");
|
||||
}
|
||||
}
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::GetClientControls(nsIMutableArray **aControls)
|
||||
{
|
||||
NS_IF_ADDREF(*aControls = mClientControls);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPOperation::SetClientControls(nsIMutableArray *aControls)
|
||||
{
|
||||
mClientControls = aControls;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPOperation::GetServerControls(nsIMutableArray **aControls)
|
||||
{
|
||||
NS_IF_ADDREF(*aControls = mServerControls);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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) {
|
||||
NS_ERROR("nsLDAPOperation::AddExt(): mMessageListener not set");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LDAPMod **attrs = 0;
|
||||
int retVal = LDAP_SUCCESS;
|
||||
uint32_t modCount = 0;
|
||||
nsresult rv = mods->GetLength(&modCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mods && modCount) {
|
||||
attrs = static_cast<LDAPMod **>(moz_xmalloc((modCount + 1) *
|
||||
sizeof(LDAPMod *)));
|
||||
if (!attrs) {
|
||||
NS_ERROR("nsLDAPOperation::AddExt: out of memory ");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoCString type;
|
||||
uint32_t 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
|
||||
int32_t operation;
|
||||
NS_ASSERTION(NS_SUCCEEDED(modif->GetOperation(&operation)) &&
|
||||
((operation & ~LDAP_MOD_BVALUES) == LDAP_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 (uint32_t counter = 0; counter < modCount; ++counter)
|
||||
delete attrs[counter];
|
||||
|
||||
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)
|
||||
{
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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 = mConnection->AddPendingOperation(mMsgID, this);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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) {
|
||||
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)
|
||||
{
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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 = mConnection->AddPendingOperation(mMsgID, this);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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) {
|
||||
NS_ERROR("nsLDAPOperation::ModifyExt(): mMessageListener not set");
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
LDAPMod **attrs = 0;
|
||||
int retVal = 0;
|
||||
uint32_t modCount = 0;
|
||||
nsresult rv = mods->GetLength(&modCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (modCount && mods) {
|
||||
attrs = static_cast<LDAPMod **>(moz_xmalloc((modCount + 1) *
|
||||
sizeof(LDAPMod *)));
|
||||
if (!attrs) {
|
||||
NS_ERROR("nsLDAPOperation::ModifyExt: out of memory ");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoCString type;
|
||||
uint32_t 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;
|
||||
|
||||
int32_t 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 (uint32_t counter = 0; counter < modCount; ++counter)
|
||||
delete attrs[counter];
|
||||
|
||||
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)
|
||||
{
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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 = mConnection->AddPendingOperation(mMsgID, this);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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,
|
||||
bool deleteOldRDn,
|
||||
LDAPControl **serverctrls,
|
||||
LDAPControl **clientctrls)
|
||||
{
|
||||
if (!mMessageListener) {
|
||||
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,
|
||||
bool aDeleteOldRDn)
|
||||
{
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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 = mConnection->AddPendingOperation(mMsgID, this);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
(void)ldap_abandon_ext(mConnectionHandle, mMsgID, 0, 0);
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::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);
|
||||
|
||||
uint32_t valuesCount;
|
||||
rv = values->GetLength(&valuesCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aBValues = static_cast<berval **>
|
||||
(moz_xmalloc((valuesCount + 1) *
|
||||
sizeof(berval *)));
|
||||
if (!*aBValues)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
uint32_t 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 (uint32_t counter = 0;
|
||||
counter < valueIndex && counter < valuesCount;
|
||||
++counter)
|
||||
delete (*aBValues)[valueIndex];
|
||||
|
||||
free(*aBValues);
|
||||
delete bval;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
value->Get((uint32_t*)&bval->bv_len,
|
||||
(uint8_t**)&bval->bv_val);
|
||||
(*aBValues)[valueIndex] = bval;
|
||||
}
|
||||
|
||||
(*aBValues)[valuesCount] = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
104
ldap/xpcom/src/nsLDAPOperation.h
Normal file
104
ldap/xpcom/src/nsLDAPOperation.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _nsLDAPOperation_h_
|
||||
#define _nsLDAPOperation_h_
|
||||
|
||||
#include "ldap.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsLDAPConnection.h"
|
||||
|
||||
// 97a479d0-9a44-47c6-a17a-87f9b00294bb
|
||||
#define NS_LDAPOPERATION_CID \
|
||||
{ 0x97a479d0, 0x9a44, 0x47c6, \
|
||||
{ 0xa1, 0x7a, 0x87, 0xf9, 0xb0, 0x02, 0x94, 0xbb}}
|
||||
|
||||
class nsLDAPOperation : public nsILDAPOperation
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPOPERATION
|
||||
|
||||
// constructor & destructor
|
||||
//
|
||||
nsLDAPOperation();
|
||||
|
||||
/**
|
||||
* used to break cycles
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
virtual ~nsLDAPOperation();
|
||||
|
||||
/**
|
||||
* 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
|
||||
bool 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)
|
||||
RefPtr<nsLDAPConnection> mConnection; // connection this op is on
|
||||
|
||||
LDAP *mConnectionHandle; // cache connection handle
|
||||
nsCString mSavePassword;
|
||||
nsCString mMechanism;
|
||||
nsCOMPtr<nsIAuthModule> mAuthModule;
|
||||
int32_t mMsgID; // opaque handle to outbound message for this op
|
||||
|
||||
nsCOMPtr<nsIMutableArray> mClientControls;
|
||||
nsCOMPtr<nsIMutableArray> mServerControls;
|
||||
};
|
||||
|
||||
#endif // _nsLDAPOperation_h
|
||||
62
ldap/xpcom/src/nsLDAPProtocolHandler.js
Normal file
62
ldap/xpcom/src/nsLDAPProtocolHandler.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const kNetworkProtocolCIDPrefix = "@mozilla.org/network/protocol;1?name=";
|
||||
const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
|
||||
|
||||
function makeProtocolHandler(aCID, aProtocol, aDefaultPort) {
|
||||
return {
|
||||
classID: Components.ID(aCID),
|
||||
QueryInterface: XPCOMUtils.generateQI([nsIProtocolHandler]),
|
||||
|
||||
scheme: aProtocol,
|
||||
defaultPort: aDefaultPort,
|
||||
protocolFlags: nsIProtocolHandler.URI_NORELATIVE |
|
||||
nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
|
||||
nsIProtocolHandler.ALLOWS_PROXY,
|
||||
|
||||
newURI: function (aSpec, aOriginCharset, aBaseURI) {
|
||||
var url = Components.classes["@mozilla.org/network/ldap-url;1"]
|
||||
.createInstance(Components.interfaces.nsIURI);
|
||||
|
||||
if (url instanceof Components.interfaces.nsILDAPURL)
|
||||
url.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD,
|
||||
aDefaultPort, aSpec, aOriginCharset, aBaseURI);
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
newChannel: function (aURI) {
|
||||
return this.newChannel2(aURI, null);
|
||||
},
|
||||
|
||||
newChannel2: function (aURI, aLoadInfo) {
|
||||
if ("@mozilla.org/network/ldap-channel;1" in Components.classes) {
|
||||
var channel = Components.classes["@mozilla.org/network/ldap-channel;1"]
|
||||
.createInstance(Components.interfaces.nsIChannel);
|
||||
channel.init(aURI);
|
||||
return channel;
|
||||
}
|
||||
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
allowPort: function (port, scheme) {
|
||||
return port == aDefaultPort;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function nsLDAPProtocolHandler() {}
|
||||
|
||||
nsLDAPProtocolHandler.prototype = makeProtocolHandler("{b3de9249-b0e5-4c12-8d91-c9a434fd80f5}", "ldap", 389);
|
||||
|
||||
function nsLDAPSProtocolHandler() {}
|
||||
|
||||
nsLDAPSProtocolHandler.prototype = makeProtocolHandler("{c85a5ef2-9c56-445f-b029-76889f2dd29b}", "ldaps", 636);
|
||||
|
||||
const NSGetFactory = XPCOMUtils.generateNSGetFactory([nsLDAPProtocolHandler,
|
||||
nsLDAPSProtocolHandler]);
|
||||
147
ldap/xpcom/src/nsLDAPProtocolModule.cpp
Normal file
147
ldap/xpcom/src/nsLDAPProtocolModule.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsLDAPURL.h"
|
||||
#include "nsLDAPConnection.h"
|
||||
#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"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
// use the default constructor
|
||||
//
|
||||
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(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
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPCONNECTION_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPOPERATION_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPMESSAGE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPMODIFICATION_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPSERVER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPURL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPBERVALUE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPBERELEMENT_CID);
|
||||
#ifdef MOZ_PREF_EXTENSIONS
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPSYNCQUERY_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_LDAPCONTROL_CID);
|
||||
|
||||
// a table of the CIDs implemented by this module
|
||||
//
|
||||
|
||||
const mozilla::Module::CIDEntry kLDAPProtocolCIDs[] = {
|
||||
{ &kNS_LDAPCONNECTION_CID, false, NULL, nsLDAPConnectionConstructor},
|
||||
{ &kNS_LDAPOPERATION_CID, false, NULL, nsLDAPOperationConstructor},
|
||||
{ &kNS_LDAPMESSAGE_CID, false, NULL, nsLDAPMessageConstructor},
|
||||
{ &kNS_LDAPMODIFICATION_CID, false, NULL, nsLDAPModificationConstructor},
|
||||
{ &kNS_LDAPSERVER_CID, false, NULL, nsLDAPServerConstructor},
|
||||
{ &kNS_LDAPSERVICE_CID, false, NULL, nsLDAPServiceConstructor},
|
||||
{ &kNS_LDAPURL_CID, false, NULL, nsLDAPURLConstructor},
|
||||
{ &kNS_LDAPBERVALUE_CID, false, NULL, nsLDAPBERValueConstructor},
|
||||
{ &kNS_LDAPBERELEMENT_CID, false, NULL, nsLDAPBERElementConstructor},
|
||||
#ifdef MOZ_PREF_EXTENSIONS
|
||||
{ &kNS_LDAPSYNCQUERY_CID, false, NULL, nsLDAPSyncQueryConstructor},
|
||||
#endif
|
||||
{ &kNS_LDAPCONTROL_CID, false, NULL, nsLDAPControlConstructor},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
const mozilla::Module::ContractIDEntry kLDAPProtocolContracts[] = {
|
||||
{ "@mozilla.org/network/ldap-connection;1", &kNS_LDAPCONNECTION_CID},
|
||||
{ "@mozilla.org/network/ldap-operation;1", &kNS_LDAPOPERATION_CID},
|
||||
{ "@mozilla.org/network/ldap-message;1", &kNS_LDAPMESSAGE_CID},
|
||||
{ "@mozilla.org/network/ldap-modification;1", &kNS_LDAPMODIFICATION_CID},
|
||||
{ "@mozilla.org/network/ldap-server;1", &kNS_LDAPSERVER_CID},
|
||||
{ "@mozilla.org/network/ldap-service;1", &kNS_LDAPSERVICE_CID},
|
||||
{ "@mozilla.org/network/ldap-url;1", &kNS_LDAPURL_CID},
|
||||
{ "@mozilla.org/network/ldap-ber-value;1", &kNS_LDAPBERVALUE_CID},
|
||||
{ "@mozilla.org/network/ldap-ber-element;1", &kNS_LDAPBERELEMENT_CID},
|
||||
#ifdef MOZ_PREF_EXTENSIONS
|
||||
{ "@mozilla.org/ldapsyncquery;1", &kNS_LDAPSYNCQUERY_CID},
|
||||
#endif
|
||||
{ "@mozilla.org/network/ldap-control;1", &kNS_LDAPCONTROL_CID},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static nsresult
|
||||
nsLDAPInitialize()
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
gLDAPLogModule = PR_NewLogModule("ldap");
|
||||
if (!gLDAPLogModule) {
|
||||
PR_fprintf(PR_STDERR,
|
||||
"nsLDAP_Initialize(): PR_NewLogModule() failed\n");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
#endif
|
||||
|
||||
// use NSPR under the hood for all networking
|
||||
//
|
||||
int rv = prldap_install_routines( NULL, 1 /* shared */ );
|
||||
|
||||
if (rv != LDAP_SUCCESS) {
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Error,
|
||||
("nsLDAPInitialize(): pr_ldap_install_routines() failed: %s\n",
|
||||
ldap_err2string(rv)));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Never block for more than 10000 milliseconds (ie 10 seconds) doing any
|
||||
// sort of I/O operation.
|
||||
//
|
||||
rv = prldap_set_session_option(0, 0, PRLDAP_OPT_IO_MAX_TIMEOUT,
|
||||
10000);
|
||||
if (rv != LDAP_SUCCESS) {
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Error,
|
||||
("nsLDAPInitialize(): error setting PRLDAP_OPT_IO_MAX_TIMEOUT:"
|
||||
" %s\n", ldap_err2string(rv)));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static const mozilla::Module kLDAPProtocolModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kLDAPProtocolCIDs,
|
||||
kLDAPProtocolContracts,
|
||||
NULL,
|
||||
NULL,
|
||||
nsLDAPInitialize,
|
||||
NULL
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(nsLDAPProtocolModule) = &kLDAPProtocolModule;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo *gLDAPLogModule = 0;
|
||||
#endif
|
||||
342
ldap/xpcom/src/nsLDAPSecurityGlue.cpp
Normal file
342
ldap/xpcom/src/nsLDAPSecurityGlue.cpp
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Only build this code if PSM is being built also
|
||||
//
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsISSLSocketControl.h"
|
||||
#include "nsString.h"
|
||||
#include "nsMemory.h"
|
||||
#include "plstr.h"
|
||||
#include "ldap.h"
|
||||
#include "ldappr.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
// LDAP per-session data structure.
|
||||
//
|
||||
typedef struct {
|
||||
char *hostname;
|
||||
LDAP_X_EXTIOF_CLOSE_CALLBACK *realClose;
|
||||
LDAP_X_EXTIOF_CONNECT_CALLBACK *realConnect;
|
||||
LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *realDisposeHandle;
|
||||
} nsLDAPSSLSessionClosure;
|
||||
|
||||
// LDAP per-socket data structure.
|
||||
//
|
||||
typedef struct {
|
||||
nsLDAPSSLSessionClosure *sessionClosure; /* session info */
|
||||
} nsLDAPSSLSocketClosure;
|
||||
|
||||
// free the per-socket data structure as necessary
|
||||
//
|
||||
static void
|
||||
nsLDAPSSLFreeSocketClosure(nsLDAPSSLSocketClosure **aClosure)
|
||||
{
|
||||
if (aClosure && *aClosure) {
|
||||
free(*aClosure);
|
||||
*aClosure = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Replacement close() function, which cleans up local stuff associated
|
||||
// with this socket, and then calls the real close function.
|
||||
//
|
||||
extern "C" int LDAP_CALLBACK
|
||||
nsLDAPSSLClose(int s, struct lextiof_socket_private *socketarg)
|
||||
{
|
||||
PRLDAPSocketInfo socketInfo;
|
||||
nsLDAPSSLSocketClosure *socketClosure;
|
||||
nsLDAPSSLSessionClosure *sessionClosure;
|
||||
|
||||
// get the socketInfo associated with this socket
|
||||
//
|
||||
memset(&socketInfo, 0, sizeof(socketInfo));
|
||||
socketInfo.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
|
||||
if (prldap_get_socket_info(s, socketarg, &socketInfo) != LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPSSLClose(): prldap_get_socket_info() failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// save off the session closure data in an automatic, since we're going to
|
||||
// need to call through it
|
||||
//
|
||||
socketClosure = reinterpret_cast<nsLDAPSSLSocketClosure *>
|
||||
(socketInfo.soinfo_appdata);
|
||||
sessionClosure = socketClosure->sessionClosure;
|
||||
|
||||
// free the socket closure data
|
||||
//
|
||||
nsLDAPSSLFreeSocketClosure(
|
||||
reinterpret_cast<nsLDAPSSLSocketClosure **>
|
||||
(&socketInfo.soinfo_appdata));
|
||||
|
||||
// call the real close function
|
||||
//
|
||||
return (*(sessionClosure->realClose))(s, socketarg);
|
||||
}
|
||||
|
||||
// Replacement connection function. Calls the real connect function,
|
||||
//
|
||||
extern "C" int LDAP_CALLBACK
|
||||
nsLDAPSSLConnect(const char *hostlist, int defport, int timeout,
|
||||
unsigned long options,
|
||||
struct lextiof_session_private *sessionarg,
|
||||
struct lextiof_socket_private **socketargp )
|
||||
{
|
||||
PRLDAPSocketInfo socketInfo;
|
||||
PRLDAPSessionInfo sessionInfo;
|
||||
nsLDAPSSLSocketClosure *socketClosure = nullptr;
|
||||
nsLDAPSSLSessionClosure *sessionClosure;
|
||||
int intfd = -1;
|
||||
nsCOMPtr <nsISupports> securityInfo;
|
||||
nsCOMPtr <nsISocketProvider> tlsSocketProvider;
|
||||
nsCOMPtr <nsISSLSocketControl> sslSocketControl;
|
||||
nsresult rv;
|
||||
|
||||
// Ensure secure option is set. Also, clear secure bit in options
|
||||
// the we pass to the standard connect() function (since it doesn't know
|
||||
// how to handle the secure option).
|
||||
//
|
||||
NS_ASSERTION(options & LDAP_X_EXTIOF_OPT_SECURE,
|
||||
"nsLDAPSSLConnect(): called for non-secure connection");
|
||||
options &= ~LDAP_X_EXTIOF_OPT_SECURE;
|
||||
|
||||
// Retrieve session info. so we can store a pointer to our session info.
|
||||
// in our socket info. later.
|
||||
//
|
||||
memset(&sessionInfo, 0, sizeof(sessionInfo));
|
||||
sessionInfo.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
|
||||
if (prldap_get_session_info(nullptr, sessionarg, &sessionInfo)
|
||||
!= LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPSSLConnect(): unable to get session info");
|
||||
return -1;
|
||||
}
|
||||
sessionClosure = reinterpret_cast<nsLDAPSSLSessionClosure *>
|
||||
(sessionInfo.seinfo_appdata);
|
||||
|
||||
// Call the real connect() callback to make the TCP connection. If it
|
||||
// succeeds, *socketargp is set.
|
||||
//
|
||||
intfd = (*(sessionClosure->realConnect))(hostlist, defport, timeout,
|
||||
options, sessionarg, socketargp);
|
||||
if ( intfd < 0 ) {
|
||||
PR_LOG(gLDAPLogModule, PR_LOG_DEBUG,
|
||||
("nsLDAPSSLConnect(): standard connect() function returned %d",
|
||||
intfd));
|
||||
return intfd;
|
||||
}
|
||||
|
||||
// Retrieve socket info from the newly created socket so that we
|
||||
// have the PRFileDesc onto which we will be layering SSL.
|
||||
//
|
||||
memset(&socketInfo, 0, sizeof(socketInfo));
|
||||
socketInfo.soinfo_size = PRLDAP_SOCKETINFO_SIZE;
|
||||
if (prldap_get_socket_info(intfd, *socketargp, &socketInfo)
|
||||
!= LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPSSLConnect(): unable to get socket info");
|
||||
goto close_socket_and_exit_with_error;
|
||||
}
|
||||
|
||||
// Allocate a structure to hold our socket-specific data.
|
||||
//
|
||||
socketClosure = static_cast<nsLDAPSSLSocketClosure *>(moz_xmalloc(
|
||||
sizeof(nsLDAPSSLSocketClosure)));
|
||||
if (!socketClosure) {
|
||||
NS_WARNING("nsLDAPSSLConnect(): unable to allocate socket closure");
|
||||
goto close_socket_and_exit_with_error;
|
||||
}
|
||||
memset(socketClosure, 0, sizeof(nsLDAPSSLSocketClosure));
|
||||
socketClosure->sessionClosure = sessionClosure;
|
||||
|
||||
// Add the NSPR layer for SSL provided by PSM to this socket.
|
||||
//
|
||||
tlsSocketProvider = do_GetService(NS_STARTTLSSOCKETPROVIDER_CONTRACTID,
|
||||
&rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPSSLConnect(): unable to get socket provider service");
|
||||
goto close_socket_and_exit_with_error;
|
||||
}
|
||||
// XXXdmose: Note that hostlist can be a list of hosts (in the
|
||||
// current XPCOM SDK code, it will always be a list of IP
|
||||
// addresses). Because of this, we need to use
|
||||
// sessionClosure->hostname which was passed in separately to tell
|
||||
// AddToSocket what to match the name in the certificate against.
|
||||
// What exactly happen will happen when this is used with some IP
|
||||
// address in the list other than the first one is not entirely
|
||||
// clear, and I suspect it may depend on the format of the name in
|
||||
// the certificate. Need to investigate.
|
||||
//
|
||||
rv = tlsSocketProvider->AddToSocket(PR_AF_INET,
|
||||
sessionClosure->hostname,
|
||||
defport,
|
||||
nullptr,
|
||||
mozilla::NeckoOriginAttributes(),
|
||||
0,
|
||||
socketInfo.soinfo_prfd,
|
||||
getter_AddRefs(securityInfo));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPSSLConnect(): unable to add SSL layer to socket");
|
||||
goto close_socket_and_exit_with_error;
|
||||
}
|
||||
|
||||
// If possible we want to avoid using SSLv2, as this can confuse
|
||||
// some directory servers (notably the netscape 4.1 ds). The only
|
||||
// way that PSM provides for us to do this is to use a socket that can
|
||||
// be used for the STARTTLS protocol, because the STARTTLS protocol disallows
|
||||
// the use of SSLv2.
|
||||
// (Thanks to Brian Ryner for helping figure this out).
|
||||
//
|
||||
sslSocketControl = do_QueryInterface(securityInfo, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsLDAPSSLConnect(): unable to QI to nsISSLSocketControl");
|
||||
} else {
|
||||
rv = sslSocketControl->StartTLS();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsLDAPSSLConnect(): StartTLS failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Attach our closure to the socketInfo.
|
||||
//
|
||||
socketInfo.soinfo_appdata = reinterpret_cast<prldap_socket_private *>
|
||||
(socketClosure);
|
||||
if (prldap_set_socket_info(intfd, *socketargp, &socketInfo)
|
||||
!= LDAP_SUCCESS ) {
|
||||
NS_ERROR("nsLDAPSSLConnect(): unable to set socket info");
|
||||
}
|
||||
return intfd; // success
|
||||
|
||||
close_socket_and_exit_with_error:
|
||||
if (socketInfo.soinfo_prfd) {
|
||||
PR_Close(socketInfo.soinfo_prfd);
|
||||
}
|
||||
if (socketClosure) {
|
||||
nsLDAPSSLFreeSocketClosure(&socketClosure);
|
||||
}
|
||||
if ( intfd >= 0 && *socketargp ) {
|
||||
(*(sessionClosure->realClose))(intfd, *socketargp);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
// Free data associated with this session (LDAP *) as necessary.
|
||||
//
|
||||
static void
|
||||
nsLDAPSSLFreeSessionClosure(nsLDAPSSLSessionClosure **aSessionClosure)
|
||||
{
|
||||
if (aSessionClosure && *aSessionClosure) {
|
||||
|
||||
// free the hostname
|
||||
//
|
||||
if ( (*aSessionClosure)->hostname ) {
|
||||
PL_strfree((*aSessionClosure)->hostname);
|
||||
(*aSessionClosure)->hostname = nullptr;
|
||||
}
|
||||
|
||||
// free the structure itself
|
||||
//
|
||||
free(*aSessionClosure);
|
||||
*aSessionClosure = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Replacement session handle disposal code. First cleans up our local
|
||||
// stuff, then calls the original session handle disposal function.
|
||||
//
|
||||
extern "C" void LDAP_CALLBACK
|
||||
nsLDAPSSLDisposeHandle(LDAP *ld, struct lextiof_session_private *sessionarg)
|
||||
{
|
||||
PRLDAPSessionInfo sessionInfo;
|
||||
nsLDAPSSLSessionClosure *sessionClosure;
|
||||
LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *disposehdl_fn;
|
||||
|
||||
memset(&sessionInfo, 0, sizeof(sessionInfo));
|
||||
sessionInfo.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
|
||||
if (prldap_get_session_info(ld, nullptr, &sessionInfo) == LDAP_SUCCESS) {
|
||||
sessionClosure = reinterpret_cast<nsLDAPSSLSessionClosure *>
|
||||
(sessionInfo.seinfo_appdata);
|
||||
disposehdl_fn = sessionClosure->realDisposeHandle;
|
||||
nsLDAPSSLFreeSessionClosure(&sessionClosure);
|
||||
(*disposehdl_fn)(ld, sessionarg);
|
||||
}
|
||||
}
|
||||
|
||||
// Installs appropriate routines and data for making this connection
|
||||
// handle SSL. The aHostName is ultimately passed to PSM and is used to
|
||||
// validate certificates.
|
||||
//
|
||||
nsresult
|
||||
nsLDAPInstallSSL( LDAP *ld, const char *aHostName)
|
||||
{
|
||||
struct ldap_x_ext_io_fns iofns;
|
||||
nsLDAPSSLSessionClosure *sessionClosure;
|
||||
PRLDAPSessionInfo sessionInfo;
|
||||
|
||||
// Allocate our own session information.
|
||||
//
|
||||
sessionClosure = static_cast<nsLDAPSSLSessionClosure *>(moz_xmalloc(
|
||||
sizeof(nsLDAPSSLSessionClosure)));
|
||||
if (!sessionClosure) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memset(sessionClosure, 0, sizeof(nsLDAPSSLSessionClosure));
|
||||
|
||||
// Override a few functions, saving a pointer to the original function
|
||||
// in each case so we can call it from our SSL savvy functions.
|
||||
//
|
||||
memset(&iofns, 0, sizeof(iofns));
|
||||
iofns.lextiof_size = LDAP_X_EXTIO_FNS_SIZE;
|
||||
if (ldap_get_option(ld, LDAP_X_OPT_EXTIO_FN_PTRS,
|
||||
static_cast<void *>(&iofns)) != LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPInstallSSL(): unexpected error getting"
|
||||
" LDAP_X_OPT_EXTIO_FN_PTRS");
|
||||
nsLDAPSSLFreeSessionClosure(&sessionClosure);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Make a copy of the hostname to pass to AddToSocket later
|
||||
//
|
||||
sessionClosure->hostname = PL_strdup(aHostName);
|
||||
if (!sessionClosure->hostname) {
|
||||
NS_ERROR("nsLDAPInstallSSL(): PL_strdup failed\n");
|
||||
nsLDAPSSLFreeSessionClosure(&sessionClosure);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Override functions
|
||||
//
|
||||
sessionClosure->realClose = iofns.lextiof_close;
|
||||
iofns.lextiof_close = nsLDAPSSLClose;
|
||||
sessionClosure->realConnect = iofns.lextiof_connect;
|
||||
iofns.lextiof_connect = nsLDAPSSLConnect;
|
||||
sessionClosure->realDisposeHandle = iofns.lextiof_disposehandle;
|
||||
iofns.lextiof_disposehandle = nsLDAPSSLDisposeHandle;
|
||||
|
||||
if (ldap_set_option(ld, LDAP_X_OPT_EXTIO_FN_PTRS,
|
||||
static_cast<void *>(&iofns)) != LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPInstallSSL(): error setting LDAP_X_OPT_EXTIO_FN_PTRS");
|
||||
nsLDAPSSLFreeSessionClosure(&sessionClosure);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Store session info. for later retrieval.
|
||||
//
|
||||
sessionInfo.seinfo_size = PRLDAP_SESSIONINFO_SIZE;
|
||||
sessionInfo.seinfo_appdata = reinterpret_cast<prldap_session_private *>
|
||||
(sessionClosure);
|
||||
if (prldap_set_session_info(ld, nullptr, &sessionInfo) != LDAP_SUCCESS) {
|
||||
NS_ERROR("nsLDAPInstallSSL(): error setting prldap session info");
|
||||
free(sessionClosure);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
133
ldap/xpcom/src/nsLDAPServer.cpp
Normal file
133
ldap/xpcom/src/nsLDAPServer.cpp
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPServer.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPServer, nsILDAPServer)
|
||||
|
||||
nsLDAPServer::nsLDAPServer()
|
||||
: mSizeLimit(0),
|
||||
mProtocolVersion(nsILDAPConnection::VERSION3)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPServer::~nsLDAPServer()
|
||||
{
|
||||
}
|
||||
|
||||
// attribute wstring key;
|
||||
NS_IMETHODIMP nsLDAPServer::GetKey(char16_t **_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPServer::GetKey: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*_retval = ToNewUnicode(mKey);
|
||||
if (!*_retval) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetKey(const char16_t *aKey)
|
||||
{
|
||||
mKey = aKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute AUTF8String username;
|
||||
NS_IMETHODIMP nsLDAPServer::GetUsername(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mUsername);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetUsername(const nsACString& aUsername)
|
||||
{
|
||||
mUsername.Assign(aUsername);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute AUTF8String password;
|
||||
NS_IMETHODIMP nsLDAPServer::GetPassword(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mPassword);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetPassword(const nsACString& aPassword)
|
||||
{
|
||||
mPassword.Assign(aPassword);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute AUTF8String binddn;
|
||||
NS_IMETHODIMP nsLDAPServer::GetBinddn(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mBindDN);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetBinddn(const nsACString& aBindDN)
|
||||
{
|
||||
mBindDN.Assign(aBindDN);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute unsigned long sizelimit;
|
||||
NS_IMETHODIMP nsLDAPServer::GetSizelimit(uint32_t *_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPServer::GetSizelimit: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*_retval = mSizeLimit;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetSizelimit(uint32_t aSizeLimit)
|
||||
{
|
||||
mSizeLimit = aSizeLimit;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute nsILDAPURL url;
|
||||
NS_IMETHODIMP nsLDAPServer::GetUrl(nsILDAPURL **_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPServer::GetUrl: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*_retval = mURL);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetUrl(nsILDAPURL *aURL)
|
||||
{
|
||||
mURL = aURL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// attribute long protocolVersion
|
||||
NS_IMETHODIMP nsLDAPServer::GetProtocolVersion(uint32_t *_retval)
|
||||
{
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPServer::GetProtocolVersion: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
*_retval = mProtocolVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPServer::SetProtocolVersion(uint32_t aVersion)
|
||||
{
|
||||
if (aVersion != nsILDAPConnection::VERSION2 &&
|
||||
aVersion != nsILDAPConnection::VERSION3) {
|
||||
NS_ERROR("nsLDAPServer::SetProtocolVersion: invalid version");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
mProtocolVersion = aVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
39
ldap/xpcom/src/nsLDAPServer.h
Normal file
39
ldap/xpcom/src/nsLDAPServer.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsILDAPServer.h"
|
||||
#include "nsILDAPURL.h"
|
||||
|
||||
// 8bbbaa54-f316-4271-87c3-d52b5b1c1f5b
|
||||
#define NS_LDAPSERVER_CID \
|
||||
{ 0x8bbbaa54, 0xf316, 0x4271, \
|
||||
{ 0x87, 0xc3, 0xd5, 0x2b, 0x5b, 0x1c, 0x1f, 0x5b}}
|
||||
|
||||
class nsLDAPServer : public nsILDAPServer
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPSERVER
|
||||
|
||||
// Constructor & destructor
|
||||
//
|
||||
nsLDAPServer();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPServer();
|
||||
|
||||
nsString mKey; // Unique identifier for this server object
|
||||
nsCString mUsername; // Username / UID
|
||||
nsCString mPassword; // Password to bind with
|
||||
nsCString mBindDN; // DN associated with the UID above
|
||||
uint32_t mSizeLimit; // Limit the LDAP search to this # of entries
|
||||
uint32_t mProtocolVersion; // What version of LDAP to use?
|
||||
// This "links" to a LDAP URL object, which holds further information
|
||||
// related to the LDAP server. Like Host, port, base-DN and scope.
|
||||
nsCOMPtr<nsILDAPURL> mURL;
|
||||
};
|
||||
985
ldap/xpcom/src/nsLDAPService.cpp
Normal file
985
ldap/xpcom/src/nsLDAPService.cpp
Normal file
|
|
@ -0,0 +1,985 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPInternal.h"
|
||||
#include "nsLDAPService.h"
|
||||
#include "nsLDAPConnection.h"
|
||||
#include "nsLDAPOperation.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// Constants for CIDs used here.
|
||||
//
|
||||
static NS_DEFINE_CID(kLDAPConnectionCID, NS_LDAPCONNECTION_CID);
|
||||
static NS_DEFINE_CID(kLDAPOperationCID, NS_LDAPOPERATION_CID);
|
||||
|
||||
// First we provide all the methods for the "local" class
|
||||
// nsLDAPServiceEntry.
|
||||
//
|
||||
|
||||
// constructor
|
||||
//
|
||||
nsLDAPServiceEntry::nsLDAPServiceEntry()
|
||||
: mLeases(0),
|
||||
mTimestamp(0),
|
||||
mDelete(false),
|
||||
mRebinding(false)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
// Init function
|
||||
//
|
||||
bool nsLDAPServiceEntry::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set/Get the timestamp when this server was last used. We might have
|
||||
// to use an "interval" here instead, see Bug #76887.
|
||||
//
|
||||
PRTime nsLDAPServiceEntry::GetTimestamp()
|
||||
{
|
||||
return mTimestamp;
|
||||
}
|
||||
void nsLDAPServiceEntry::SetTimestamp()
|
||||
{
|
||||
mTimestamp = PR_Now();
|
||||
}
|
||||
|
||||
|
||||
// Increment, decrement and Get the leases. This code might go away
|
||||
// with bug #75954.
|
||||
//
|
||||
void nsLDAPServiceEntry::IncrementLeases()
|
||||
{
|
||||
mLeases++;
|
||||
}
|
||||
bool nsLDAPServiceEntry::DecrementLeases()
|
||||
{
|
||||
if (!mLeases) {
|
||||
return false;
|
||||
}
|
||||
mLeases--;
|
||||
|
||||
return true;
|
||||
}
|
||||
uint32_t nsLDAPServiceEntry::GetLeases()
|
||||
{
|
||||
return mLeases;
|
||||
}
|
||||
|
||||
// Get/Set the nsLDAPServer object for this entry.
|
||||
//
|
||||
already_AddRefed<nsILDAPServer> nsLDAPServiceEntry::GetServer()
|
||||
{
|
||||
nsCOMPtr<nsILDAPServer> server = mServer;
|
||||
return server.forget();
|
||||
}
|
||||
bool nsLDAPServiceEntry::SetServer(nsILDAPServer *aServer)
|
||||
{
|
||||
if (!aServer) {
|
||||
return false;
|
||||
}
|
||||
mServer = aServer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get/Set/Clear the nsLDAPConnection object for this entry.
|
||||
//
|
||||
already_AddRefed<nsILDAPConnection> nsLDAPServiceEntry::GetConnection()
|
||||
{
|
||||
nsCOMPtr<nsILDAPConnection> conn = mConnection;
|
||||
return conn.forget();
|
||||
}
|
||||
void nsLDAPServiceEntry::SetConnection(nsILDAPConnection *aConnection)
|
||||
{
|
||||
mConnection = aConnection;
|
||||
}
|
||||
|
||||
// Get/Set the nsLDAPMessage object for this entry (it's a "cache").
|
||||
//
|
||||
already_AddRefed<nsILDAPMessage> nsLDAPServiceEntry::GetMessage()
|
||||
{
|
||||
nsCOMPtr<nsILDAPMessage> message = mMessage;
|
||||
return message.forget();
|
||||
}
|
||||
void nsLDAPServiceEntry::SetMessage(nsILDAPMessage *aMessage)
|
||||
{
|
||||
mMessage = aMessage;
|
||||
}
|
||||
|
||||
// Push/Pop pending listeners/callback for this server entry. This is
|
||||
// implemented as a "stack" on top of the nsCOMArray, since we can
|
||||
// potentially have more than one listener waiting for the connection
|
||||
// to be available for consumption.
|
||||
//
|
||||
already_AddRefed<nsILDAPMessageListener> nsLDAPServiceEntry::PopListener()
|
||||
{
|
||||
if (mListeners.IsEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILDAPMessageListener> listener = mListeners[0];
|
||||
mListeners.RemoveObjectAt(0);
|
||||
return listener.forget();
|
||||
}
|
||||
bool nsLDAPServiceEntry::PushListener(nsILDAPMessageListener *listener)
|
||||
{
|
||||
return mListeners.AppendObject(listener);
|
||||
}
|
||||
|
||||
// Mark this server to currently be rebinding. This is to avoid a
|
||||
// race condition where multiple consumers could potentially request
|
||||
// to reconnect the connection.
|
||||
//
|
||||
bool nsLDAPServiceEntry::IsRebinding()
|
||||
{
|
||||
return mRebinding;
|
||||
}
|
||||
void nsLDAPServiceEntry::SetRebinding(bool aState)
|
||||
{
|
||||
mRebinding = aState;
|
||||
}
|
||||
|
||||
// Mark a service entry for deletion, this is "dead" code right now,
|
||||
// see bug #75966.
|
||||
//
|
||||
bool nsLDAPServiceEntry::DeleteEntry()
|
||||
{
|
||||
mDelete = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
// This is the end of the nsLDAPServiceEntry class
|
||||
|
||||
|
||||
// Here begins the implementation for nsLDAPService
|
||||
//
|
||||
NS_IMPL_ISUPPORTS(nsLDAPService,
|
||||
nsILDAPService,
|
||||
nsILDAPMessageListener)
|
||||
|
||||
|
||||
// constructor
|
||||
//
|
||||
nsLDAPService::nsLDAPService()
|
||||
: mLock("nsLDAPService.mLock")
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
//
|
||||
nsLDAPService::~nsLDAPService()
|
||||
{
|
||||
}
|
||||
|
||||
// Initializer
|
||||
//
|
||||
nsresult nsLDAPService::Init()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void addServer (in nsILDAPServer aServer);
|
||||
NS_IMETHODIMP nsLDAPService::AddServer(nsILDAPServer *aServer)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
nsString key;
|
||||
nsresult rv;
|
||||
|
||||
if (!aServer) {
|
||||
NS_ERROR("nsLDAPService::AddServer: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// Set up the hash key for the server entry
|
||||
//
|
||||
rv = aServer->GetKey(getter_Copies(key));
|
||||
if (NS_FAILED(rv)) {
|
||||
// Only pass along errors we are aware of
|
||||
if ((rv == NS_ERROR_OUT_OF_MEMORY) || (rv == NS_ERROR_NULL_POINTER))
|
||||
return rv;
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Create the new service server entry, and add it into the hash table
|
||||
//
|
||||
entry = new nsLDAPServiceEntry;
|
||||
if (!entry) {
|
||||
NS_ERROR("nsLDAPService::AddServer: out of memory ");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (!entry->Init()) {
|
||||
delete entry;
|
||||
NS_ERROR("nsLDAPService::AddServer: out of memory ");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!entry->SetServer(aServer)) {
|
||||
delete entry;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We increment the refcount here for the server entry, when
|
||||
// we purge a server completely from the service (TBD), we
|
||||
// need to decrement the counter as well.
|
||||
//
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (mServers.Get(key)) {
|
||||
// Collision detected, lets just throw away this service entry
|
||||
// and keep the old one.
|
||||
//
|
||||
delete entry;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mServers.Put(key, entry);
|
||||
}
|
||||
NS_ADDREF(aServer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void deleteServer (in wstring aKey);
|
||||
NS_IMETHODIMP nsLDAPService::DeleteServer(const char16_t *aKey)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
// We should probably rename the key for this entry now that it's
|
||||
// "deleted", so that we can add in a new one with the same ID.
|
||||
// This is bug #77669.
|
||||
//
|
||||
mServers.Get(nsDependentString(aKey), &entry);
|
||||
if (entry) {
|
||||
if (entry->GetLeases() > 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
entry->DeleteEntry();
|
||||
} else {
|
||||
// There is no Server entry for this key
|
||||
//
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsILDAPServer getServer (in wstring aKey);
|
||||
NS_IMETHODIMP nsLDAPService::GetServer(const char16_t *aKey,
|
||||
nsILDAPServer **_retval)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPService::GetServer: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry)) {
|
||||
*_retval = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!(*_retval = entry->GetServer().take())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//void requestConnection (in wstring aKey,
|
||||
// in nsILDAPMessageListener aMessageListener);
|
||||
NS_IMETHODIMP nsLDAPService::RequestConnection(const char16_t *aKey,
|
||||
nsILDAPMessageListener *aListener)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
nsCOMPtr<nsILDAPConnection> conn;
|
||||
nsCOMPtr<nsILDAPMessage> message;
|
||||
nsresult rv;
|
||||
|
||||
if (!aListener) {
|
||||
NS_ERROR("nsLDAPService::RequestConection: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// Try to find a possibly cached connection and LDAP message.
|
||||
//
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
entry->SetTimestamp();
|
||||
|
||||
conn = entry->GetConnection();
|
||||
message = entry->GetMessage();
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
if (message) {
|
||||
// We already have the connection, and the message, ready to
|
||||
// be used. This might be confusing, since we actually call
|
||||
// the listener before this function returns, see bug #75899.
|
||||
//
|
||||
aListener->OnLDAPMessage(message);
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
rv = EstablishConnection(entry, aListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We got a new connection, now push the listeners on our stack,
|
||||
// until we get the LDAP message back.
|
||||
//
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry) ||
|
||||
!entry->PushListener(static_cast<nsILDAPMessageListener *>
|
||||
(aListener))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsILDAPConnection getConnection (in wstring aKey);
|
||||
NS_IMETHODIMP nsLDAPService::GetConnection(const char16_t *aKey,
|
||||
nsILDAPConnection **_retval)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!_retval) {
|
||||
NS_ERROR("nsLDAPService::GetConnection: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry)) {
|
||||
*_retval = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
entry->SetTimestamp();
|
||||
entry->IncrementLeases();
|
||||
if (!(*_retval = entry->GetConnection().take())){
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void releaseConnection (in wstring aKey);
|
||||
NS_IMETHODIMP nsLDAPService::ReleaseConnection(const char16_t *aKey)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (entry->GetLeases() > 0) {
|
||||
entry->SetTimestamp();
|
||||
entry->DecrementLeases();
|
||||
} else {
|
||||
// Releasing a non-leased connection is currently a No-Op.
|
||||
//
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void reconnectConnection (in wstring aKey,
|
||||
// in nsILDAPMessageListener aMessageListener);
|
||||
NS_IMETHODIMP nsLDAPService::ReconnectConnection(const char16_t *aKey,
|
||||
nsILDAPMessageListener *aListener)
|
||||
{
|
||||
nsLDAPServiceEntry *entry;
|
||||
nsresult rv;
|
||||
|
||||
if (!aListener) {
|
||||
NS_ERROR("nsLDAPService::ReconnectConnection: null pointer ");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!mServers.Get(nsDependentString(aKey), &entry)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
entry->SetTimestamp();
|
||||
|
||||
if (entry->IsRebinding()) {
|
||||
if (!entry->PushListener(aListener)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clear the old connection and message, which should get garbaged
|
||||
// collected now. We mark this as being "rebinding" now, and it
|
||||
// we be marked as finished either if there's an error condition,
|
||||
// or if the OnLDAPMessage() method gets called (i.e. bind() done).
|
||||
//
|
||||
entry->SetMessage(0);
|
||||
entry->SetConnection(0);
|
||||
|
||||
// Get a new connection
|
||||
//
|
||||
entry->SetRebinding(true);
|
||||
}
|
||||
|
||||
rv = EstablishConnection(entry, aListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!entry->PushListener(static_cast<nsILDAPMessageListener *>
|
||||
(aListener))) {
|
||||
entry->SetRebinding(false);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Messages received are passed back via this function.
|
||||
*
|
||||
* @arg aMessage The message that was returned, 0 if none was.
|
||||
*
|
||||
* void OnLDAPMessage (in nsILDAPMessage aMessage)
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsLDAPService::OnLDAPMessage(nsILDAPMessage *aMessage)
|
||||
{
|
||||
nsCOMPtr<nsILDAPOperation> operation;
|
||||
nsCOMPtr<nsILDAPConnection> connection;
|
||||
int32_t messageType;
|
||||
|
||||
// XXXleif: NULL messages are supposedly allowed, but the semantics
|
||||
// are not definted (yet?). This is something to look out for...
|
||||
//
|
||||
|
||||
|
||||
// figure out what sort of message was returned
|
||||
//
|
||||
nsresult rv = aMessage->GetType(&messageType);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPService::OnLDAPMessage(): unexpected error in "
|
||||
"nsLDAPMessage::GetType()");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
switch (messageType) {
|
||||
case LDAP_RES_BIND:
|
||||
// a bind has completed
|
||||
//
|
||||
rv = aMessage->GetOperation(getter_AddRefs(operation));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPService::OnLDAPMessage(): unexpected error in "
|
||||
"nsLDAPMessage::GetOperation()");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = operation->GetConnection(getter_AddRefs(connection));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPService::OnLDAPMessage(): unexpected error in "
|
||||
"nsLDAPOperation::GetConnection()");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Now we have the connection, lets find the corresponding
|
||||
// server entry in the Service.
|
||||
//
|
||||
{
|
||||
nsCOMPtr<nsILDAPMessageListener> listener;
|
||||
nsCOMPtr<nsILDAPMessage> message;
|
||||
nsLDAPServiceEntry *entry;
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!mConnections.Get(connection, &entry)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
message = entry->GetMessage();
|
||||
if (message) {
|
||||
// We already have a message, lets keep that one.
|
||||
//
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
entry->SetRebinding(false);
|
||||
entry->SetMessage(aMessage);
|
||||
|
||||
// Now process all the pending callbacks/listeners. We
|
||||
// have to make sure to unlock before calling a listener,
|
||||
// since it's likely to call back into us again.
|
||||
//
|
||||
while ((listener = entry->PopListener())) {
|
||||
MutexAutoUnlock unlock(mLock);
|
||||
listener->OnLDAPMessage(aMessage);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_WARNING("nsLDAPService::OnLDAPMessage(): unexpected LDAP message "
|
||||
"received");
|
||||
|
||||
// get the console service so we can log a message
|
||||
//
|
||||
nsCOMPtr<nsIConsoleService> consoleSvc =
|
||||
do_GetService("@mozilla.org/consoleservice;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPChannel::OnLDAPMessage() couldn't get console "
|
||||
"service");
|
||||
break;
|
||||
}
|
||||
|
||||
// log the message
|
||||
//
|
||||
rv = consoleSvc->LogStringMessage(
|
||||
NS_LITERAL_STRING("LDAP: WARNING: nsLDAPService::OnLDAPMessage(): Unexpected LDAP message received").get());
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "nsLDAPService::OnLDAPMessage(): "
|
||||
"consoleSvc->LogStringMessage() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void onLDAPInit (in nsILDAPConnection aConn, in nsresult aStatus); */
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPService::OnLDAPInit(nsILDAPConnection *aConn, nsresult aStatus)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Helper function to establish an LDAP connection properly.
|
||||
//
|
||||
nsresult
|
||||
nsLDAPService::EstablishConnection(nsLDAPServiceEntry *aEntry,
|
||||
nsILDAPMessageListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsILDAPOperation> operation;
|
||||
nsCOMPtr<nsILDAPServer> server;
|
||||
nsCOMPtr<nsILDAPURL> url;
|
||||
nsCOMPtr<nsILDAPConnection> conn, conn2;
|
||||
nsCOMPtr<nsILDAPMessage> message;
|
||||
nsAutoCString binddn;
|
||||
nsAutoCString password;
|
||||
uint32_t protocolVersion;
|
||||
nsresult rv;
|
||||
|
||||
server = aEntry->GetServer();
|
||||
if (!server) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get username, password, and protocol version from the server entry.
|
||||
//
|
||||
rv = server->GetBinddn(binddn);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = server->GetPassword(password);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = server->GetProtocolVersion(&protocolVersion);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get the host and port out of the URL, which is in the server entry.
|
||||
//
|
||||
rv = server->GetUrl(getter_AddRefs(url));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Create a new connection for this server.
|
||||
//
|
||||
conn = do_CreateInstance(kLDAPConnectionCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPService::EstablishConnection(): could not create "
|
||||
"@mozilla.org/network/ldap-connection;1");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = conn->Init(url, binddn, this, nullptr, protocolVersion);
|
||||
if (NS_FAILED(rv)) {
|
||||
switch (rv) {
|
||||
// Only pass along errors we are aware of
|
||||
//
|
||||
case NS_ERROR_OUT_OF_MEMORY:
|
||||
case NS_ERROR_NOT_AVAILABLE:
|
||||
case NS_ERROR_FAILURE:
|
||||
return rv;
|
||||
|
||||
case NS_ERROR_ILLEGAL_VALUE:
|
||||
default:
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to detect a collision, i.e. someone established a connection
|
||||
// just before we did. If so, we drop ours. This code is somewhat
|
||||
// similar to what happens in RequestConnection(), i.e. we try to
|
||||
// call the listener directly if possible, and if not, push it on
|
||||
// the stack of pending requests.
|
||||
//
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
conn2 = aEntry->GetConnection();
|
||||
message = aEntry->GetMessage();
|
||||
}
|
||||
|
||||
if (conn2) {
|
||||
// Drop the new connection, we can't use it.
|
||||
//
|
||||
conn = nullptr;
|
||||
if (message) {
|
||||
aListener->OnLDAPMessage(message);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!aEntry->PushListener(static_cast<nsILDAPMessageListener *>
|
||||
(aListener))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We made the connection, lets store it to the server entry,
|
||||
// and also update the reverse lookup tables (for finding the
|
||||
// server entry related to a particular connection).
|
||||
//
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
aEntry->SetConnection(conn);
|
||||
mConnections.Put(conn, aEntry);
|
||||
}
|
||||
|
||||
// Setup the bind() operation.
|
||||
//
|
||||
operation = do_CreateInstance(kLDAPOperationCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = operation->Init(conn, this, nullptr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_UNEXPECTED; // this should never happen
|
||||
}
|
||||
|
||||
// Start a bind operation
|
||||
//
|
||||
// Here we need to support the password, see bug #75990
|
||||
//
|
||||
rv = operation->SimpleBind(password);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Only pass along errors we are aware of
|
||||
if ((rv == NS_ERROR_LDAP_ENCODING_ERROR) ||
|
||||
(rv == NS_ERROR_FAILURE) ||
|
||||
(rv == NS_ERROR_OUT_OF_MEMORY))
|
||||
return rv;
|
||||
else
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* AString createFilter (in unsigned long aMaxSize, in AString aPattern, in AString aPrefix, in AString aSuffix, in AString aAttr, in AString aValue); */
|
||||
NS_IMETHODIMP nsLDAPService::CreateFilter(uint32_t aMaxSize,
|
||||
const nsACString & aPattern,
|
||||
const nsACString & aPrefix,
|
||||
const nsACString & aSuffix,
|
||||
const nsACString & aAttr,
|
||||
const nsACString & aValue,
|
||||
nsACString & _retval)
|
||||
{
|
||||
if (!aMaxSize) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// figure out how big of an array we're going to need for the tokens,
|
||||
// including a trailing NULL, and allocate space for it.
|
||||
//
|
||||
const char *iter = aValue.BeginReading();
|
||||
const char *iterEnd = aValue.EndReading();
|
||||
uint32_t numTokens = CountTokens(iter, iterEnd);
|
||||
char **valueWords;
|
||||
valueWords = static_cast<char **>(moz_xmalloc((numTokens + 1) *
|
||||
sizeof(char *)));
|
||||
if (!valueWords) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// build the array of values
|
||||
//
|
||||
uint32_t curToken = 0;
|
||||
while (iter != iterEnd && curToken < numTokens ) {
|
||||
valueWords[curToken] = NextToken(&iter, &iterEnd);
|
||||
if ( !valueWords[curToken] ) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(curToken, valueWords);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
curToken++;
|
||||
}
|
||||
valueWords[numTokens] = 0; // end of array signal to LDAP C SDK
|
||||
|
||||
// make buffer to be used for construction
|
||||
//
|
||||
char *buffer = static_cast<char *>(moz_xmalloc(aMaxSize * sizeof(char)));
|
||||
if (!buffer) {
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numTokens, valueWords);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// create the filter itself
|
||||
//
|
||||
nsresult rv;
|
||||
int result = ldap_create_filter(buffer, aMaxSize,
|
||||
const_cast<char *>(PromiseFlatCString(aPattern).get()),
|
||||
const_cast<char *>(PromiseFlatCString(aPrefix).get()),
|
||||
const_cast<char *>(PromiseFlatCString(aSuffix).get()),
|
||||
const_cast<char *>(PromiseFlatCString(aAttr).get()),
|
||||
const_cast<char *>(PromiseFlatCString(aValue).get()),
|
||||
valueWords);
|
||||
switch (result) {
|
||||
case LDAP_SUCCESS:
|
||||
rv = NS_OK;
|
||||
break;
|
||||
|
||||
case LDAP_SIZELIMIT_EXCEEDED:
|
||||
MOZ_LOG(gLDAPLogModule, mozilla::LogLevel::Debug,
|
||||
("nsLDAPService::CreateFilter(): "
|
||||
"filter longer than max size of %d generated",
|
||||
aMaxSize));
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
break;
|
||||
|
||||
case LDAP_PARAM_ERROR:
|
||||
rv = NS_ERROR_INVALID_ARG;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("nsLDAPService::CreateFilter(): ldap_create_filter() "
|
||||
"returned unexpected error");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
|
||||
_retval.Assign(buffer);
|
||||
|
||||
// done with the array and the buffer
|
||||
//
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numTokens, valueWords);
|
||||
free(buffer);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Parse a distinguished name (DN) and returns the relative DN,
|
||||
// base DN and the list of attributes that make up the relative DN.
|
||||
NS_IMETHODIMP nsLDAPService::ParseDn(const char *aDn,
|
||||
nsACString &aRdn,
|
||||
nsACString &aBaseDn,
|
||||
uint32_t *aRdnCount,
|
||||
char ***aRdnAttrs)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRdnCount);
|
||||
NS_ENSURE_ARG_POINTER(aRdnAttrs);
|
||||
|
||||
// explode the DN
|
||||
char **dnComponents = ldap_explode_dn(aDn, 0);
|
||||
if (!dnComponents) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: parsing DN failed");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// count DN components
|
||||
if (!*dnComponents || !*(dnComponents + 1)) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: DN has too few components");
|
||||
ldap_value_free(dnComponents);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// get the base DN
|
||||
nsAutoCString baseDn(nsDependentCString(*(dnComponents + 1)));
|
||||
for (char **component = dnComponents + 2; *component; ++component) {
|
||||
baseDn.AppendLiteral(",");
|
||||
baseDn.Append(nsDependentCString(*component));
|
||||
}
|
||||
|
||||
// explode the RDN
|
||||
char **rdnComponents = ldap_explode_rdn(*dnComponents, 0);
|
||||
if (!rdnComponents) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: parsing RDN failed");
|
||||
ldap_value_free(dnComponents);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// count RDN attributes
|
||||
uint32_t rdnCount = 0;
|
||||
for (char **component = rdnComponents; *component; ++component)
|
||||
++rdnCount;
|
||||
if (rdnCount < 1) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: RDN has too few components");
|
||||
ldap_value_free(dnComponents);
|
||||
ldap_value_free(rdnComponents);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// get the RDN attribute names
|
||||
char **attrNameArray = static_cast<char **>(
|
||||
moz_xmalloc(rdnCount * sizeof(char *)));
|
||||
if (!attrNameArray) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: out of memory ");
|
||||
ldap_value_free(dnComponents);
|
||||
ldap_value_free(rdnComponents);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
uint32_t index = 0;
|
||||
for (char **component = rdnComponents; *component; ++component) {
|
||||
uint32_t len = 0;
|
||||
char *p;
|
||||
for (p = *component; *p != '\0' && *p != '='; ++p)
|
||||
++len;
|
||||
if (*p != '=') {
|
||||
NS_ERROR("nsLDAPService::parseDn: "
|
||||
"could not find '=' in RDN component");
|
||||
ldap_value_free(dnComponents);
|
||||
ldap_value_free(rdnComponents);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (!(attrNameArray[index] = (char*)NS_Alloc(len + 1))) {
|
||||
NS_ERROR("nsLDAPService::ParseDn: out of memory ");
|
||||
ldap_value_free(dnComponents);
|
||||
ldap_value_free(rdnComponents);
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(index, attrNameArray);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(attrNameArray[index], *component, len);
|
||||
*(attrNameArray[index] + len) = '\0';
|
||||
++index;
|
||||
}
|
||||
|
||||
// perform assignments
|
||||
aRdn.Assign(*dnComponents);
|
||||
aBaseDn.Assign(baseDn);
|
||||
*aRdnCount = rdnCount;
|
||||
*aRdnAttrs = attrNameArray;
|
||||
|
||||
ldap_value_free(dnComponents);
|
||||
ldap_value_free(rdnComponents);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Count the number of space-separated tokens between aIter and aIterEnd
|
||||
//
|
||||
uint32_t
|
||||
nsLDAPService::CountTokens(const char *aIter,
|
||||
const char *aIterEnd)
|
||||
{
|
||||
uint32_t count(0);
|
||||
|
||||
// keep iterating through the string until we hit the end
|
||||
//
|
||||
while (aIter != aIterEnd) {
|
||||
|
||||
// move past any leading spaces
|
||||
//
|
||||
while (aIter != aIterEnd &&
|
||||
ldap_utf8isspace(const_cast<char *>(aIter))){
|
||||
++aIter;
|
||||
}
|
||||
|
||||
// move past all chars in this token
|
||||
//
|
||||
while (aIter != aIterEnd) {
|
||||
|
||||
if (ldap_utf8isspace(const_cast<char *>(aIter))) {
|
||||
++count; // token finished; increment the count
|
||||
++aIter; // move past the space
|
||||
break;
|
||||
}
|
||||
|
||||
++aIter; // move to next char
|
||||
|
||||
// if we've hit the end of this token and the end of this
|
||||
// iterator simultaneous, be sure to bump the count, since we're
|
||||
// never gonna hit the IsAsciiSpace where it's normally done.
|
||||
//
|
||||
if (aIter == aIterEnd) {
|
||||
++count;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// return the next token in this iterator
|
||||
//
|
||||
char*
|
||||
nsLDAPService::NextToken(const char **aIter,
|
||||
const char **aIterEnd)
|
||||
{
|
||||
// move past any leading whitespace
|
||||
//
|
||||
while (*aIter != *aIterEnd &&
|
||||
ldap_utf8isspace(const_cast<char *>(*aIter))) {
|
||||
++(*aIter);
|
||||
}
|
||||
|
||||
const char *start = *aIter;
|
||||
|
||||
// copy the token into our local variable
|
||||
//
|
||||
while (*aIter != *aIterEnd &&
|
||||
!ldap_utf8isspace(const_cast<char *>(*aIter))) {
|
||||
++(*aIter);
|
||||
}
|
||||
|
||||
return ToNewCString(Substring(start, *aIter));
|
||||
}
|
||||
116
ldap/xpcom/src/nsLDAPService.h
Normal file
116
ldap/xpcom/src/nsLDAPService.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ldap.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsILDAPService.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPServer.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
// 6a89ae33-7a90-430d-888c-0dede53a951a
|
||||
//
|
||||
#define NS_LDAPSERVICE_CID \
|
||||
{ \
|
||||
0x6a89ae33, 0x7a90, 0x430d, \
|
||||
{0x88, 0x8c, 0x0d, 0xed, 0xe5, 0x3a, 0x95, 0x1a} \
|
||||
}
|
||||
|
||||
// This is a little "helper" class, we use to store information
|
||||
// related to one Service entry (one LDAP server).
|
||||
//
|
||||
class nsLDAPServiceEntry
|
||||
{
|
||||
public:
|
||||
nsLDAPServiceEntry();
|
||||
virtual ~nsLDAPServiceEntry() {};
|
||||
bool Init();
|
||||
|
||||
inline uint32_t GetLeases();
|
||||
inline void IncrementLeases();
|
||||
inline bool DecrementLeases();
|
||||
|
||||
inline PRTime GetTimestamp();
|
||||
inline void SetTimestamp();
|
||||
|
||||
inline already_AddRefed<nsILDAPServer> GetServer();
|
||||
inline bool SetServer(nsILDAPServer *aServer);
|
||||
|
||||
inline already_AddRefed<nsILDAPConnection> GetConnection();
|
||||
inline void SetConnection(nsILDAPConnection *aConnection);
|
||||
|
||||
inline already_AddRefed<nsILDAPMessage> GetMessage();
|
||||
inline void SetMessage(nsILDAPMessage *aMessage);
|
||||
|
||||
inline already_AddRefed<nsILDAPMessageListener> PopListener();
|
||||
inline bool PushListener(nsILDAPMessageListener *);
|
||||
|
||||
inline bool IsRebinding();
|
||||
inline void SetRebinding(bool);
|
||||
|
||||
inline bool DeleteEntry();
|
||||
|
||||
protected:
|
||||
uint32_t mLeases; // The number of leases currently granted
|
||||
PRTime mTimestamp; // Last time this server was "used"
|
||||
bool mDelete; // This entry is due for deletion
|
||||
bool mRebinding; // Keep state if we are rebinding or not
|
||||
|
||||
nsCOMPtr<nsILDAPServer> mServer;
|
||||
nsCOMPtr<nsILDAPConnection> mConnection;
|
||||
nsCOMPtr<nsILDAPMessage> mMessage;
|
||||
|
||||
// Array holding all the pending callbacks (listeners) for this entry
|
||||
nsCOMArray<nsILDAPMessageListener> mListeners;
|
||||
};
|
||||
|
||||
// This is the interface we're implementing.
|
||||
//
|
||||
class nsLDAPService : public nsILDAPService, public nsILDAPMessageListener
|
||||
{
|
||||
public:
|
||||
// interface decls
|
||||
//
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPSERVICE
|
||||
NS_DECL_NSILDAPMESSAGELISTENER
|
||||
|
||||
// constructor and destructor
|
||||
//
|
||||
nsLDAPService();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPService();
|
||||
nsresult EstablishConnection(nsLDAPServiceEntry *,
|
||||
nsILDAPMessageListener *);
|
||||
|
||||
// kinda like strtok_r, but with iterators. for use by
|
||||
// createFilter
|
||||
//
|
||||
char *NextToken(const char **aIter, const char **aIterEnd);
|
||||
|
||||
// count how many tokens are in this string; for use by
|
||||
// createFilter; note that unlike with NextToken, these params
|
||||
// are copies, not references.
|
||||
//
|
||||
uint32_t CountTokens(const char * aIter, const char * aIterEnd);
|
||||
|
||||
|
||||
mozilla::Mutex mLock; // Lock mechanism
|
||||
|
||||
// Hash table holding server entries
|
||||
nsDataHashtable<nsStringHashKey, nsLDAPServiceEntry*> mServers;
|
||||
// Hash table holding "reverse" lookups from connection to server
|
||||
nsDataHashtable<nsVoidPtrHashKey, nsLDAPServiceEntry*> mConnections;
|
||||
};
|
||||
386
ldap/xpcom/src/nsLDAPSyncQuery.cpp
Normal file
386
ldap/xpcom/src/nsLDAPSyncQuery.cpp
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPSyncQuery.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsILDAPErrors.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsILDAPMessage.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
// nsISupports Implementation
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPSyncQuery, nsILDAPSyncQuery, nsILDAPMessageListener)
|
||||
|
||||
// Constructor
|
||||
//
|
||||
nsLDAPSyncQuery::nsLDAPSyncQuery() :
|
||||
mFinished(false), // This is a control variable for event loop
|
||||
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)
|
||||
{
|
||||
int32_t 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
|
||||
// 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;
|
||||
}
|
||||
|
||||
// our OnLDAPMessage accepts all result callbacks
|
||||
//
|
||||
rv = mOperation->Init(mConnection, this, nullptr);
|
||||
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)
|
||||
{
|
||||
|
||||
int32_t errCode;
|
||||
|
||||
mOperation = nullptr; // 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)
|
||||
{
|
||||
uint32_t attrCount;
|
||||
char** attributes;
|
||||
nsresult rv = aMessage->GetAttributes(&attrCount, &attributes);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_WARNING("nsLDAPSyncQuery:OnLDAPSearchEntry(): "
|
||||
"aMessage->GetAttributes() failed");
|
||||
FinishLDAPQuery();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Iterate through the attributes received in this message
|
||||
for (uint32_t i = 0; i < attrCount; i++)
|
||||
{
|
||||
char16_t **vals;
|
||||
uint32_t valueCount;
|
||||
|
||||
// Get the values of this attribute.
|
||||
// XXX better failure handling
|
||||
rv = aMessage->GetValues(attributes[i], &valueCount, &vals);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
NS_WARNING("nsLDAPSyncQuery:OnLDAPSearchEntry(): "
|
||||
"aMessage->GetValues() failed\n");
|
||||
FinishLDAPQuery();
|
||||
break;
|
||||
}
|
||||
|
||||
// Store all values of this attribute in the mResults.
|
||||
for (uint32_t j = 0; j < valueCount; j++) {
|
||||
mResults.Append(char16_t('\n'));
|
||||
mResults.AppendASCII(attributes[i]);
|
||||
mResults.Append(char16_t('='));
|
||||
mResults.Append(vals[j]);
|
||||
}
|
||||
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(valueCount, vals);
|
||||
}
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(attrCount, attributes);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsLDAPSyncQuery::OnLDAPSearchResult(nsILDAPMessage *aMessage)
|
||||
{
|
||||
// We are done with the LDAP search.
|
||||
// Release the control variable for the eventloop and other members
|
||||
//
|
||||
FinishLDAPQuery();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLDAPSyncQuery::StartLDAPSearch()
|
||||
{
|
||||
nsresult rv;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// initialize the LDAP operation object
|
||||
//
|
||||
rv = mOperation->Init(mConnection, this, nullptr);
|
||||
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;
|
||||
//
|
||||
nsAutoCString urlFilter;
|
||||
rv = mServerURL->GetFilter(urlFilter);
|
||||
if (NS_FAILED(rv)) {
|
||||
FinishLDAPQuery();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// get the base dn to search
|
||||
//
|
||||
nsAutoCString dn;
|
||||
rv = mServerURL->GetDn(dn);
|
||||
if (NS_FAILED(rv)) {
|
||||
FinishLDAPQuery();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// and the scope
|
||||
//
|
||||
int32_t scope;
|
||||
rv = mServerURL->GetScope(&scope);
|
||||
if (NS_FAILED(rv)) {
|
||||
FinishLDAPQuery();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsAutoCString attributes;
|
||||
rv = mServerURL->GetAttributes(attributes);
|
||||
if (NS_FAILED(rv)) {
|
||||
FinishLDAPQuery();
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// time to kick off the search.
|
||||
rv = mOperation->SearchExt(dn, scope, urlFilter, attributes, 0, 0);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
FinishLDAPQuery();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// void initConnection ();
|
||||
//
|
||||
nsresult nsLDAPSyncQuery::InitConnection()
|
||||
{
|
||||
// Because mConnection->Init proxies back to the main thread, this
|
||||
// better be the main thread.
|
||||
NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_FAILURE);
|
||||
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;
|
||||
}
|
||||
rv = mConnection->Init(mServerURL, EmptyCString(), this,
|
||||
nullptr, 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 = true;
|
||||
|
||||
// Release member variables
|
||||
//
|
||||
mConnection = nullptr;
|
||||
mOperation = nullptr;
|
||||
mServerURL = nullptr;
|
||||
|
||||
}
|
||||
|
||||
/* wstring getQueryResults (in nsILDAPURL aServerURL, in unsigned long aVersion); */
|
||||
NS_IMETHODIMP nsLDAPSyncQuery::GetQueryResults(nsILDAPURL *aServerURL,
|
||||
uint32_t aProtocolVersion,
|
||||
char16_t **_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;
|
||||
|
||||
}
|
||||
58
ldap/xpcom/src/nsLDAPSyncQuery.h
Normal file
58
ldap/xpcom/src/nsLDAPSyncQuery.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsILDAPConnection.h"
|
||||
#include "nsILDAPOperation.h"
|
||||
#include "nsILDAPMessageListener.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsStringGlue.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_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSILDAPMESSAGELISTENER
|
||||
NS_DECL_NSILDAPSYNCQUERY
|
||||
|
||||
nsLDAPSyncQuery();
|
||||
|
||||
protected:
|
||||
virtual ~nsLDAPSyncQuery();
|
||||
|
||||
nsCOMPtr<nsILDAPConnection> mConnection; // connection used for search
|
||||
nsCOMPtr<nsILDAPOperation> mOperation; // current ldap op
|
||||
nsCOMPtr<nsILDAPURL> mServerURL; // LDAP URL
|
||||
bool mFinished; // control variable for eventQ
|
||||
nsString mResults; // values to return
|
||||
uint32_t 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();
|
||||
};
|
||||
|
||||
725
ldap/xpcom/src/nsLDAPURL.cpp
Normal file
725
ldap/xpcom/src/nsLDAPURL.cpp
Normal file
|
|
@ -0,0 +1,725 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsLDAPURL.h"
|
||||
#include "netCore.h"
|
||||
#include "plstr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIStandardURL.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
// The two schemes we support, LDAP and LDAPS
|
||||
//
|
||||
NS_NAMED_LITERAL_CSTRING(LDAP_SCHEME, "ldap");
|
||||
NS_NAMED_LITERAL_CSTRING(LDAP_SSL_SCHEME, "ldaps");
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsLDAPURL, nsILDAPURL, nsIURI)
|
||||
|
||||
nsLDAPURL::nsLDAPURL()
|
||||
: mScope(SCOPE_BASE),
|
||||
mOptions(0)
|
||||
{
|
||||
}
|
||||
|
||||
nsLDAPURL::~nsLDAPURL()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLDAPURL::Init(uint32_t aUrlType, int32_t aDefaultPort,
|
||||
const nsACString &aSpec, const char* aOriginCharset,
|
||||
nsIURI *aBaseURI)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
{
|
||||
mBaseURL = do_CreateInstance(NS_STANDARDURL_CONTRACTID);
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStandardURL> standardURL(do_QueryInterface(mBaseURL, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = standardURL->Init(aUrlType, aDefaultPort, aSpec, aOriginCharset,
|
||||
aBaseURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now get the spec from the mBaseURL in case it was a relative one
|
||||
nsCString spec;
|
||||
rv = mBaseURL->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return SetSpec(spec);
|
||||
}
|
||||
|
||||
void
|
||||
nsLDAPURL::GetPathInternal(nsCString &aPath)
|
||||
{
|
||||
aPath.Assign('/');
|
||||
|
||||
if (!mDN.IsEmpty())
|
||||
aPath.Append(mDN);
|
||||
|
||||
if (!mAttributes.IsEmpty())
|
||||
aPath.Append('?');
|
||||
|
||||
// If mAttributes isn't empty, cut off the internally stored commas at start
|
||||
// and end, and append to the path.
|
||||
if (!mAttributes.IsEmpty())
|
||||
aPath.Append(Substring(mAttributes, 1, mAttributes.Length() - 2));
|
||||
|
||||
if (mScope || !mFilter.IsEmpty())
|
||||
{
|
||||
aPath.Append((mAttributes.IsEmpty() ? "??" : "?"));
|
||||
if (mScope)
|
||||
{
|
||||
if (mScope == SCOPE_ONELEVEL)
|
||||
aPath.Append("one");
|
||||
else if (mScope == SCOPE_SUBTREE)
|
||||
aPath.Append("sub");
|
||||
}
|
||||
if (!mFilter.IsEmpty())
|
||||
{
|
||||
aPath.Append('?');
|
||||
aPath.Append(mFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsLDAPURL::SetPathInternal(const nsCString &aPath)
|
||||
{
|
||||
LDAPURLDesc *desc;
|
||||
|
||||
// This is from the LDAP C-SDK, which currently doesn't
|
||||
// support everything from RFC 2255... :(
|
||||
//
|
||||
int err = ldap_url_parse(aPath.get(), &desc);
|
||||
switch (err) {
|
||||
case LDAP_SUCCESS: {
|
||||
// The base URL can pick up the host & port details and deal with them
|
||||
// better than we can
|
||||
mDN = desc->lud_dn;
|
||||
mScope = desc->lud_scope;
|
||||
mFilter = desc->lud_filter;
|
||||
mOptions = desc->lud_options;
|
||||
nsresult rv = SetAttributeArray(desc->lud_attrs);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
ldap_free_urldesc(desc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
case LDAP_URL_ERR_NOTLDAP:
|
||||
case LDAP_URL_ERR_NODN:
|
||||
case LDAP_URL_ERR_BADSCOPE:
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
case LDAP_URL_ERR_MEM:
|
||||
NS_ERROR("nsLDAPURL::SetSpec: out of memory ");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
case LDAP_URL_ERR_PARAM:
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// This shouldn't happen...
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// A string representation of the URI. Setting the spec
|
||||
// causes the new spec to be parsed, initializing the URI. Setting
|
||||
// the spec (or any of the accessors) causes also any currently
|
||||
// open streams on the URI's channel to be closed.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetSpec(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetSpec(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetSpec(const nsACString &aSpec)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// Cache the original spec in case we don't like what we've been passed and
|
||||
// need to reset ourselves.
|
||||
nsCString originalSpec;
|
||||
nsresult rv = mBaseURL->GetSpec(originalSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mBaseURL->SetSpec(aSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetPathInternal(PromiseFlatCString(aSpec));
|
||||
if (NS_FAILED(rv))
|
||||
mBaseURL->SetSpec(originalSpec);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetPrePath(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetPrePath(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetScheme(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetScheme(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetScheme(const nsACString &aScheme)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (aScheme.Equals(LDAP_SCHEME, nsCaseInsensitiveCStringComparator()))
|
||||
mOptions &= !OPT_SECURE;
|
||||
else if (aScheme.Equals(LDAP_SSL_SCHEME,
|
||||
nsCaseInsensitiveCStringComparator()))
|
||||
mOptions |= OPT_SECURE;
|
||||
else
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
return mBaseURL->SetScheme(aScheme);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetUserPass(nsACString &_retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetUserPass(const nsACString &aUserPass)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetUsername(nsACString &_retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetUsername(const nsACString &aUsername)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetPassword(nsACString &_retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetPassword(const nsACString &aPassword)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetHostPort(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetHostPort(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetHostPort(const nsACString &aHostPort)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->SetHostPort(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetHostAndPort(const nsACString &aHostPort)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->SetHostAndPort(aHostPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetHost(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetHost(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetHost(const nsACString &aHost)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->SetHost(aHost);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetPort(int32_t *_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetPort(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::SetPort(int32_t aPort)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->SetPort(aPort);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetPath(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetPath(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetPath(const nsACString &aPath)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv = SetPathInternal(PromiseFlatCString(aPath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return mBaseURL->SetPath(aPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetAsciiSpec(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// XXX handle extra items?
|
||||
return mBaseURL->GetAsciiSpec(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetAsciiHost(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetAsciiHost(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetAsciiHostPort(nsACString &_retval)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetAsciiHostPort(_retval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetOriginCharset(nsACString &result)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->GetOriginCharset(result);
|
||||
}
|
||||
|
||||
// boolean equals (in nsIURI other)
|
||||
// (based on nsSimpleURI::Equals)
|
||||
NS_IMETHODIMP nsLDAPURL::Equals(nsIURI *other, bool *_retval)
|
||||
{
|
||||
*_retval = false;
|
||||
if (other)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILDAPURL> otherURL(do_QueryInterface(other, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsAutoCString thisSpec, otherSpec;
|
||||
uint32_t otherOptions;
|
||||
|
||||
rv = GetSpec(thisSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = otherURL->GetSpec(otherSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = otherURL->GetOptions(&otherOptions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (thisSpec == otherSpec && mOptions == otherOptions)
|
||||
*_retval = true;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// boolean schemeIs(in const char * scheme);
|
||||
//
|
||||
NS_IMETHODIMP nsLDAPURL::SchemeIs(const char *aScheme, bool *aEquals)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return mBaseURL->SchemeIs(aScheme, aEquals);
|
||||
}
|
||||
|
||||
// nsIURI clone ();
|
||||
//
|
||||
nsresult
|
||||
nsLDAPURL::CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
nsLDAPURL *clone = new nsLDAPURL();
|
||||
|
||||
if (!clone)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
clone->mDN = mDN;
|
||||
clone->mScope = mScope;
|
||||
clone->mFilter = mFilter;
|
||||
clone->mOptions = mOptions;
|
||||
clone->mAttributes = mAttributes;
|
||||
|
||||
nsresult rv;
|
||||
if (aRefHandlingMode == eHonorRef) {
|
||||
rv = mBaseURL->Clone(getter_AddRefs(clone->mBaseURL));
|
||||
} else if (aRefHandlingMode == eReplaceRef) {
|
||||
rv = mBaseURL->CloneWithNewRef(newRef, getter_AddRefs(clone->mBaseURL));
|
||||
} else {
|
||||
rv = mBaseURL->CloneIgnoringRef(getter_AddRefs(clone->mBaseURL));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ADDREF(*aResult = clone);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::Clone(nsIURI** result)
|
||||
{
|
||||
return CloneInternal(eHonorRef, EmptyCString(), result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::CloneIgnoringRef(nsIURI** result)
|
||||
{
|
||||
return CloneInternal(eIgnoreRef, EmptyCString(), result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::CloneWithNewRef(const nsACString& newRef, nsIURI** result)
|
||||
{
|
||||
return CloneInternal(eReplaceRef, newRef, result);
|
||||
}
|
||||
|
||||
// string resolve (in string relativePath);
|
||||
//
|
||||
NS_IMETHODIMP nsLDAPURL::Resolve(const nsACString &relativePath,
|
||||
nsACString &_retval)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// The following attributes come from nsILDAPURL
|
||||
|
||||
// attribute AUTF8String dn;
|
||||
//
|
||||
NS_IMETHODIMP nsLDAPURL::GetDn(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mDN);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPURL::SetDn(const nsACString& aDn)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
mDN.Assign(aDn);
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetAttributes(nsACString &aAttributes)
|
||||
{
|
||||
if (mAttributes.IsEmpty())
|
||||
{
|
||||
aAttributes.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mAttributes[0] == ',' &&
|
||||
mAttributes[mAttributes.Length() - 1] == ',',
|
||||
"mAttributes does not begin and end with a comma");
|
||||
|
||||
// We store the string internally with comma before and after, so strip
|
||||
// them off here.
|
||||
aAttributes = Substring(mAttributes, 1, mAttributes.Length() - 2);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetAttributes(const nsACString &aAttributes)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (aAttributes.IsEmpty())
|
||||
mAttributes.Truncate();
|
||||
else
|
||||
{
|
||||
// We need to make sure we start off the string with a comma.
|
||||
if (aAttributes[0] != ',')
|
||||
mAttributes = ',';
|
||||
|
||||
mAttributes.Append(aAttributes);
|
||||
|
||||
// Also end with a comma if appropriate.
|
||||
if (mAttributes[mAttributes.Length() - 1] != ',')
|
||||
mAttributes.Append(',');
|
||||
}
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
nsresult nsLDAPURL::SetAttributeArray(char** aAttributes)
|
||||
{
|
||||
mAttributes.Truncate();
|
||||
|
||||
while (aAttributes && *aAttributes)
|
||||
{
|
||||
// Always start with a comma as that's what we store internally.
|
||||
mAttributes.Append(',');
|
||||
mAttributes.Append(*aAttributes);
|
||||
++aAttributes;
|
||||
}
|
||||
|
||||
// Add a comma on the end if we have something.
|
||||
if (!mAttributes.IsEmpty())
|
||||
mAttributes.Append(',');
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::AddAttribute(const nsACString &aAttribute)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (mAttributes.IsEmpty())
|
||||
{
|
||||
mAttributes = ',';
|
||||
mAttributes.Append(aAttribute);
|
||||
mAttributes.Append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wrap the attribute in commas, so that we can do an exact match.
|
||||
nsAutoCString findAttribute(",");
|
||||
findAttribute.Append(aAttribute);
|
||||
findAttribute.Append(',');
|
||||
|
||||
// Check to see if the attribute is already stored. If it is, then also
|
||||
// check to see if it is the last attribute in the string, or if the next
|
||||
// character is a comma, this means we won't match substrings.
|
||||
int32_t pos = mAttributes.Find(findAttribute, CaseInsensitiveCompare);
|
||||
if (pos != -1)
|
||||
return NS_OK;
|
||||
|
||||
mAttributes.Append(Substring(findAttribute, 1));
|
||||
}
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::RemoveAttribute(const nsACString &aAttribute)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
if (mAttributes.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
nsAutoCString findAttribute(",");
|
||||
findAttribute.Append(aAttribute);
|
||||
findAttribute.Append(',');
|
||||
|
||||
if (mAttributes.Equals(findAttribute, nsCaseInsensitiveCStringComparator()))
|
||||
mAttributes.Truncate();
|
||||
else
|
||||
{
|
||||
int32_t pos = mAttributes.Find(findAttribute, CaseInsensitiveCompare);
|
||||
if (pos == -1)
|
||||
return NS_OK;
|
||||
|
||||
mAttributes.Cut(pos, findAttribute.Length() - 1);
|
||||
}
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::HasAttribute(const nsACString &aAttribute,
|
||||
bool *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
|
||||
nsAutoCString findAttribute(",");
|
||||
findAttribute.Append(aAttribute);
|
||||
findAttribute.Append(',');
|
||||
|
||||
*_retval = mAttributes.Find(findAttribute, CaseInsensitiveCompare) != -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetScope(int32_t *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = mScope;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetScope(int32_t aScope)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// Only allow scopes supported by the C-SDK
|
||||
if ((aScope != SCOPE_BASE) && (aScope != SCOPE_ONELEVEL) &&
|
||||
(aScope != SCOPE_SUBTREE))
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
|
||||
mScope = aScope;
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetFilter(nsACString& _retval)
|
||||
{
|
||||
_retval.Assign(mFilter);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsLDAPURL::SetFilter(const nsACString& aFilter)
|
||||
{
|
||||
if (!mBaseURL)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
mFilter.Assign(aFilter);
|
||||
|
||||
if (mFilter.IsEmpty())
|
||||
mFilter.AssignLiteral("(objectclass=*)");
|
||||
|
||||
// Now get the current path
|
||||
nsCString newPath;
|
||||
GetPathInternal(newPath);
|
||||
|
||||
// and update the base url
|
||||
return mBaseURL->SetPath(newPath);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::GetOptions(uint32_t *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(_retval);
|
||||
*_retval = mOptions;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetOptions(uint32_t aOptions)
|
||||
{
|
||||
// Secure is the only option supported at the moment
|
||||
if ((mOptions & OPT_SECURE) == (aOptions & OPT_SECURE))
|
||||
return NS_OK;
|
||||
|
||||
mOptions = aOptions;
|
||||
|
||||
if ((aOptions & OPT_SECURE) == OPT_SECURE)
|
||||
return SetScheme(LDAP_SSL_SCHEME);
|
||||
|
||||
return SetScheme(LDAP_SCHEME);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::SetRef(const nsACString &aRef)
|
||||
{
|
||||
return mBaseURL->SetRef(aRef);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetRef(nsACString &result)
|
||||
{
|
||||
return mBaseURL->GetRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsLDAPURL::EqualsExceptRef(nsIURI *other, bool *result)
|
||||
{
|
||||
return mBaseURL->EqualsExceptRef(other, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetSpecIgnoringRef(nsACString &result)
|
||||
{
|
||||
return mBaseURL->GetSpecIgnoringRef(result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPURL::GetHasRef(bool *result)
|
||||
{
|
||||
return mBaseURL->GetHasRef(result);
|
||||
}
|
||||
61
ldap/xpcom/src/nsLDAPURL.h
Normal file
61
ldap/xpcom/src/nsLDAPURL.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ldap.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsILDAPURL.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// cb7c67f8-0053-4072-89e9-501cbd1b35ab
|
||||
#define NS_LDAPURL_CID \
|
||||
{ 0xcb7c67f8, 0x0053, 0x4072, \
|
||||
{ 0x89, 0xe9, 0x50, 0x1c, 0xbd, 0x1b, 0x35, 0xab}}
|
||||
|
||||
/**
|
||||
* nsLDAPURL
|
||||
*
|
||||
* nsLDAPURL uses an nsStandardURL stored in mBaseURL as its main url formatter.
|
||||
*
|
||||
* This is done to ensure that the pre-path sections of the URI are correctly
|
||||
* formatted and to re-use the functions for nsIURI as appropriate.
|
||||
*
|
||||
* Handling of the path sections of the URI are done within nsLDAPURL/parts of
|
||||
* the LDAP c-sdk. nsLDAPURL holds the individual sections of the path of the
|
||||
* URI locally (to allow convenient get/set), but always updates the mBaseURL
|
||||
* when one changes to ensure that mBaseURL.spec and the local data are kept
|
||||
* consistent.
|
||||
*/
|
||||
|
||||
class nsLDAPURL : public nsILDAPURL
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIURI
|
||||
NS_DECL_NSILDAPURL
|
||||
|
||||
nsLDAPURL();
|
||||
|
||||
protected:
|
||||
enum RefHandlingEnum {
|
||||
eIgnoreRef,
|
||||
eHonorRef,
|
||||
eReplaceRef
|
||||
};
|
||||
virtual ~nsLDAPURL();
|
||||
|
||||
void GetPathInternal(nsCString &aPath);
|
||||
nsresult SetPathInternal(const nsCString &aPath);
|
||||
nsresult SetAttributeArray(char** aAttributes);
|
||||
nsresult CloneInternal(RefHandlingEnum aRefHandlingMode,
|
||||
const nsACString& newRef, nsIURI** aResult);
|
||||
|
||||
nsCString mDN; // Base Distinguished Name (Base DN)
|
||||
int32_t mScope; // Search scope (base, one or sub)
|
||||
nsCString mFilter; // LDAP search filter
|
||||
uint32_t mOptions; // Options
|
||||
nsCString mAttributes;
|
||||
nsCOMPtr<nsIURI> mBaseURL;
|
||||
};
|
||||
147
ldap/xpcom/src/nsLDAPUtils.h
Normal file
147
ldap/xpcom/src/nsLDAPUtils.h
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This module contains helper functions and macros for converting directory
|
||||
module to frozen linkage.
|
||||
*/
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
/* Internal API helper macros */
|
||||
|
||||
#define LdapCompressWhitespace(str) \
|
||||
(str).CompressWhitespace()
|
||||
|
||||
#else // MOZILLA_INTERNAL_API
|
||||
/* Frozen linkage helper functions */
|
||||
|
||||
/* This macro has been copied from msgcore.h */
|
||||
#define IS_SPACE(VAL) \
|
||||
(((((PRIntn)(VAL)) & 0x7f) == ((PRIntn)(VAL))) && isspace((PRIntn)(VAL)))
|
||||
|
||||
/* This function has been copied from nsMsgUtils.cpp */
|
||||
inline void LdapCompressWhitespace(nsCString& aString)
|
||||
{
|
||||
// This code is frozen linkage specific
|
||||
aString.Trim(" \f\n\r\t\v");
|
||||
|
||||
char *start, *end;
|
||||
aString.BeginWriting(&start, &end);
|
||||
|
||||
for (char *cur = start; cur < end; ++cur) {
|
||||
if (!IS_SPACE(*cur))
|
||||
continue;
|
||||
|
||||
*cur = ' ';
|
||||
|
||||
if (!IS_SPACE(*(cur + 1)))
|
||||
continue;
|
||||
|
||||
// Loop through the white space
|
||||
char *wend = cur + 2;
|
||||
while (IS_SPACE(*wend))
|
||||
++wend;
|
||||
|
||||
uint32_t wlen = wend - cur - 1;
|
||||
|
||||
// fix "end"
|
||||
end -= wlen;
|
||||
|
||||
// move everything forwards a bit
|
||||
for (char *m = cur + 1; m < end; ++m) {
|
||||
*m = *(m + wlen);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new length.
|
||||
aString.SetLength(end - start);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function copied from nsReadableUtils.
|
||||
* Migrating to frozen linkage is the only change done
|
||||
*/
|
||||
inline
|
||||
bool IsUTF8(const nsACString& aString)
|
||||
{
|
||||
const char *done_reading = aString.EndReading();
|
||||
|
||||
int32_t state = 0;
|
||||
bool overlong = false;
|
||||
bool surrogate = false;
|
||||
bool nonchar = false;
|
||||
uint16_t olupper = 0; // overlong byte upper bound.
|
||||
uint16_t slower = 0; // surrogate byte lower bound.
|
||||
|
||||
const char *ptr = aString.BeginReading();
|
||||
|
||||
while (ptr < done_reading) {
|
||||
uint8_t c;
|
||||
|
||||
if (0 == state) {
|
||||
|
||||
c = *ptr++;
|
||||
|
||||
if ((c & 0x80) == 0x00)
|
||||
continue;
|
||||
|
||||
if ( c <= 0xC1 ) // [80-BF] where not expected, [C0-C1] for overlong.
|
||||
return false;
|
||||
else if ((c & 0xE0) == 0xC0)
|
||||
state = 1;
|
||||
else if ((c & 0xF0) == 0xE0) {
|
||||
state = 2;
|
||||
if ( c == 0xE0 ) { // to exclude E0[80-9F][80-BF]
|
||||
overlong = true;
|
||||
olupper = 0x9F;
|
||||
} else if ( c == 0xED ) { // ED[A0-BF][80-BF] : surrogate codepoint
|
||||
surrogate = true;
|
||||
slower = 0xA0;
|
||||
} else if ( c == 0xEF ) // EF BF [BE-BF] : non-character
|
||||
nonchar = true;
|
||||
} else if ( c <= 0xF4 ) { // XXX replace /w UTF8traits::is4byte when it's updated to exclude [F5-F7].(bug 199090)
|
||||
state = 3;
|
||||
nonchar = true;
|
||||
if ( c == 0xF0 ) { // to exclude F0[80-8F][80-BF]{2}
|
||||
overlong = true;
|
||||
olupper = 0x8F;
|
||||
}
|
||||
else if ( c == 0xF4 ) { // to exclude F4[90-BF][80-BF]
|
||||
// actually not surrogates but codepoints beyond 0x10FFFF
|
||||
surrogate = true;
|
||||
slower = 0x90;
|
||||
}
|
||||
} else
|
||||
return false; // Not UTF-8 string
|
||||
}
|
||||
|
||||
while (ptr < done_reading && state) {
|
||||
c = *ptr++;
|
||||
--state;
|
||||
|
||||
// non-character : EF BF [BE-BF] or F[0-7] [89AB]F BF [BE-BF]
|
||||
if ( nonchar && ( !state && c < 0xBE ||
|
||||
state == 1 && c != 0xBF ||
|
||||
state == 2 && 0x0F != (0x0F & c) ))
|
||||
nonchar = false;
|
||||
|
||||
if ((c & 0xC0) != 0x80 || overlong && c <= olupper ||
|
||||
surrogate && slower <= c || nonchar && !state )
|
||||
return false; // Not UTF-8 string
|
||||
overlong = surrogate = false;
|
||||
}
|
||||
}
|
||||
return !state; // state != 0 at the end indicates an invalid UTF-8 seq.
|
||||
}
|
||||
|
||||
#define kNotFound -1
|
||||
|
||||
#define nsCaseInsensitiveCStringComparator() \
|
||||
CaseInsensitiveCompare
|
||||
#define nsCaseInsensitiveStringComparator() \
|
||||
CaseInsensitiveCompare
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
Loading…
Add table
Add a link
Reference in a new issue