📄 pldap.cxx
字号:
/*
* pldap.cxx
*
* Lightweight Directory Access Protocol interface class.
*
* Portable Windows Library
*
* Copyright (c) 1993-2003 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): ______________________________________.
*
* $Log: pldap.cxx,v $
* Revision 1.2 2007/06/04 16:06:44 joegenbaclor
* *** empty log message ***
*
* Revision 1.1 2006/06/29 04:18:03 joegenbaclor
* *** empty log message ***
*
* Revision 1.20 2006/01/16 19:52:05 dsandras
* Applied patch from Brian Lu <brian lu sun com> to allow compilation on
* Solaris using SUN's LDAP. Thanks!!
*
* Revision 1.19 2005/09/18 13:01:43 dominance
* fixed pragma warnings when building with gcc.
*
* Revision 1.18 2005/08/31 15:21:34 dominance
* fix building with recent OpenLDAP
*
* Revision 1.17 2004/05/24 12:02:49 csoutheren
* Add function to permit setting a limit on the number of results returned
* from an LDAP query. Change the default number of results to unlimited,
* rather than MAX_INT which apparently is clamped to some arbitrary low value.
* Thanks to Damien Sandras
*
* Revision 1.16 2004/04/09 06:52:17 rjongbloed
* Removed #pargma linker command for /delayload of DLL as documentations sais that
* you cannot do this.
*
* Revision 1.15 2004/02/23 23:52:19 csoutheren
* Added pragmas to avoid every Windows application needing to include libs explicitly
*
* Revision 1.14 2004/02/04 09:37:00 rjongbloed
* Fixed memory leak and race condition, thanks Rossano Ravelli
*
* Revision 1.13 2004/01/17 17:45:29 csoutheren
* Changed to use PString::MakeEmpty
*
* Revision 1.12 2003/07/15 12:12:11 csoutheren
* Added support for multiple values in a single attribute string
* Thanks to Ravelli Rossano
*
* Revision 1.11 2003/07/12 00:10:40 csoutheren
* Fixed problem where Modify routines were calling Add, thanks to Ravelli Rossano
*
* Revision 1.10 2003/06/06 09:14:01 dsandras
*
* Test that a search result has been returned before calling ldapresult2error.
*
* Revision 1.9 2003/06/05 23:17:52 rjongbloed
* Changed default operation timeout to 30 seconds.
*
* Revision 1.8 2003/06/05 05:29:30 rjongbloed
* Fixed LDAP bind authentication methods, thanks Ravelli Rossano
*
* Revision 1.7 2003/04/17 08:34:48 robertj
* Changed LDAP structure output so if field is empty it leaves it out
* altogether rather then encoding an empty string, some servers barf.
*
* Revision 1.6 2003/04/16 08:00:19 robertj
* Windoes psuedo autoconf support
*
* Revision 1.5 2003/04/07 11:59:52 robertj
* Fixed search function returning an error if can't find anything for filter.
*
* Revision 1.4 2003/04/01 07:05:16 robertj
* Added ability to specify host:port in opening an LDAP server
*
* Revision 1.3 2003/03/31 03:32:53 robertj
* Major addition of functionality.
*
*/
#ifdef __GNUC__
#pragma implementation "pldap.h"
#endif
#include <ptlib.h>
#include <ptlib/sockets.h>
#include <ptclib/pldap.h>
////////////////////////////////////////////////
/// Get rid of LNK4221: no public symbols found;
/// archive member will be inaccessible
const char * pldap_file_content = NULL;
////////////////////////////////////////////////
#if P_LDAP
#define LDAP_DEPRECATED 1
#include <ldap.h>
#if defined(_MSC_VER)
#pragma comment(lib, P_LDAP_LIBRARY)
#endif
///////////////////////////////////////////////////////////////////////////////
PLDAPSession::PLDAPSession(const PString & baseDN)
: ldapContext(NULL),
errorNumber(LDAP_SUCCESS),
protocolVersion(LDAP_VERSION3),
defaultBaseDN(baseDN),
searchLimit(0),
timeout(0, 30),
multipleValueSeparator('\n')
{
}
PLDAPSession::~PLDAPSession()
{
Close();
}
BOOL PLDAPSession::Open(const PString & server, WORD port)
{
Close();
PString host = server;
PINDEX colon = server.Find(':');
if (colon != P_MAX_INDEX) {
host = server.Left(colon);
port = PIPSocket::GetPortByService(server.Mid(colon+1), "tcp");
}
ldapContext = ldap_init(server, port);
if (!IsOpen())
return FALSE;
SetOption(LDAP_OPT_PROTOCOL_VERSION, protocolVersion);
return TRUE;
}
BOOL PLDAPSession::Close()
{
if (!IsOpen())
return FALSE;
ldap_unbind(ldapContext);
ldapContext = NULL;
return TRUE;
}
BOOL PLDAPSession::SetOption(int optcode, int value)
{
if (!IsOpen())
return FALSE;
return ldap_set_option(ldapContext, optcode, &value);
}
BOOL PLDAPSession::SetOption(int optcode, void * value)
{
if (!IsOpen())
return FALSE;
return ldap_set_option(ldapContext, optcode, value);
}
BOOL PLDAPSession::Bind(const PString & who,
const PString & passwd,
AuthenticationMethod authMethod)
{
if (!IsOpen())
return FALSE;
const char * whoPtr;
if (who.IsEmpty())
whoPtr = NULL;
else
whoPtr = who;
#ifdef SOLARIS
static const int AuthMethodCode[NumAuthenticationMethod2] = {
LDAP_AUTH_SIMPLE, LDAP_AUTH_SASL, LDAP_AUTH_KRBV41_30, LDAP_AUTH_KRBV42_30
#else
static const int AuthMethodCode[NumAuthenticationMethod] = {
LDAP_AUTH_SIMPLE, LDAP_AUTH_SASL, LDAP_AUTH_KRBV4
#endif
};
errorNumber = ldap_bind_s(ldapContext, whoPtr, passwd, AuthMethodCode[authMethod]);
return errorNumber == LDAP_SUCCESS;
}
PLDAPSession::ModAttrib::ModAttrib(const PString & n, Operation o)
: name(n),
op(o)
{
}
void PLDAPSession::ModAttrib::SetLDAPMod(struct ldapmod & mod, Operation defaultOp)
{
mod.mod_type = (char *)(const char *)name;
Operation realOp = op == NumOperations ? defaultOp : op;
static const int OpCode[NumOperations] = {
LDAP_MOD_ADD, LDAP_MOD_REPLACE, LDAP_MOD_DELETE
};
mod.mod_op = OpCode[realOp];
if (IsBinary())
mod.mod_op |= LDAP_MOD_BVALUES;
SetLDAPModVars(mod);
}
PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
Operation op)
: ModAttrib(name, op)
{
}
PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
const PString & value,
Operation op)
: ModAttrib(name, op)
{
AddValue(value);
}
PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
const PStringList & vals,
Operation op)
: ModAttrib(name, op),
values(vals)
{
}
void PLDAPSession::StringModAttrib::SetValue(const PString & value)
{
values.RemoveAll();
values.AppendString(value);
}
void PLDAPSession::StringModAttrib::AddValue(const PString & value)
{
values.AppendString(value);
}
BOOL PLDAPSession::StringModAttrib::IsBinary() const
{
return FALSE;
}
void PLDAPSession::StringModAttrib::SetLDAPModVars(struct ldapmod & mod)
{
pointers.SetSize(values.GetSize()+1);
PINDEX i;
for (i = 0; i < values.GetSize(); i++)
pointers[i] = values[i].GetPointer();
pointers[i] = NULL;
mod.mod_values = pointers.GetPointer();
}
PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
Operation op)
: ModAttrib(name, op)
{
}
PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
const PBYTEArray & value,
Operation op)
: ModAttrib(name, op)
{
AddValue(value);
}
PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
const PList<PBYTEArray> & vals,
Operation op)
: ModAttrib(name, op),
values(vals)
{
}
void PLDAPSession::BinaryModAttrib::SetValue(const PBYTEArray & value)
{
values.RemoveAll();
values.Append(new PBYTEArray(value));
}
void PLDAPSession::BinaryModAttrib::AddValue(const PBYTEArray & value)
{
values.Append(new PBYTEArray(value));
}
BOOL PLDAPSession::BinaryModAttrib::IsBinary() const
{
return TRUE;
}
void PLDAPSession::BinaryModAttrib::SetLDAPModVars(struct ldapmod & mod)
{
pointers.SetSize(values.GetSize()+1);
bervals.SetSize(values.GetSize()*sizeof(berval));
berval * ber = (berval *)bervals.GetPointer();
PINDEX i;
for (i = 0; i < values.GetSize(); i++) {
ber[i].bv_val = (char *)values[i].GetPointer();
ber[i].bv_len = values[i].GetSize();
pointers[i] = &ber[i];
}
pointers[i] = NULL;
mod.mod_bvalues = pointers.GetPointer();
}
static LDAPMod ** CreateLDAPModArray(const PList<PLDAPSession::ModAttrib> & attributes,
PLDAPSession::ModAttrib::Operation defaultOp,
PBYTEArray & storage)
{
PINDEX count = attributes.GetSize();
storage.SetSize(count*sizeof(LDAPMod) + (count+1)*sizeof(LDAPMod *));
LDAPMod ** attrs = (LDAPMod **)storage.GetPointer();
LDAPMod * attr = (LDAPMod * )&attrs[count+1];
for (PINDEX i = 0; i < count; i++) {
attrs[i] = &attr[i];
attributes[i].SetLDAPMod(attr[i], defaultOp);
}
return attrs;
}
static PList<PLDAPSession::ModAttrib> AttribsFromDict(const PStringToString & attributes)
{
PList<PLDAPSession::ModAttrib> attrs;
for (PINDEX i = 0; i < attributes.GetSize(); i++)
attrs.Append(new PLDAPSession::StringModAttrib(attributes.GetKeyAt(i),
attributes.GetDataAt(i).Lines()));
return attrs;
}
static PList<PLDAPSession::ModAttrib> AttribsFromArray(const PStringArray & attributes)
{
PList<PLDAPSession::ModAttrib> attrs;
for (PINDEX i = 0; i < attributes.GetSize(); i++) {
PString attr = attributes[i];
PINDEX equal = attr.Find('=');
if (equal != P_MAX_INDEX)
attrs.Append(new PLDAPSession::StringModAttrib(attr.Left(equal),
attr.Mid(equal+1).Lines()));
}
return attrs;
}
static PList<PLDAPSession::ModAttrib> AttribsFromStruct(const PLDAPStructBase & attributes)
{
PList<PLDAPSession::ModAttrib> attrs;
for (PINDEX i = 0; i < attributes.GetNumAttributes(); i++) {
PLDAPAttributeBase & attr = attributes.GetAttribute(i);
if (attr.IsBinary())
attrs.Append(new PLDAPSession::BinaryModAttrib(attr.GetName(), attr.ToBinary()));
else {
PString str = attr.ToString();
if (!str)
attrs.Append(new PLDAPSession::StringModAttrib(attr.GetName(), str));
}
}
return attrs;
}
BOOL PLDAPSession::Add(const PString & dn, const PList<ModAttrib> & attributes)
{
if (!IsOpen())
return FALSE;
PBYTEArray storage;
int msgid;
errorNumber = ldap_add_ext(ldapContext,
dn,
CreateLDAPModArray(attributes, ModAttrib::Add, storage),
NULL,
NULL,
&msgid);
if (errorNumber != LDAP_SUCCESS)
return FALSE;
P_timeval tval = timeout;
LDAPMessage * result = NULL;
ldap_result(ldapContext, msgid, LDAP_MSG_ALL, tval, &result);
if (result)
errorNumber = ldap_result2error(ldapContext, result, TRUE);
return errorNumber == LDAP_SUCCESS;
}
BOOL PLDAPSession::Add(const PString & dn, const PStringToString & attributes)
{
return Add(dn, AttribsFromDict(attributes));
}
BOOL PLDAPSession::Add(const PString & dn, const PStringArray & attributes)
{
return Add(dn, AttribsFromArray(attributes));
}
BOOL PLDAPSession::Add(const PString & dn, const PLDAPStructBase & attributes)
{
return Add(dn, AttribsFromStruct(attributes));
}
BOOL PLDAPSession::Modify(const PString & dn, const PList<ModAttrib> & attributes)
{
if (!IsOpen())
return FALSE;
PBYTEArray storage;
int msgid;
errorNumber = ldap_modify_ext(ldapContext,
dn,
CreateLDAPModArray(attributes, ModAttrib::Replace, storage),
NULL,
NULL,
&msgid);
if (errorNumber != LDAP_SUCCESS)
return FALSE;
P_timeval tval = timeout;
LDAPMessage * result = NULL;
ldap_result(ldapContext, msgid, LDAP_MSG_ALL, tval, &result);
if (result)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -