Fixed DevStudio 2003 build with memory check code.
[pwlib.git] / src / ptclib / pldap.cxx
blob1c7abb71be176b10604cf2812a757a27f5d781fa
1 /*
2 * pldap.cxx
4 * Lightweight Directory Access Protocol interface class.
6 * Portable Windows Library
8 * Copyright (c) 1993-2003 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.23 2007/09/08 11:34:28 rjongbloed
28 * Improved memory checking (leaks etc), especially when using MSVC debug library.
30 * Revision 1.22 2007/07/19 15:05:36 shorne
31 * Added Factory loaded LDAP schemas
33 * Revision 1.21 2007/04/20 07:23:53 csoutheren
34 * Applied 1703646 - Fixed behaviour of PLDAPSession::GetSearchResult
35 * Thanks to Fabrizio Ammollo
37 * Revision 1.20 2006/01/16 19:52:05 dsandras
38 * Applied patch from Brian Lu <brian lu sun com> to allow compilation on
39 * Solaris using SUN's LDAP. Thanks!!
41 * Revision 1.19 2005/09/18 13:01:43 dominance
42 * fixed pragma warnings when building with gcc.
44 * Revision 1.18 2005/08/31 15:21:34 dominance
45 * fix building with recent OpenLDAP
47 * Revision 1.17 2004/05/24 12:02:49 csoutheren
48 * Add function to permit setting a limit on the number of results returned
49 * from an LDAP query. Change the default number of results to unlimited,
50 * rather than MAX_INT which apparently is clamped to some arbitrary low value.
51 * Thanks to Damien Sandras
53 * Revision 1.16 2004/04/09 06:52:17 rjongbloed
54 * Removed #pargma linker command for /delayload of DLL as documentations sais that
55 * you cannot do this.
57 * Revision 1.15 2004/02/23 23:52:19 csoutheren
58 * Added pragmas to avoid every Windows application needing to include libs explicitly
60 * Revision 1.14 2004/02/04 09:37:00 rjongbloed
61 * Fixed memory leak and race condition, thanks Rossano Ravelli
63 * Revision 1.13 2004/01/17 17:45:29 csoutheren
64 * Changed to use PString::MakeEmpty
66 * Revision 1.12 2003/07/15 12:12:11 csoutheren
67 * Added support for multiple values in a single attribute string
68 * Thanks to Ravelli Rossano
70 * Revision 1.11 2003/07/12 00:10:40 csoutheren
71 * Fixed problem where Modify routines were calling Add, thanks to Ravelli Rossano
73 * Revision 1.10 2003/06/06 09:14:01 dsandras
75 * Test that a search result has been returned before calling ldapresult2error.
77 * Revision 1.9 2003/06/05 23:17:52 rjongbloed
78 * Changed default operation timeout to 30 seconds.
80 * Revision 1.8 2003/06/05 05:29:30 rjongbloed
81 * Fixed LDAP bind authentication methods, thanks Ravelli Rossano
83 * Revision 1.7 2003/04/17 08:34:48 robertj
84 * Changed LDAP structure output so if field is empty it leaves it out
85 * altogether rather then encoding an empty string, some servers barf.
87 * Revision 1.6 2003/04/16 08:00:19 robertj
88 * Windoes psuedo autoconf support
90 * Revision 1.5 2003/04/07 11:59:52 robertj
91 * Fixed search function returning an error if can't find anything for filter.
93 * Revision 1.4 2003/04/01 07:05:16 robertj
94 * Added ability to specify host:port in opening an LDAP server
96 * Revision 1.3 2003/03/31 03:32:53 robertj
97 * Major addition of functionality.
101 #ifdef __GNUC__
102 #pragma implementation "pldap.h"
103 #endif
105 #include <ptlib.h>
107 #include <ptlib/sockets.h>
108 #include <ptclib/pldap.h>
110 #define new PNEW
113 #if P_LDAP
115 #define LDAP_DEPRECATED 1
116 #include <ldap.h>
119 #if defined(_MSC_VER)
120 #pragma comment(lib, P_LDAP_LIBRARY)
121 #endif
123 ///////////////////////////////////////////////////////////////////////////////
125 PLDAPSession::PLDAPSession(const PString & baseDN)
126 : ldapContext(NULL),
127 errorNumber(LDAP_SUCCESS),
128 protocolVersion(LDAP_VERSION3),
129 defaultBaseDN(baseDN),
130 searchLimit(0),
131 timeout(0, 30),
132 multipleValueSeparator('\n')
137 PLDAPSession::~PLDAPSession()
139 Close();
143 BOOL PLDAPSession::Open(const PString & server, WORD port)
145 Close();
147 PString host = server;
148 PINDEX colon = server.Find(':');
149 if (colon != P_MAX_INDEX) {
150 host = server.Left(colon);
151 port = PIPSocket::GetPortByService(server.Mid(colon+1), "tcp");
154 ldapContext = ldap_init(server, port);
155 if (!IsOpen())
156 return FALSE;
158 SetOption(LDAP_OPT_PROTOCOL_VERSION, protocolVersion);
159 return TRUE;
163 BOOL PLDAPSession::Close()
165 if (!IsOpen())
166 return FALSE;
168 ldap_unbind(ldapContext);
169 ldapContext = NULL;
170 return TRUE;
174 BOOL PLDAPSession::SetOption(int optcode, int value)
176 if (!IsOpen())
177 return FALSE;
179 return ldap_set_option(ldapContext, optcode, &value);
183 BOOL PLDAPSession::SetOption(int optcode, void * value)
185 if (!IsOpen())
186 return FALSE;
188 return ldap_set_option(ldapContext, optcode, value);
192 BOOL PLDAPSession::Bind(const PString & who,
193 const PString & passwd,
194 AuthenticationMethod authMethod)
196 if (!IsOpen())
197 return FALSE;
199 const char * whoPtr;
200 if (who.IsEmpty())
201 whoPtr = NULL;
202 else
203 whoPtr = who;
205 #ifdef SOLARIS
206 static const int AuthMethodCode[NumAuthenticationMethod2] = {
207 LDAP_AUTH_SIMPLE, LDAP_AUTH_SASL, LDAP_AUTH_KRBV41_30, LDAP_AUTH_KRBV42_30
208 #else
209 static const int AuthMethodCode[NumAuthenticationMethod] = {
210 LDAP_AUTH_SIMPLE, LDAP_AUTH_SASL, LDAP_AUTH_KRBV4
211 #endif
213 errorNumber = ldap_bind_s(ldapContext, whoPtr, passwd, AuthMethodCode[authMethod]);
214 return errorNumber == LDAP_SUCCESS;
218 PLDAPSession::ModAttrib::ModAttrib(const PString & n, Operation o)
219 : name(n),
220 op(o)
225 void PLDAPSession::ModAttrib::SetLDAPMod(struct ldapmod & mod, Operation defaultOp)
227 mod.mod_type = (char *)(const char *)name;
229 Operation realOp = op == NumOperations ? defaultOp : op;
230 static const int OpCode[NumOperations] = {
231 LDAP_MOD_ADD, LDAP_MOD_REPLACE, LDAP_MOD_DELETE
233 mod.mod_op = OpCode[realOp];
235 if (IsBinary())
236 mod.mod_op |= LDAP_MOD_BVALUES;
238 SetLDAPModVars(mod);
242 PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
243 Operation op)
244 : ModAttrib(name, op)
249 PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
250 const PString & value,
251 Operation op)
252 : ModAttrib(name, op)
254 AddValue(value);
258 PLDAPSession::StringModAttrib::StringModAttrib(const PString & name,
259 const PStringList & vals,
260 Operation op)
261 : ModAttrib(name, op),
262 values(vals)
267 void PLDAPSession::StringModAttrib::SetValue(const PString & value)
269 values.RemoveAll();
270 values.AppendString(value);
274 void PLDAPSession::StringModAttrib::AddValue(const PString & value)
276 values.AppendString(value);
280 BOOL PLDAPSession::StringModAttrib::IsBinary() const
282 return FALSE;
286 void PLDAPSession::StringModAttrib::SetLDAPModVars(struct ldapmod & mod)
288 pointers.SetSize(values.GetSize()+1);
289 PINDEX i;
290 for (i = 0; i < values.GetSize(); i++)
291 pointers[i] = values[i].GetPointer();
292 pointers[i] = NULL;
293 mod.mod_values = pointers.GetPointer();
297 PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
298 Operation op)
299 : ModAttrib(name, op)
304 PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
305 const PBYTEArray & value,
306 Operation op)
307 : ModAttrib(name, op)
309 AddValue(value);
313 PLDAPSession::BinaryModAttrib::BinaryModAttrib(const PString & name,
314 const PList<PBYTEArray> & vals,
315 Operation op)
316 : ModAttrib(name, op),
317 values(vals)
322 void PLDAPSession::BinaryModAttrib::SetValue(const PBYTEArray & value)
324 values.RemoveAll();
325 values.Append(new PBYTEArray(value));
329 void PLDAPSession::BinaryModAttrib::AddValue(const PBYTEArray & value)
331 values.Append(new PBYTEArray(value));
335 BOOL PLDAPSession::BinaryModAttrib::IsBinary() const
337 return TRUE;
341 void PLDAPSession::BinaryModAttrib::SetLDAPModVars(struct ldapmod & mod)
343 pointers.SetSize(values.GetSize()+1);
344 bervals.SetSize(values.GetSize()*sizeof(berval));
345 berval * ber = (berval *)bervals.GetPointer();
346 PINDEX i;
347 for (i = 0; i < values.GetSize(); i++) {
348 ber[i].bv_val = (char *)values[i].GetPointer();
349 ber[i].bv_len = values[i].GetSize();
350 pointers[i] = &ber[i];
352 pointers[i] = NULL;
353 mod.mod_bvalues = pointers.GetPointer();
357 static LDAPMod ** CreateLDAPModArray(const PList<PLDAPSession::ModAttrib> & attributes,
358 PLDAPSession::ModAttrib::Operation defaultOp,
359 PBYTEArray & storage)
361 PINDEX count = attributes.GetSize();
362 storage.SetSize(count*sizeof(LDAPMod) + (count+1)*sizeof(LDAPMod *));
364 LDAPMod ** attrs = (LDAPMod **)storage.GetPointer();
365 LDAPMod * attr = (LDAPMod * )&attrs[count+1];
366 for (PINDEX i = 0; i < count; i++) {
367 attrs[i] = &attr[i];
368 attributes[i].SetLDAPMod(attr[i], defaultOp);
371 return attrs;
375 static PList<PLDAPSession::ModAttrib> AttribsFromDict(const PStringToString & attributes)
377 PList<PLDAPSession::ModAttrib> attrs;
379 for (PINDEX i = 0; i < attributes.GetSize(); i++)
380 attrs.Append(new PLDAPSession::StringModAttrib(attributes.GetKeyAt(i),
381 attributes.GetDataAt(i).Lines()));
383 return attrs;
387 static PList<PLDAPSession::ModAttrib> AttribsFromArray(const PStringArray & attributes)
389 PList<PLDAPSession::ModAttrib> attrs;
391 for (PINDEX i = 0; i < attributes.GetSize(); i++) {
392 PString attr = attributes[i];
393 PINDEX equal = attr.Find('=');
394 if (equal != P_MAX_INDEX)
395 attrs.Append(new PLDAPSession::StringModAttrib(attr.Left(equal),
396 attr.Mid(equal+1).Lines()));
399 return attrs;
403 static PList<PLDAPSession::ModAttrib> AttribsFromStruct(const PLDAPStructBase & attributes)
405 PList<PLDAPSession::ModAttrib> attrs;
407 for (PINDEX i = 0; i < attributes.GetNumAttributes(); i++) {
408 PLDAPAttributeBase & attr = attributes.GetAttribute(i);
409 if (attr.IsBinary())
410 attrs.Append(new PLDAPSession::BinaryModAttrib(attr.GetName(), attr.ToBinary()));
411 else {
412 PString str = attr.ToString();
413 if (!str)
414 attrs.Append(new PLDAPSession::StringModAttrib(attr.GetName(), str));
418 return attrs;
422 BOOL PLDAPSession::Add(const PString & dn, const PList<ModAttrib> & attributes)
424 if (!IsOpen())
425 return FALSE;
427 PBYTEArray storage;
428 int msgid;
429 errorNumber = ldap_add_ext(ldapContext,
431 CreateLDAPModArray(attributes, ModAttrib::Add, storage),
432 NULL,
433 NULL,
434 &msgid);
435 if (errorNumber != LDAP_SUCCESS)
436 return FALSE;
438 P_timeval tval = timeout;
439 LDAPMessage * result = NULL;
440 ldap_result(ldapContext, msgid, LDAP_MSG_ALL, tval, &result);
441 if (result)
442 errorNumber = ldap_result2error(ldapContext, result, TRUE);
444 return errorNumber == LDAP_SUCCESS;
448 BOOL PLDAPSession::Add(const PString & dn, const PStringToString & attributes)
450 return Add(dn, AttribsFromDict(attributes));
454 BOOL PLDAPSession::Add(const PString & dn, const PStringArray & attributes)
456 return Add(dn, AttribsFromArray(attributes));
460 BOOL PLDAPSession::Add(const PString & dn, const PLDAPStructBase & attributes)
462 return Add(dn, AttribsFromStruct(attributes));
466 BOOL PLDAPSession::Modify(const PString & dn, const PList<ModAttrib> & attributes)
468 if (!IsOpen())
469 return FALSE;
471 PBYTEArray storage;
472 int msgid;
473 errorNumber = ldap_modify_ext(ldapContext,
475 CreateLDAPModArray(attributes, ModAttrib::Replace, storage),
476 NULL,
477 NULL,
478 &msgid);
479 if (errorNumber != LDAP_SUCCESS)
480 return FALSE;
482 P_timeval tval = timeout;
483 LDAPMessage * result = NULL;
484 ldap_result(ldapContext, msgid, LDAP_MSG_ALL, tval, &result);
485 if (result)
486 errorNumber = ldap_result2error(ldapContext, result, TRUE);
488 return errorNumber == LDAP_SUCCESS;
492 BOOL PLDAPSession::Modify(const PString & dn, const PStringToString & attributes)
494 return Modify(dn, AttribsFromDict(attributes));
498 BOOL PLDAPSession::Modify(const PString & dn, const PStringArray & attributes)
500 return Modify(dn, AttribsFromArray(attributes));
504 BOOL PLDAPSession::Modify(const PString & dn, const PLDAPStructBase & attributes)
506 return Modify(dn, AttribsFromStruct(attributes));
510 BOOL PLDAPSession::Delete(const PString & dn)
512 if (!IsOpen())
513 return FALSE;
515 int msgid;
516 errorNumber = ldap_delete_ext(ldapContext, dn, NULL, NULL, &msgid);
517 if (errorNumber != LDAP_SUCCESS)
518 return FALSE;
520 P_timeval tval = timeout;
521 LDAPMessage * result = NULL;
522 ldap_result(ldapContext, msgid, LDAP_MSG_ALL, tval, &result);
523 if (result)
524 errorNumber = ldap_result2error(ldapContext, result, TRUE);
526 return errorNumber == LDAP_SUCCESS;
530 PLDAPSession::SearchContext::SearchContext()
532 result = NULL;
533 message = NULL;
534 found = FALSE;
535 completed = FALSE;
539 PLDAPSession::SearchContext::~SearchContext()
541 if (message != NULL)
542 ldap_msgfree(message);
544 if (result != NULL && result != message)
545 ldap_msgfree(result);
549 BOOL PLDAPSession::Search(SearchContext & context,
550 const PString & filter,
551 const PStringArray & attributes,
552 const PString & baseDN,
553 SearchScope scope)
555 if (!IsOpen())
556 return FALSE;
558 PCharArray storage;
559 char ** attribs = attributes.ToCharArray(&storage);
561 PString base = baseDN;
562 if (base.IsEmpty())
563 base = defaultBaseDN;
565 static const int ScopeCode[NumSearchScope] = {
566 LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
569 P_timeval tval = timeout;
571 errorNumber = ldap_search_ext(ldapContext,
572 base,
573 ScopeCode[scope],
574 filter,
575 attribs,
576 FALSE,
577 NULL,
578 NULL,
579 tval,
580 searchLimit,
581 &context.msgid);
583 if (errorNumber != LDAP_SUCCESS)
584 return FALSE;
586 if (ldap_result(ldapContext, context.msgid, LDAP_MSG_ONE, tval, &context.result) > 0)
587 return GetNextSearchResult(context);
589 if (context.result)
590 errorNumber = ldap_result2error(ldapContext, context.result, TRUE);
591 if (errorNumber == 0)
592 errorNumber = LDAP_OTHER;
593 return FALSE;
597 BOOL PLDAPSession::GetSearchResult(SearchContext & context, PStringToString & data)
599 data.RemoveAll();
601 if (!IsOpen())
602 return FALSE;
604 if (context.result == NULL || context.message == NULL || context.completed)
605 return FALSE;
607 // Extract the resulting data
609 data.SetAt("dn", GetSearchResultDN(context));
611 BerElement * ber = NULL;
612 char * attrib = ldap_first_attribute(ldapContext, context.message, &ber);
613 while (attrib != NULL) {
615 struct berval ** bvals = ldap_get_values_len(ldapContext, context.message, attrib);
616 if (bvals != NULL) {
617 PString value = data(attrib);
619 for (PINDEX i = 0; bvals[i] != NULL; i++ ) {
620 if (!value)
621 value += multipleValueSeparator;
622 value += PString(bvals[i]->bv_val, bvals[i]->bv_len);
624 ber_bvecfree(bvals);
626 data.SetAt(attrib, value);
629 ldap_memfree(attrib);
630 attrib = ldap_next_attribute(ldapContext, context.message, ber);
633 if (ber != NULL)
634 ber_free (ber, 0);
636 return TRUE;
640 BOOL PLDAPSession::GetSearchResult(SearchContext & context,
641 const PString & attribute,
642 PString & data)
644 data.MakeEmpty();
646 if (!IsOpen())
647 return FALSE;
649 if (context.result == NULL || context.message == NULL || context.completed)
650 return FALSE;
652 if (attribute == "dn") {
653 data = GetSearchResultDN(context);
654 return TRUE;
657 char ** values = ldap_get_values(ldapContext, context.message, attribute);
658 if (values == NULL)
659 return FALSE;
661 PINDEX count = ldap_count_values(values);
662 for (PINDEX i = 0; i < count; i++) {
663 if (!data)
664 data += multipleValueSeparator;
665 data += values[i];
668 ldap_value_free(values);
669 return TRUE;
673 BOOL PLDAPSession::GetSearchResult(SearchContext & context,
674 const PString & attribute,
675 PStringArray & data)
677 data.RemoveAll();
679 if (!IsOpen())
680 return FALSE;
682 if (context.result == NULL || context.message == NULL || context.completed)
683 return FALSE;
685 if (attribute == "dn") {
686 data.SetSize(1);
687 data[0] = GetSearchResultDN(context);
688 return TRUE;
691 char ** values = ldap_get_values(ldapContext, context.message, attribute);
692 if (values == NULL)
693 return FALSE;
695 PINDEX count = ldap_count_values(values);
696 data.SetSize(count);
697 for (PINDEX i = 0; i < count; i++)
698 data[i] = values[i];
700 ldap_value_free(values);
701 return TRUE;
705 BOOL PLDAPSession::GetSearchResult(SearchContext & context,
706 const PString & attribute,
707 PArray<PBYTEArray> & data)
709 data.RemoveAll();
711 if (!IsOpen())
712 return FALSE;
714 if (attribute == "dn") {
715 char * dn = ldap_get_dn(ldapContext, context.message);
716 data.Append(new PBYTEArray((const BYTE *)dn, ::strlen(dn)));
717 ldap_memfree(dn);
718 return TRUE;
721 struct berval ** values = ldap_get_values_len(ldapContext, context.message, attribute);
722 if (values == NULL)
723 return FALSE;
725 PINDEX count = ldap_count_values_len(values);
726 data.SetSize(count);
727 for (PINDEX i = 0; i < count; i++) {
728 PBYTEArray* dataPtr = new PBYTEArray(values[i]->bv_len);
729 data.SetAt(i, dataPtr);
731 memcpy(data[i].GetPointer(), (const BYTE *)values[i]->bv_val, values[i]->bv_len);
734 ldap_value_free_len(values);
735 return TRUE;
739 BOOL PLDAPSession::GetSearchResult(SearchContext & context,
740 PLDAPStructBase & data)
742 if (!IsOpen())
743 return FALSE;
745 BOOL atLeastOne = FALSE;
747 for (PINDEX i = 0; i < data.GetNumAttributes(); i++) {
748 PLDAPAttributeBase & attr = data.GetAttribute(i);
749 if (attr.IsBinary()) {
750 PArray<PBYTEArray> bin;
751 if (GetSearchResult(context, attr.GetName(), bin)) {
752 attr.FromBinary(bin);
753 atLeastOne = TRUE;
756 else {
757 PString str;
758 if (GetSearchResult(context, attr.GetName(), str)) {
759 attr.FromString(str);
760 atLeastOne = TRUE;
765 return atLeastOne;
769 PString PLDAPSession::GetSearchResultDN(SearchContext & context)
771 PString str;
773 if (context.message != NULL) {
774 char * dn = ldap_get_dn(ldapContext, context.message);
775 if (dn != NULL) {
776 str = dn;
777 ldap_memfree(dn);
781 return str;
785 BOOL PLDAPSession::GetNextSearchResult(SearchContext & context)
787 if (!IsOpen())
788 return FALSE;
790 if (context.result == NULL || context.completed)
791 return FALSE;
793 P_timeval tval = timeout;
794 do {
795 if (context.message == NULL)
796 context.message = ldap_first_message(ldapContext, context.result);
797 else
798 context.message = ldap_next_message(ldapContext, context.message);
800 if (context.message != NULL) {
801 switch (ldap_msgtype(context.message)) {
802 case LDAP_RES_SEARCH_ENTRY :
803 context.found = TRUE;
804 errorNumber = LDAP_SUCCESS;
805 return TRUE;
807 case LDAP_RES_SEARCH_RESULT :
808 errorNumber = ldap_result2error(ldapContext, context.message, FALSE);
809 if (errorNumber == 0 && !context.found)
810 errorNumber = LDAP_NO_RESULTS_RETURNED;
811 context.completed = TRUE;
812 return FALSE;
814 // Ignore other result message types for now ...
817 ldap_msgfree(context.result);
818 } while (ldap_result(ldapContext, context.msgid, LDAP_MSG_ONE, tval, &context.result) > 0);
820 if (context.result)
821 errorNumber = ldap_result2error(ldapContext, context.result, FALSE);
822 if (errorNumber == 0)
823 errorNumber = LDAP_OTHER;
824 return FALSE;
828 PList<PStringToString> PLDAPSession::Search(const PString & filter,
829 const PStringArray & attributes,
830 const PString & base,
831 SearchScope scope)
833 PList<PStringToString> data;
835 SearchContext context;
836 if (!Search(context, filter, attributes, base, scope))
837 return data;
839 do {
840 PStringToString * entry = new PStringToString;
841 if (GetSearchResult(context, *entry))
842 data.Append(entry);
843 else {
844 delete entry;
845 break;
847 } while (GetNextSearchResult(context));
849 return data;
853 PString PLDAPSession::GetErrorText() const
855 return ldap_err2string(errorNumber);
859 ///////////////////////////////////////////////////////////////////////////////
861 PLDAPAttributeBase::PLDAPAttributeBase(const char * n, void * ptr, PINDEX sz)
862 : name(n),
863 pointer(ptr),
864 size(sz)
866 PLDAPStructBase::GetInitialiser().AddAttribute(this);
870 PString PLDAPAttributeBase::ToString() const
872 PStringStream stream;
873 PrintOn(stream);
874 return stream;
878 void PLDAPAttributeBase::FromString(const PString & str)
880 PStringStream stream(str);
881 ReadFrom(stream);
885 PBYTEArray PLDAPAttributeBase::ToBinary() const
887 return PBYTEArray((const BYTE *)pointer, size, FALSE);
891 void PLDAPAttributeBase::FromBinary(const PArray<PBYTEArray> & data)
893 if (data.GetSize() > 0 && data[0].GetSize() == size)
894 memcpy(pointer, data[0], size);
898 ///////////////////////////////////////////////////////////////////////////////
900 PMutex PLDAPStructBase::initialiserMutex;
901 PLDAPStructBase * PLDAPStructBase::initialiserInstance;
903 PLDAPStructBase::PLDAPStructBase()
905 attributes.DisallowDeleteObjects();
907 initialiserMutex.Wait();
908 initialiserStack = initialiserInstance;
909 initialiserInstance = this;
913 PLDAPStructBase & PLDAPStructBase::operator=(const PLDAPStructBase & other)
915 for (PINDEX i = 0; i < attributes.GetSize(); i++)
916 attributes.GetDataAt(i).Copy(other.attributes.GetDataAt(i));
918 return *this;
922 PLDAPStructBase & PLDAPStructBase::operator=(const PStringArray & array)
924 for (PINDEX i = 0; i < array.GetSize(); i++) {
925 PString str = array[i];
926 PINDEX equal = str.Find('=');
927 if (equal != P_MAX_INDEX) {
928 PLDAPAttributeBase * attr = GetAttribute(str.Left(equal));
929 if (attr != NULL)
930 attr->FromString(str.Mid(equal+1));
933 return *this;
937 PLDAPStructBase & PLDAPStructBase::operator=(const PStringToString & dict)
939 for (PINDEX i = 0; i < dict.GetSize(); i++) {
940 PLDAPAttributeBase * attr = GetAttribute(dict.GetKeyAt(i));
941 if (attr != NULL)
942 attr->FromString(dict.GetDataAt(i));
944 return *this;
948 void PLDAPStructBase::PrintOn(ostream & strm) const
950 strm << attributes << '\n';
954 void PLDAPStructBase::AddAttribute(PLDAPAttributeBase * attr)
956 attributes.SetAt(attr->GetName(), attr);
960 void PLDAPStructBase::EndConstructor()
962 initialiserInstance = initialiserStack;
963 initialiserMutex.Signal();
966 ///////////////////////////////////////////////////////////////////
968 static const char PLDAPSchemaPluginBaseClass[] = "PLDAPSchema";
970 template <> PLDAPSchema * PDevicePluginFactory<PLDAPSchema>::Worker::Create(const PString & type) const
972 return PLDAPSchema::CreateSchema(type);
975 PLDAPSchema::PLDAPSchema()
979 PLDAPSchema::Attribute::Attribute(const PString & name, AttributeType type)
980 : m_name(name),m_type(type)
984 void PLDAPSchema::LoadSchema()
986 AttributeList(attributelist);
989 PLDAPSchema * PLDAPSchema::CreateSchema(const PString & schemaname, PPluginManager * pluginMgr)
991 if (pluginMgr == NULL)
992 pluginMgr = &PPluginManager::GetPluginManager();
994 return (PLDAPSchema *)pluginMgr->CreatePluginsDeviceByName(schemaname, PLDAPSchemaPluginBaseClass);
997 PStringList PLDAPSchema::GetSchemaNames(PPluginManager * pluginMgr)
999 if (pluginMgr == NULL)
1000 pluginMgr = &PPluginManager::GetPluginManager();
1002 return pluginMgr->GetPluginsProviding(PLDAPSchemaPluginBaseClass);
1005 PStringList PLDAPSchema::GetSchemaFriendlyNames(const PString & schema, PPluginManager * pluginMgr)
1007 if (pluginMgr == NULL)
1008 pluginMgr = &PPluginManager::GetPluginManager();
1010 return pluginMgr->GetPluginsDeviceNames(schema, PLDAPSchemaPluginBaseClass);
1013 void PLDAPSchema::OnReceivedAttribute(const PString & attribute, const PString & value)
1015 SetAttribute(attribute,value);
1018 BOOL PLDAPSchema::SetAttribute(const PString & attribute, const PString & value)
1021 for (std::list<Attribute>::const_iterator r = attributelist.begin(); r != attributelist.end(); ++r) {
1022 if ((r->m_name == attribute) && (r->m_type != AttributeBinary)) {
1023 attributes.insert(make_pair(attribute,value));
1024 PTRACE(4, "schema\tMatch " << attribute);
1025 return TRUE;
1029 return FALSE;
1032 BOOL PLDAPSchema::SetAttribute(const PString & attribute, const PBYTEArray & value)
1034 for (std::list<Attribute>::const_iterator r = attributelist.begin(); r != attributelist.end(); ++r) {
1035 if ((r->m_name == attribute) && (r->m_type == AttributeBinary)) {
1036 binattributes.insert(make_pair(attribute,value));
1037 PTRACE(4, "schema\tMatch Binary " << attribute);
1038 return TRUE;
1042 return FALSE;
1045 BOOL PLDAPSchema::GetAttribute(const PString & attribute, PString & value)
1047 for (ldapAttributes::const_iterator r = attributes.begin(); r != attributes.end(); ++r) {
1048 if (r->first == attribute) {
1049 value = r->second;
1050 return TRUE;
1053 return FALSE;
1056 BOOL PLDAPSchema::GetAttribute(const PString & attribute, PBYTEArray & value)
1058 for (ldapBinAttributes::const_iterator r = binattributes.begin(); r != binattributes.end(); ++r) {
1059 if (r->first == attribute) {
1060 value = r->second;
1061 return TRUE;
1064 return FALSE;
1067 PStringList PLDAPSchema::GetAttributeList()
1069 PStringList att;
1070 for (std::list<Attribute>::iterator r = attributelist.begin(); r != attributelist.end(); ++r) {
1071 att.AppendString(r->m_name);
1073 return att;
1076 BOOL PLDAPSchema::Exists(const PString & attribute)
1078 for (std::list<Attribute>::const_iterator r = attributelist.begin(); r != attributelist.end(); ++r) {
1079 if (r->m_name == attribute) {
1080 if (r->m_type == AttributeString) {
1081 for (ldapAttributes::const_iterator r = attributes.begin(); r != attributes.end(); ++r) {
1082 if (r->first == attribute)
1083 return TRUE;
1085 } else if (r->m_type == AttributeBinary) {
1086 for (ldapBinAttributes::const_iterator r = binattributes.begin(); r != binattributes.end(); ++r) {
1087 if (r->first == attribute)
1088 return TRUE;
1093 return FALSE;
1096 PLDAPSchema::AttributeType PLDAPSchema::GetAttributeType(const PString & attribute)
1098 for (std::list<Attribute>::const_iterator r = attributelist.begin(); r != attributelist.end(); ++r) {
1099 if (r->m_name == attribute)
1100 return (AttributeType)r->m_type;
1102 return AttibuteUnknown;
1105 void PLDAPSchema::OnSendSchema(PList<PLDAPSession::ModAttrib> & attrib, PLDAPSession::ModAttrib::Operation op)
1107 for (ldapAttributes::const_iterator r = attributes.begin(); r != attributes.end(); ++r)
1108 attrib.Append(new PLDAPSession::StringModAttrib(r->first,r->second,op));
1110 for (ldapBinAttributes::const_iterator s = binattributes.begin(); s != binattributes.end(); ++s) {
1111 attrib.Append(new PLDAPSession::BinaryModAttrib(s->first,s->second,op));
1116 #endif // P_LDAP
1119 // End of file ////////////////////////////////////////////////////////////////