perl-mozldap-1.5.3/0000775000076400007640000000000011426105703012573 5ustar richrichperl-mozldap-1.5.3/ChangeLog0000444000076400007640000006205010176311136014344 0ustar richrich2005-01-27 Leif Hedstrom * Conn.pm (new): Fixed the nspr option to truly be an on/off flag, if we need to support shared in the future, we can do so with another option. * typemap: Kludgy fix for "void *", used for the prldap options. * API.xs: Made it work properly, the arguments were totally wrong. * Conn.pm (new): Added support for the timeout (for NSPR enabled connections only!). (init): Honor this timeout option. (setNSPRTimeout): Fix for sending down the timeout options. (installNSPR): The "shared" argument wasn't properly passed down to the API when used on an established connection. 2005-01-05 Leif Hedstrom * Conn.pm (init): Bad "my" declaration. 2005-01-04 Leif Hedstrom * LDIF.pm: Changed all calls to new to use the class method directly. * Utils.pm: Changed all calls to new to use the class method directly. * Entry.pm: Changed all calls to new to use the class method directly. * Conn.pm: Changed all calls to new to use the class method directly. * Makefile.PL: Fixes for missing NSPR libraries, even though the prldap libraries are available... 2004-12-28 Leif Hedstrom * Conn.pm (new): Added the entryclass argument. (newEntry): Honor the new entryclass setting. (nextEntry): Ditto. (delete): Changed to check if the provided entry is proper Mozilla::LDAP::Entry (or subclass) type. (add): Ditto. 2004-11-02 Leif Hedstrom * API.xs (internal_sortcmp_proc): Added support for Perl sort functions. (ldap_multi_sort_entries): Ditto. (ldap_sort_entries): Ditto. * Conn.pm: Cleaned up NSPR code, fixed some bugs. (search): Added support for sortattrs, using multisort. (search): Fixed parsing of the attrs. (setOption): Set an "arbitrary" option. (getOption): Getter. (setSizelimit): Set the sizelimit. (getSizelimit): Getter. (init): Added the callback, this has at least the potential of making it possible to parse some server controls as returned by the asyncronous bind. (setOption): Added support for hash style arguments. 2004-10-28 Leif Hedstrom * Entry.pm (attrModified): Removed some dead code. * Conn.pm (add): Fixed so we don't try to add attributes that have been deleted (From Donaldo). 2004-10-19 Leif Hedstrom * Conn.pm (new): Add NSPR option. (installNSPR): Try to fix the problem by rebinding if this is called. (installNSPR): Now works as a class (static) method. 2004-10-17 Leif Hedstrom * Conn.pm (close): Removed $ret, it was always 1 anyways. * Entry.pm (move): Added support for hash-style arguments. (copy): Added support for hash-style arguments. (removeValue): Added support for hash-style arguments, cleaned up some local variable statements. (removeDNValue): Added support for hash-style arguments. (addValue): Added support for hash-style arguments. (addDNValue): Added support for hash-style arguments (getValues): Cleaned up arguments. (hasValue): Added support for hash-style arguments. (hasValue): Make sure to lower-case the attribute, this was a bug. (hasDNValue): Support hash-style arguments. (matchValue): Support hash-style arguments. (matchDNValue): Support hash-style arguments. (setDN): Support hash-style arguments. 2004-10-15 Leif Hedstrom * API.xs (prldap_set_session_option): New function to set the IO timeout option when using NSPR I/O etc.. * API.pm: Fixed all indentation, added PRLDAP_OPT_IO_MAX_TIMEOUT and prldap_get_session_option. * constant.h (constant): Fixed indentation, and added PRLDAP_OPT_IO_MAX_TIMEOUT. 2004-10-14 Leif Hedstrom * Entry.pm (isEntryModified): Added new method, which indicates that something in the entry has been modified. * Conn.pm (newEntry): You can now provide the DN as an argument. * Entry.pm (unRemove): Fixed, old bug solved by Kevin... * Conn.pm (newEntry): Simplified this to use the normal constructor. (searchURL): Avoid the warnings... * Entry.pm (DESTROY): Fixed core dump during destructor. * Conn.pm (getErrorCode): Added support for hash-style args. (browse): Added support for hash-style args. (browse): The hash-style arguments now also supports attrsonly. (compare): Added hash-style args. (search): Got rid of the annoying warning finally, for undefined hash value. * API.xs (prldap_install_routines): New function, to modify an existing LDAP * handle (ld) to use NSPR I/O, threading etc. * API.pm: Added the NSPR section to symbols. * Conn.pm (installNSPR): Added this function, to support NSPR. * Makefile.PL: Added all the NSPR/NSS dependt libraries as well, for better compiling results. * Conn.pm (getVersion): Added this getter as well. * Makefile.PL: Added LD_RUN_PATH stuff. 2004-10-13 Leif Hedstrom * Conn.pm (search): Fix for bug 4633, we can now return some number of entries even if we hit SIZE/TIME-LIMIT. (searchURL): Dito. (getErrorCode): Dito. (getErrorString): Dito. (modifyRDN): Changed argument handling. (search): Support hash style arguments now. (searchURL): Support hash style arguments. * Entry.pm (addDNValue): Added a "nocase" (optional) argument. (addValue): Dito. * Conn.pm (setVersion): New function, change the LDAP protocol version on the connection. (update): Performance optimization, faster check if the %mod structure is empty or not. (update): Fix for bug #77368, $conn->update() returns false if there are no changes being made. Seems more reasonable to not consider that a failure I think. (update): Changed to use ldap_modify_ext_s(). * Utils.pm (ldapArgs): Added support for -V, and defaulting to LDAP v3 now. 2003-06-24 Leif Hedstrom * Makefile.PL: Lots of changes to support modern C-SDK. 2003-06-24 Leif Hedstrom * API.xs, typemap: Changed `na' to `PL_na'. This means we now only support Perl 5.005 or later. 2000-09-19 Leif Hedstrom * Conn.pm (update): Bug fix to allow us to delete() an attribute, call update(), and then add new values (or the same values...) to the entry again. 2000-09-19 Leif Hedstrom * Entry.pm (DESTROY): Bug fix from daniel.hams@db.com (Daniel Hams) to avoid warnings from Apache and mod_perl. 2000-09-13 Leif Hedstrom * Utils.pm (askPassword): Oops, stupid typo here, should be "unless $prompt" of course... 2000-09-13 Leif Hedstrom * Entry.pm (isDeleted): Removed a test which made this function not working at all... :) 2000-09-13 Leif Hedstrom * Removed an if defined() to avoid warnings with Perl v5.6. 2000-06-24 Wolfram Schmidt * Entry.pm (FIRSTKEY): Fix bug for deleting all attributes and calling keys. 2000-05-30 Kevin McCarthy * Makefile.PL: Added fix so API.xs compiles under Perl 5.6 (POLLUTE=>1) 2000-05-30 Leif Hedstrom * Lots of small fixes... 1999-09-07 Leif Hedstrom * API.xs (avref2charptrptr): Fixed potential core dump, if the argument passed wasn't a proper array. (avref2berptrptr): Ditto. 1999-09-06 Leif Hedstrom * Conn.pm (search): Removed $res and $resv, set the internal data element directly. (searchURL): Ditto. 1999-08-25 John Kristian * Entry.pm (printLDIF): Bug fix. * LDIF.pm: Cleaned out memory leaks. 1999-08-24 Leif Hedstrom * Merged v1.3.x into trunk, tagged it as v1.4, and released it! 1999-08-19 Leif Hedstrom * Changed internal version numbering again, just called this plain v1.4. * Entry.pm (FIRSTKEY): Bug fix, we'd crap out if there are no attributes in the returned entry. (NEXTKEY): Ditto. 1999-08-18 Leif Hedstrom * Set version number to v1.4! Woohoo! Also tagged it as v1.3.4, last "development" release. 1999-08-17 Leif Hedstrom * Makefile.PL: Fixes for Windows/NT, cleaned out some code etc. (MY::postamble): Support for "make html". * MANIFEST: Updated with all new files etc. * test.pl: Renamed to oldtest.pl, to avoid "make test" to fail. 1999-08-16 Kevin McCarthy and Leif Hedstrom * API.xs: Cleaned most all the memory allocation changes, we are changing it to use the LDAP_OPT_MEMALLOC_FN_PTRS option in the C-SDK instead (much cleaner!). (perldap_init): New function, set up the memory management handlers. This is called when the API module is loaded. (perldap_malloc): New function, our memory management method(s). (perldap_calloc): Ditto. (perldap_realloc): Ditto. (perldap_free): Ditto. 1999-08-16 Kevin McCarthy * API.xs: Cleaned up prototypes, changed strdup() to use a Perl'ified version, change a number of free()'s to use Safefree. (ldap_value_free_perl): New function, similar to ldap_mods_free_perl(), to avoid memory problems (on NT and ActivePerl primarily). (StrDup): New function, to handle strdup() calls in a safe way. (ber_bvfree_perl): Ditto. (ber_bvecfree_perl): Ditto. 1999-08-15 Leif Hedstrom * API.xs (ldap_mods_free_perl): Modified version of ldap_mods_free(), which uses Perl native free method instead of the things from the LDAP SDK. This fixes some nasty issues with Windows/NT and ActiveState Perl. Woohoo!!! 1999-08-14 Leif Hedstrom and Kevin McCarthy * Entry.pm (setValues): Implemented bug fix for bug id 7131, where the "_save_" structures weren't set properly when using setValues(). 1999-08-14 Kevin McCarthy * Conn.pm (update): Rewrote to optimize add/remove vs replace operations. Basically, we'll try to do whatever seems to be the smallest amount of work for the LDAP server now. 1999-08-13 Leif Hedstrom * Makefile.PL: Cleaned up code, and added support for linking in the missing libraries need for some missing symbols. 1999-08-13 Michelle Wyner * Entry.pm: Updated documentation, and cleaned it up. * Conn.pm: Ditto. 1999-08-12 Leif Hedstrom * Entry.pm (move): Changed name, was rename(), is now move(). 1999-08-10 Leif Hedstrom * Entry.pm (setValues): Renamed, used to be setValue(), which is now an alias to setValues(). (getValues): New method, to get the array of values. (STORE): Fixed tests around DN handling, making sure it's not treated as an array. I also optimized a couple of tests, since we now filter out "DN" earlier in the funtion(s). (attrModified): Ditto. (attrClean): Ditto. (unRemove): Ditto. (removeValue): Ditto. (addValue): Ditto. 1999-08-08 Leif Hedstrom and Kevin McCarthy * Entry.pm (setValue): Remove _delete_ flag, if set. * Conn.pm (close): Fixed memory leak, moved code from the DESTROY method over here. (DESTROY): Call the close() method. (getErrorCode): We now return LDAP_SUCCESS if there is no LDAP connection handle. (getErrorString): Ditto. * Entry.pm (STORE): Bug fix for large attribute sets. (attrModified): Ditto. (removeValue): Ditto. (addValue): Ditto. (EXISTS): Fix for bug 4368, cleaning up the code, and avoid the double calls. 1999-08-06 Leif Hedstrom and Kevin McCarthy * API.xs: Added some more tests around free() statements. These are most likely never triggered, but better safe than sorrow (and the overhead of testing this is insignificant). * Conn.pm (browse): Added this function, to make it easy to browse an entry. (compare): Compare an attribute value against a DN/entry, without having to do the search. * Entry.pm (removeValue): Fixed loop bug. (addValue): Ditto. (hasValue): Ditto. (matchValue): Fixed loop bug, and also missing normalization in half of the case statement. (rename): Added this new method, to rename attributes. (copy): Added, to copy attributes. * Merged v1.2.3 with v1.3 branch. 1999-08-06 Kevin McCarthy * Entry.pm (addDNValue): Bug fix, index for norm was wrong. * Entry.pm (size): Optimzied for performance. 1999-07-25 Kevin McCarthy * API.xs: Fixed memory allocation problems in parsing and generating the LDAPMods structure. 1999-06-22 Leif Hedstrom * Conn.pm (add): Fixed bug 3342, thanks to Kevin McCarthy for debugging this, and providing a patch. This fixes the problem with adding new entries that has binary data. 1999-03-23 Leif Hedstrom * Changed versioning numbers for all .pm files. 1999-03-22 Leif Hedstrom * Entry.pm: Removed all _self_obj_ stuff... * Conn.pm: Ditto. * Conn.pm: Cleanup in use statements, and "use strict". (search): Avoid warnings of uninitialized variables. (searchURL): Ditto. (modifyRDN): Bugfix, we did not update the appropriate DN in the self object (very minor...). * Entry.pm: Cleanup in use statements, and "use strict". (BEGIN): Added this initializer, to use the new LDIF module. (STORE): Fixed bug where we would not ignore the internal instance variables properly. * Utils.pm: Cleanup in all use statements, and "use strict". Also enforces the VERSION control feature. * Merged v1.2.1 to devel-branch-1_3, and tagged v1.3.1. 1999-03-21 Leif Hedstrom * Checked in v1.2.1(beta). 1999-03-19 Leif Hedstrom * Conn.pm (add): Fixed the code so that it will handle hash array, as the documentation indicates. (Pointed out by Kevin Burns). (add): Code cleanup in the add() method. 1999-03-18 Leif Hedstrom * Entry.pm: Changed back some of the "my" definitions, to make sure arrays are properly reset. (setValue): Added the _modified_ flag, from Stephen P. Schaefer . (addValue): Bug fix, when calling delete, and then addValue(). From Stephen P. Schaefer as well. * Conn.pm: Ditto. This fixes the bug where qsearch/printLDIF() would print multiple values. 1999-03-12 Leif Hedstrom * Conn.pm: Changed docs for modifyRDN(), it was wrong... 1999-03-11 Leif Hedstrom * Entry.pm (new): Added this method, so that "new ...::Entry" will work as expected. 1999-03-09 Leif Hedstrom * Entry.pm: Tons of changes to handling the save/modified/deleted attribute values. (DESTROY): Added this destructor again, this time it does seem to help quite a lot! Whoohoo... * Conn.pm (update): Bug fix for bug #2530, keeping sort order for attribute values. 1999-03-08 Leif Hedstrom * Entry.pm (unRemove): Bug fix, this was terribly horked, please let's try it to make sure it works... * Conn.pm (newEntry): Bug fix, forgot to give it the self_obj member value... Sigh. 1999-03-05 Leif Hedstrom * Entry.pm (DELETE): We now handle the event that someone tries to delete an internal attribute. * Conn.pm (update): Bug: We forgot to test for existance of "_save_" before trying to loop over it. * Entry.pm (attrClean): Added this method, to make it easier to reset the internal state of en Entry. This is used primarily by the Conn.pm package. (unRemove): Bug Fix: $selfl changed to $self... 1999-02-28 Leif Hedstrom * Entry.pm (matchValue): Added support for the normalization, which should have been done before... Bug #2854. * Conn.pm (printError): Changed to use ldap_err2string instead of ldap_perror. * Utils.pm (ldapArgs): Changed "root" to "base" in the LD structure. (userCredentials): Ditto. * Conn.pm: Changed documentation to reflect the "base/root" change. 1999-01-06 Leif Hedstrom * Conn.pm (nextEntry): Fixed (tried to fix...) the bug with missing attributes. I hope this will work, at a minimum I'm sure it won't hurt. The idea is to keep the case on the attribute type when requesting the values_len(). 1999-01-11 Leif Hedstrom * API.xs: Added IF statements around all ldap_value_free() calls. 1999-01-05 Leif Hedstrom * Conn.pm (getRes): Ooops, didn't return the appropriate value... :( (init): Changed test for LDAP_SUCCESS, to always return 0 or 1. (close): Ditto. (delete): Ditto. (add): Ditto. (modifyRDN): Ditto. (update): Ditto. (simpleAuth): Ditto. * Entry.pm (NEXTKEY): Don't return the last $key if it's one that should be hidden. * Conn.pm (newEntry): New method, to create an empty LDAP::Entry object. It is properly "tied" into the appropriate object. 1999-01-04 Leif Hedstrom * Entry.pm (setDN): Added third optional argument, to enfoce DN normalization. (getDN): Ditto. (hasDNValue): Ditto. (matchDNValue): Ditto. * Entry.pm (removeValue): Added support for DN normalization (optional argument). (addValue): Ditto (getDN): Ditto. 1998-12-31 Leif Hedstrom * Entry.pm (DESTROY): Added this method, don't know if it actually makes any sense at all... :( * Conn.pm (add): Use _oc_order_ to find a list of attributes, to avoide calling the TIEHASH methods. (update): Ditto. (ALL): Clean out some "my" definitions. * Entry.pm (unRemove): New function, to undo remove opertaions on an attribute. (DELETE): Bug-fix, don't undef the attribute, it would prevent us from updating it properly in the Conn::update() method. (remove): Ditto. * Conn.pm (nextEntry): Return $obj instead of blessing the %entry (again). 1998-12-25 Leif Hedstrom * Conn.pm (POD): Changed examples from $conn -> $entry. 1998-12-17 Leif Hedstrom * Conn.pm (DESTROY): undef the Perl data after doing a ldap_msgfree(), bug #1964. (search): Ditto. (searchURL): Ditto. (nextEntry): Changed the order of setting numattr, to make sure it's zero if we don't find anything. 1998-12-16 Leif Hedstrom * Entry.pm (FIRSTKEY): Modified to honor the oc_order. (NEXTKEY): Ditto. (markModified): Made as an alias for attrModified(). * Conn.pm (nextEntry): Added code to handle internal counters for number of attributes in oc_order. This is used/needed for the FIRSTKEY and NEXTKEY methods in the Entry/Tie::Hash object. * Entry.pm (isAttr): New method, to make sure an attribute name really is a valid LDAP attribute. (FIRSTKEY): Now we'll handle each() and keys() properly, whooohoo! (NEXTKEY): Ditto. 1998-12-15 Leif Hedstrom * Entry.pm (isDeleted): Added new method, almost identical to isModified(). (EXISTS): New method, to implement the EXISTS functionality. * API.xs (RET_CPP): Test for NULL pointers, bug #1387. (RET_BVPP): Ditto. * Utils.pm (ldapArgs): Fixed bug where "-s 0" would not be honored (I'm an idiot, OK?). 1998-12-14 Leif Hedstrom * Conn.pm (getRes): New method, to return the internal result message. (getLD): Use defined() around test for existence. 1998-12-11 Leif Hedstrom * Conn.pm (new): Make sure binddn and bindpasswd are set to the empty string unless specified. (init): Make sure certdb is defined before trying to use it. (setDefaultRebindProc): Added default auth method, unless explicitly specified. * Utils.pm (askPassword): Added support for Term::ReadKey. (askPassword): Moved the eval "use ..." here. (userCredentials): Removed verbose print statement. (askPassword): Added an optional argument to print a prompt; * Conn.pm (setDefaultRebindProc): Added a default "auth" value, if not provided in the call. 1998-12-04 Leif Hedstrom * Makefile.PL: Modified so that "silent" install will actually echo what options it's setting. It will now croak() if the SDK dir specified doesn't exist. * INSTALL: Updated to reflect new v1.1 stuff. Added links to the FAQ. * README: Ditto. Also changed some of the binary install information, which might not be useful anyways... * Makefile.PL: Added "filters" to remove .dll and .sl from shared libraries when creating link options. I also replaced the code to put the valid library extensions into a variable (bug #1344). * Makefile.PL: Fixed some crap with the config parsing, and ENV handling (for silent installs). 1998-12-03 Leif Hedstrom * Conn.pm (update): Bug fix, now we empty the hash array before examining changed attributes (bug #1385). * Makefile.PL: Added the "-nolinenumbers" XSUBS options (bug #1329). 1998-09-26 Leif Hedstrom * Conn.pm (init): Cleaned out _perror() calls. (delete): Added support for calling delete() with an Entry:: object as paramter. (new): Cleaned out some dead code for $ref. * Entry.pm (setValue): New method, to avoid having to use Perl assignment statements to set an entire attribute value. 1998-09-18 Leif Hedstrom * Conn.pm (init): Changed call to ldapssl_client_init() to pass a 0 value as the handle pointer. This avoids a Perl compiler warning. 1998-09-12 Leif Hedstrom * LDIF.pm (readEntries): Changed tests for empty arguments, to use defined(). * Utils.pm (ldapArgs): Bug fix, we used the wrong option for the certificate (-P) when checking to set the LDAP port. (normalizeDN): Chagned tests for empty arguments, to use use defined(). * Entry.pm (STORE): Changed tests for empty arguments, to use defined(). (DELETE): Ditto. (attrModified): Ditto. (isModified): Ditto. (remove): Ditto. (removeValue): Ditto. (addValue): Ditto. (hasValue): Ditto. (matchValue): Ditto. (setDN): Ditto. (size): Ditto. (exists): Ditto. * Conn.pm (printError): Changed test for $str to see if it's defined. (delete): Cleaned up code around $dn. (modifyRDN): Cleaned up testes around $dn and $del. 1998-09-11 Leif Hedstrom * Conn.pm (modifyRDN): We now preserve the case of the DN/RDN, but still treat RDNs as CIS when comparing strings. 1998-09-08 Leif Hedstrom * Conn.pm (setDefaultRebindProc): Bug fix, it had the Ldapc:: crap stil in there... :-(. (simpleAuth): New method, to do simple authentication rebind. 1998-09-07 Leif Hedstrom * Makefile.PL: Changed all <> to , to support command line arguments for MakeMaker. 1998-09-03 Leif Hedstrom * Conn.pm (nextEntry): Fixed bug with case sensitivity. 1998-08-18 Leif Hedstrom * Conn.pm (setDefaultRebindProc): It's back! Officially released PerLDAP v1.0. 1998-08-13 Leif Hedstrom * Makefile.PL: Fixed so that automated installs works. * Conn.pm (update): Fixed narly bug with ldap_modify()... * All: Cleaned up some hash indexes, to make sure they are properly quoted, and there are no conflicts to resolve. * Entry.pm (STORE): Fixed a bug with attribute names not being properly added to _oc_order_. (addValue): Ditto, added the same code as for STORE. 1998-08-06 Leif Hedstrom * Entry.pm (printLDIF): Copied/modified from the Utils.pm library. (isModified): Added this function, thought it might be useful. 1998-08-03 Leif Hedstrom * Conn.pm (modifyRDN): Fixed! It also has an option to take an "external" DN as an argument, if supplied. 1998-08-02 Leif Hedstrom * Conn.pm (getErrorCode): Now takes two optional arguments, to return the match string, and extra error string. Note that these two arguments are pointers to strings! * API.xs(ldap_get_lderrno): Fixed this function, at least it seems to work now... * Conn.pm (getLD): Added this function, convenient way to get the LD from the OO layer. 1998-07-30 Leif Hedstrom * Conn.pm (modifyRDN): New method, to rename the RDN of the entry. * Utils.pm (answer): New function, from LdapUtils.pm. * Conn.pm (delete): Fixed references to normalizeDN. * Utils.pm (userCredentials): Added this function, to make it easy to get credentials when binding as a user. (normalizeDN): Fixed bugs, because of calling convention... * Conn.pm (getError): Fixed bug with passing read-only argument. 1998-07-29 Leif Hedstrom * Utils.pm (unixCrypt): Moved from my LdapUtils.pm module. Added askPassword to the export tag. * Conn.pm (new): Added support for passing a hash array of all the parameters, as returned by the ldapArgs() function. * Utils.pm (str2Scope): New function, for converting strings (subtree) to a numerical scope value (2). (askPassword): Ditto, ask for a password, interactively. (ldapArgs): Ditto, handle common LDAP command line arguments. * Makefile.PL: Minor change, to do regex match on OS version for MSWin. * Entry.pm: Changed all _XXX hash values to also end with a _, hence making it easier to isolate them (/^_.*_$/). * Conn.pm (nextEntry): Changed to accept that the attributes are now arrays, not pointers to arrays. We still consider them as pointers internally though, it's cleaner API. * API.pm: Changed to use the native Exporter function to export tags into EXPORT_OK. 1998-07-22 Leif Hedstrom * LDIF.pm (readEntry): Moved from my LdapUtils.pm package. * Utils.pm (printEntry): Moved from the ::Connection class, and marked it as "obsolete". (encodeBase64): Moved from my LdapUtils.pm package. (decodeBase64): Ditto. perl-mozldap-1.5.3/test_api/0000775000076400007640000000000011426105703014403 5ustar richrichperl-mozldap-1.5.3/test_api/write.pl0000555000076400007640000000667510634204216016106 0ustar richrich#!/usr/bin/perl -w ############################################################################# # $Id: write.pl,v 1.5.2.1 2007/06/14 09:21:18 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerlDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # write.pl - Test of LDAP Modify Operations in Perl5 # Author: Clayton Donley # # This utility is mostly to demonstrate all the write operations # that can be done with LDAP through this PERL5 module. use strict; use Mozilla::LDAP::API qw(:constant :api); # This is the entry we will be adding. Do not use a pre-existing entry. my $ENTRYDN = "cn=Test Guy, o=Org, c=US"; # This is the DN and password for an Administrator my $ROOTDN = "cn=DSManager,o=Org,c=US"; my $ROOTPW = ""; my $ldap_server = ""; if (!$ldap_server) { print "Edit the top portion of this file before continuing.\n"; exit -1; } my $ld = ldap_init($ldap_server,LDAP_PORT); if ($ld == -1) { die "Connection to LDAP Server Failed"; } if (ldap_simple_bind_s($ld,$ROOTDN,$ROOTPW) != LDAP_SUCCESS) { ldap_perror($ld,"bind_s"); die; } my %testwrite = ( "cn" => "Test User", "sn" => "User", "givenName" => "Test", "telephoneNumber" => "8475551212", "objectClass" => ["top","person","organizationalPerson", "inetOrgPerson"], "mail" => "tuser\@my.org", ); if (ldap_add_s($ld,$ENTRYDN,\%testwrite) != LDAP_SUCCESS) { ldap_perror($ld,"add_s"); die; } print "Entry Added.\n"; %testwrite = ( "telephoneNumber" => "7085551212", "mail" => {"a",["Test_User\@my.org"]}, ); if (ldap_modify_s($ld,$ENTRYDN,\%testwrite) != LDAP_SUCCESS) { ldap_perror($ld,"modify_s"); die; } print "Entry Modified.\n"; # # Delete the entry for $ENTRYDN # if (ldap_delete_s($ld,$ENTRYDN) != LDAP_SUCCESS) { ldap_perror($ld,"delete_s"); die; } print "Entry Deleted.\n"; # Unbind to LDAP server ldap_unbind($ld); exit; perl-mozldap-1.5.3/test_api/api.pl0000555000076400007640000001514010634204216015510 0ustar richrich#!/usr/bin/perl -w ############################################################################# # $Id: api.pl,v 1.8.2.1 2007/06/14 09:21:18 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # api.pl - Test all LDAPv2 API function # Author: Clayton Donley # # Performs all API calls directly in order to test for possible issues # on a particular platform. use Mozilla::LDAP::API qw(:api :constant); use strict; my $BASE = "ou=Test,o=Test,c=US"; my $DN = "cn=Directory Manager"; my $PASS = "abcd1234"; my $HOST = ""; my $PORT = 389; if (!$HOST) { print "Please edit the variables at the top of this file.\n"; exit -1; } print "\nPerLDAP API TestSuite\n"; print "\nNote: Failures in earlier tests will cause later tests to fail.\n"; print "\n"; my $howmany = 10; # Initialize the Connection { my $ld = ldap_init($HOST,$PORT); if ($ld <0) { print "init - Failed!\n"; die; } print "init - OK\n"; # Set an LDAP Session Option if (ldap_set_option($ld,LDAP_OPT_PROTOCOL_VERSION,LDAP_VERSION3) != LDAP_SUCCESS) { print "set_option - Failed!\n"; } else { print "set_option - OK\n"; } # Get an LDAP Session Option my $option; ldap_get_option($ld,LDAP_OPT_REFERRALS,$option); if ($option != 1) { print "get_option - Failed!\n"; } else { print "get_option - OK\n"; } # Anonymous Bind if (ldap_simple_bind_s($ld,"","") != LDAP_SUCCESS) { print "anon_bind - Failed!\n"; } else { print "anon_bind - OK\n"; } # Authenticated Simple Bind if (ldap_simple_bind_s($ld,$DN,$PASS) != LDAP_SUCCESS) { print "simple_bind - Failed!\n"; } else { print "simple_bind - OK\n"; } # Set Rebind Process my $rebindproc = sub { return($DN,$PASS,LDAP_AUTH_SIMPLE); }; ldap_set_rebind_proc($ld,$rebindproc); print "set_rebind - OK\n"; # Add an OrgUnit Entry my $entry = { "objectclass" => ["top","organizationalUnit"], "ou" => "Test", }; if (ldap_add_s($ld,$BASE,$entry) != LDAP_SUCCESS) { print "add_org - Failed!\n"; } else { print "add_org - OK\n"; } # Add People foreach my $number (1..$howmany) { $entry = { "objectclass" => ["top","person"], "cn" => "Mozilla $number", "sn" => ["$number"], }; if (ldap_add_s($ld,"cn=Mozilla $number,$BASE",$entry) != LDAP_SUCCESS) { print "add_user_$number - Failed!\n"; } else { print "add_user_$number - OK\n"; } } # Modify People foreach my $number (1..$howmany) { $entry = { "sn" => {"ab",["Test"]}, "telephoneNumber" => {"ab",[123.456]}, # "telephoneNumber" => "800-555-111$number", }; if (ldap_modify_s($ld,"cn=Mozilla $number,$BASE",$entry) != LDAP_SUCCESS) { print "mod_user_$number - Failed!\n"; } else { print "mod_user_$number - OK\n"; } } # Search People my $filter = "(sn=Test)"; my $attrs = ["cn","sn"]; my $res; if (ldap_search_s($ld,$BASE,LDAP_SCOPE_SUBTREE,$filter,$attrs,0,$res) != LDAP_SUCCESS) { print "search_user - Failed!\n"; } else { print "search_user - OK\n"; } # Count Results if (ldap_count_entries($ld,$res) != $howmany) { print "count_res - Failed!\n"; } else { print "count_res - OK\n"; } # Sort Results if (ldap_sort_entries($ld,$res,"sn") != LDAP_SUCCESS) { print "sort_ent - Failed!\n"; } else { print "sort_ent - OK\n"; } # Multisort Results if (ldap_multisort_entries($ld,$res,["sn","telephoneNumber"]) != LDAP_SUCCESS) { print "multisort - Failed!\n"; } else { print "multisort - OK\n"; } # Get First Entry my $ent = ldap_first_entry($ld,$res); if (!$ent) { print "first_entry - Failed!\n"; } else { print "first_entry - OK\n"; } # Get Next Entry $ent = ldap_next_entry($ld,$ent); if (!$ent) { print "next_entry - Failed!\n"; } else { print "next_entry - OK\n"; } # Get DN my $dn = ldap_get_dn($ld,$ent); if (!$dn) { print "get_dn - Failed!\n"; } else { print "get_dn - OK\n"; } # Get First Attribute my $ber; my $attr = ldap_first_attribute($ld,$ent,$ber); if (!$attr) { print "first_attr - Failed!\n"; } else { print "first_attr - OK\n"; } # Get Next Attribute $attr = ldap_next_attribute($ld,$ent,$ber); if (!$attr) { print "next_attr - Failed!\n"; } else { print "next_attr - OK\n"; } # Get Attribute Values my @vals = ldap_get_values($ld,$ent,$attr); if ($#vals < 0) { print "get_values - Failed!\n"; } else { print "get_values - OK\n"; } # Free structures pointed to by $ber and $res to prevent memory leak ldap_ber_free($ber,1); ldap_msgfree($res); # Compare Attribute Values foreach my $number (1..$howmany) { if(ldap_compare_s($ld,"cn=Mozilla $number,$BASE","sn",$number) != LDAP_COMPARE_TRUE) { print "comp_user_$number - Failed!\n"; } else { print "comp_user_$number - OK\n"; } } # Delete Users foreach my $number (1..$howmany) { if (ldap_delete_s($ld,"cn=Mozilla $number,$BASE") != LDAP_SUCCESS) { print "del_user_$number - Failed!\n"; } else { print "del_user_$number - OK\n"; } } if (ldap_delete_s($ld,"$BASE") != LDAP_SUCCESS) { print "del_org - Failed!\n"; } else { print "del_org - OK\n"; } # Unbind ldap_unbind($ld); } perl-mozldap-1.5.3/test_api/search.pl0000555000076400007640000000711410634204216016206 0ustar richrich#!/usr/bin/perl ############################################################################# # $Id: search.pl,v 1.5.2.1 2007/06/14 09:21:18 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerlDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Test the search capabilities of the API, similar to write.pl. use Mozilla::LDAP::API qw(:api :constant); use strict; my $ldap_host = ""; my $BASEDN = "o=Org,c=US"; my $filter = $ARGV[0]; if (!$ldap_host) { print "Edit the top portion of this file before continuing.\n"; exit -1; } my $attrs = []; my ($ld,$result,$count); ## ## Initialize LDAP Connection ## if (($ld = ldap_init($ldap_host,LDAP_PORT)) == -1) { die "Can not open LDAP connection to $ldap_host"; } ## ## Bind as DN, PASSWORD (NULL,NULL) on LDAP connection $ld ## if (ldap_simple_bind_s($ld,"","") != LDAP_SUCCESS) { ldap_perror($ld,"bind_s"); die; } ## ## ldap_search_s - Synchronous Search ## if (ldap_search_s($ld,$BASEDN,LDAP_SCOPE_SUBTREE,$filter,$attrs,0,$result) != LDAP_SUCCESS) { ldap_perror($ld,"search_s"); die; } ## ## ldap_count_entries - Count Matched Entries ## if (($count = ldap_count_entries($ld,$result)) == -1) { ldap_perror($ld,"count_entry"); die; } ## ## first_entry - Get First Matched Entry ## next_entry - Get Next Matched Entry ## for (my $ent = ldap_first_entry($ld,$result); $ent; $ent = ldap_next_entry($ld,$ent)) { ## ## ldap_get_dn - Get DN for Matched Entries ## my ($dn,$attr,@vals,$val,$ber); if (($dn = ldap_get_dn($ld,$ent)) ne "") { print "dn: $dn\n"; } else { ldap_perror($ld,"get_dn"); die; } for ($attr = ldap_first_attribute($ld,$ent,$ber); $attr; $attr = ldap_next_attribute($ld,$ent,$ber)) { ## ## ldap_get_values ## @vals = ldap_get_values($ld,$ent,$attr); if ($#vals >= 0) { foreach $val (@vals) { print "$attr: $val\n"; } } } ldap_ber_free($ber,0); } ldap_msgfree($result); ## ## Unbind LDAP Connection ## ldap_unbind($ld); perl-mozldap-1.5.3/README0000444000076400007640000001122010634204213013437 0ustar richrich############################################################################# # # # PerLDAP v1.5 - A Perl Developers' Kit for LDAP # # # ############################################################################# What is PerLDAP? ================ PerLDAP is a set of modules written in Perl and C that allow developers to leverage their existing Perl knowledge to easily access and manage LDAP- enabled directories. PerLDAP makes it very easy to search, add, delete, and modify directory entries. For example, Perl developers can easily build web applications to access information stored in a directory or create directory sync tools between directories and other services. PerLDAP is an open source development project, the result of a joint effort between Netscape, Leif Hedstrom, Clayton Donley and several other contributors. PerLDAP currently provides the basic functions to allow Perl users to access and manipulate directories easily. Compiling the PerLDAP Sources ============================= The source to PerLDAP is available on the Mozilla site at: http://www.mozilla.org/directory/ You can either retrieve the .tar/zip file with the source distribution, or use CVS to checkout the module directly. The name of the CVS module is PerLDAP, and it checks out the directory mozilla/directory/perldap Further instructions for using CVS and Mozilla is available at http://www.mozilla.org/cvs.html and an FAQ for PerLDAP is at http://www.mozilla.org/directory/faq/perldap-faq.html Instructions for building the source can be found in the INSTALL file in the source distribution. The latest stable release of PerLDAP is v1.5, not further development is planned at this time due to lack of time and resources. Getting Started =============== Documentation for this module is in standard Perl 'pod' format. HTML versions of this documentation can also be found on the Netscape DevEdge site at: http://developer.netscape.com/tech/directory/. Additionally, many good examples can be found in the 'examples' directory. Modules and Examples Included ============================= Mozilla::LDAP::API - Low level interface between Perl and the LDAP C API Mozilla::LDAP::Entry - Perl methods for manipulating entry objects Mozilla::LDAP::Conn - Perl methods for performing LDAP operations Mozilla::LDAP::LDIF - Perl methods for utilizing LDIF Mozilla::LDAP::Utils - Some convenient LDAP related utilities test_api/search.pl - Tests low level API search calls test_api/write.pl - Tests low level API write calls test_api/api.pl - Tests ALL low level LDAPv2 calls examples/lfinger.pl - LDAP version of the regular Unix finger command. examples/qsearch.pl - Simple ldapsearch replacement. examples/monitor.pl - Retrieve status information from an LDAP server. examples/ldappasswd.pl - Change the LDAP password for a user. examples/rmentry.pl - Remove an entire entry from the database. examples/rename.pl - Rename (modRDN) an entry. examples/tabdump.pl - Dump LDAP information into a tab separated file. examples/psoftsync.pl - Synchronize LDAP with a PeopleSoft "dump" file. All examples support the "standard" LDAP command line options, which are -h hostname LDAP server name -p port # LDAP port, default is 389 (or 636 for SSL) -b base DN LDAP Base-DN -D bind DN LDAP bind DN (connect to server as this "user") -w bind pswd Password to bind to the server -P certfile Use SSL, with the publick keys from this file Note that the examples currently only support Simple Authentication (passwords), the Client Authentication features (using certificates) will be used in the next release. All examples also honors the environment variable LDAP_BASEDN, set it to your systems base DN, e.g. % setenv LDAP_BASEDN 'dc=netscape,dc=com' or for Bourne shell # LDAP_BASEDN='dc=netscape,dc=com'; export LDAP_BASEDN Reporting problems and bugs =========================== Address all bug reports and comments to the Mozilla newsgroups at: news://news.mozilla.org/netscape.public.mozilla.directory License/Copyright ================= Portions by Netscape (c) Copyright 1998 Netscape Communications Corp, Inc. Portions by Leif Hedstrom (c) Copyright 2003 Leif Hedstrom Portions by Clayton Donley (c) Copyright 1998 Clayton Donley This code is available under the mozilla.org tri-license. See http://www.mozilla.org/MPL/ . Known Bugs ========== - The Rebind operation on NT does NOT work properly when set to a Perl function. This is being investigated. perl-mozldap-1.5.3/API.xs0000444000076400007640000021350711426075705013574 0ustar richrich/****************************************************************************** * $Id: API.xs,v 1.18.2.14 2010/08/03 20:27:49 nkinder%redhat.com Exp $ * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is PerLDAP. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. and Clayton Donley. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * - Leif Hedstrom * - Kevin McCarthy * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* * DESCRIPTION * This is the XSUB interface for the API. */ #ifdef __cplusplus extern "C" { #endif /* Perl Include Files */ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __cplusplus } #endif /* LDAP C SDK Include Files */ #include #include /* need to define ber types for old version of api */ #if LDAP_VENDOR_VERSION < 600 typedef int my_chgtype_t; typedef long my_chgnum_t; typedef unsigned long my_result_t; typedef unsigned long my_vlvint_t; #else typedef ber_int_t my_chgtype_t; typedef ber_int_t my_chgnum_t; typedef ber_int_t my_result_t; typedef ber_int_t my_vlvint_t; #endif /* LDAP_VENDOR_VERSION < 600 */ /* SSL is only available in Binary */ #ifdef USE_SSL #ifndef USE_OPENLDAP # include #endif #endif /* AUTOLOAD methods for LDAP constants */ #include "constant.h" /* This stuff is needed when using OpenLDAP. Most of it is taken * from the Mozilla LDAP C SDK. */ #ifdef USE_OPENLDAP #define LDAP_C #define LDAP_CALL #define LDAP_CALLBACK /* Stuff for sorting entries */ typedef int (LDAP_C LDAP_CALLBACK LDAP_CMP_CALLBACK)(const char *val1, const char *val2); typedef int (LDAP_C LDAP_CALLBACK LDAP_CHARCMP_CALLBACK)(char*, char*); static LDAP_CHARCMP_CALLBACK *perldap_et_cmp_fn; struct entrything { char **et_vals; LDAPMessage *et_msg; }; typedef LDAPSortKey LDAPsortkey; #define LDAP_TAG_SK_MATCHRULE 0x80L /* context specific + primitive + 0 */ #define LDAP_TAG_SK_REVERSE 0x81L /* context specific + primitive + 1 */ /* VLV structure */ typedef struct ldapvirtuallist { ber_int_t ldvlist_before_count; /* # entries before target */ ber_int_t ldvlist_after_count; /* # entries after target */ char *ldvlist_attrvalue; /* jump to this value */ ber_int_t ldvlist_index; /* list offset */ ber_int_t ldvlist_size; /* number of items in vlist */ void *ldvlist_extradata; /* for use by application */ } LDAPVirtualList; /* We don't really need/use these, but we need to define them * to something to prevent compiler errors. */ typedef char FriendlyMap; typedef char LDAPFiltDesc; typedef char LDAPFiltInfo; typedef char LDAPMemCache; typedef char LDAPVersion; #endif /* Prototypes */ static int perldap_init(); static void * perldap_malloc(size_t size); static void * perldap_calloc(size_t number, size_t size); static void * perldap_realloc(void *ptr, size_t size); static void perldap_free(void *ptr); static int perldap_et_cmp(const void *aa, const void *bb); static void perldap_ldap_value_free(char **vals); static int perldap_ldap_create_persistentsearch_control(LDAP *ld, int changetypes, int changesonly, int return_echg_ctrls, char ctrl_iscritical, LDAPControl **ctrlp); static int perldap_ldap_create_sort_control(LDAP *ld, LDAPsortkey **sortKeyList, char ctrl_iscritical, LDAPControl **ctrlp); static int perldap_ldap_create_virtuallist_control(LDAP *ld, LDAPVirtualList *ldvlistp, LDAPControl **ctrlp); static int perldap_ldap_multisort_entries(LDAP *ld, LDAPMessage **chain, char **attrs, LDAP_CMP_CALLBACK *cmp); static int perldap_ldap_parse_entrychange_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *chgtypep, char **prevdnp, int *chgnumpresentp, ber_int_t *chgnump); static int perldap_ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *result, char **attribute); static int perldap_ldap_parse_virtuallist_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *target_posp, ber_int_t *list_sizep, int *errcodep); static void perldap_ldap_perror(LDAP *ld, const char *s); static int perldap_ldap_set_lderrno(LDAP *ld, int e, char *m, char *s); static int perldap_ldap_sort_entries(LDAP *ld, LDAPMessage **chain, char *attr, LDAP_CMP_CALLBACK *cmp); static int perldap_ldap_url_search(LDAP *ld, char *url, int attrsonly); static int perldap_ldap_url_search_s(LDAP *ld, char *url, int attrsonly, LDAPMessage **res); static int perldap_ldap_url_search_st(LDAP *ld, char *url, int attrsonly, struct timeval *timeout, LDAPMessage **res); static int perldap_ldapssl_client_init(const char *certdbpath, void *certdbhandle); static int perldap_ldapssl_enable_clientauth(LDAP *ld, char *keynickname, char *keypasswd, char *certnickname); static LDAP * perldap_ldapssl_init(const char *host, const char *port, int secure); static char ** avref2charptrptr(SV *avref); static struct berval ** avref2berptrptr(SV *avref); static SV* charptrptr2avref(char **cppval); static SV* berptrptr2avref(struct berval **bval); static LDAPMod *parse1mod(SV *ldap_value_ref,char *ldap_current_attribute, int ldap_add_func,int cont); static int calc_mod_size(HV *ldap_change); static LDAPMod **hash2mod(SV *ldap_change_ref,int ldap_add_func,const char *func); static int StrCaseCmp(const char *s, const char *t); static char * StrDup(const char *source); #ifdef USE_OPENLDAP static int LDAP_CALL internal_rebind_proc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *arg); static int LDAP_CALL ldap_default_rebind_proc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *arg); #else static int LDAP_CALL internal_rebind_proc(LDAP *ld,char **dnp,char **pwp, int *authmethodp,int freeit,void *arg); static int LDAP_CALL ldap_default_rebind_proc(LDAP *ld, char **dn, char **pswd, int *auth, int freeit, void *arg); #endif /* Global Definitions and Variables */ SV *ldap_perl_rebindproc = NULL; static char *ldap_default_rebind_dn = NULL; static char *ldap_default_rebind_pwd = NULL; static int ldap_default_rebind_auth = LDAP_AUTH_SIMPLE; SV *ldap_perl_sortcmp = NULL; /* Return a Perl List from a char ** in PPCODE */ #define RET_CPP(cppvar) \ int cppindex; \ if (cppvar) { \ for (cppindex = 0; cppvar[cppindex] != NULL; cppindex++) \ { \ EXTEND(sp,1); \ PUSHs(sv_2mortal(newSVpv(cppvar[cppindex],strlen(cppvar[cppindex])))); \ } \ perldap_ldap_value_free(cppvar); } /* Return a Perl List from a berval ** in PPCODE */ #define RET_BVPP(bvppvar) \ int bvppindex; \ if (bvppvar) { \ for (bvppindex = 0; bvppvar[bvppindex] != NULL; bvppindex++) \ { \ EXTEND(sp,1); \ PUSHs(sv_2mortal(newSVpv(bvppvar[bvppindex]->bv_val,bvppvar[bvppindex]->bv_len))); \ } \ ldap_value_free_len(bvppvar); } /* * Function Definition */ static int perldap_init() { #ifdef USE_OPENLDAP /* OpenLDAP doesn't allow us to set our * own memory allocation functions. */ return LDAP_OPT_SUCCESS; #else struct ldap_memalloc_fns memalloc_fns; memalloc_fns.ldapmem_malloc = perldap_malloc; memalloc_fns.ldapmem_calloc = perldap_calloc; memalloc_fns.ldapmem_realloc = perldap_realloc; memalloc_fns.ldapmem_free = perldap_free; return (ldap_set_option(NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &memalloc_fns)); #endif } static void * perldap_malloc(size_t size) { void *new_ptr; New(1, new_ptr, size, char); return (new_ptr); } static void * perldap_calloc(size_t number, size_t size) { void *new_ptr; Newz(1, new_ptr, (number*size), char); return (new_ptr); } static void * perldap_realloc(void *ptr, size_t size) { Renew(ptr, size, char); return (ptr); } static void perldap_free(void *ptr) { Safefree(ptr); } /* Helpers for using different LDAP libraries */ static void perldap_ldap_value_free(char **vals) { #ifdef USE_OPENLDAP char **a; if ( vals == NULL ) { return; } for (a = vals; *a != NULL; a++) { char *tmp= *a; ldap_memfree((void *)tmp); } ldap_memfree((void *)vals); #else ldap_value_free(vals); #endif } static int perldap_ldap_create_persistentsearch_control(LDAP *ld, int changetypes, int changesonly, int return_echg_ctrls, char ctrl_iscritical, LDAPControl **ctrlp) { int ret = 0; #ifdef USE_OPENLDAP BerElement * ber = NULL; struct berval * berval = NULL; if (ctrlp == NULL || (changetypes & ~(LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD | LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE | LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY | LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME)) != 0) { ret = LDAP_PARAM_ERROR; goto bail; } if ((ber = ber_alloc_t(LBER_USE_DER)) == NULL) { ret = LDAP_NO_MEMORY; goto bail; } if (ber_printf(ber, "{ibb}", changetypes, changesonly, return_echg_ctrls) == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } if (ber_flatten(ber, &berval) != LDAP_SUCCESS) { ret = LDAP_NO_MEMORY; goto bail; } ret = ldap_control_create(LDAP_CONTROL_PERSIST_REQUEST, ctrl_iscritical, berval, 1, ctrlp); bail: ber_free(ber, 1); ber_bvfree(berval); ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else ret = ldap_create_persistentsearch_control(ld, changetypes, changesonly, return_echg_ctrls, ctrl_iscritical, ctrlp); #endif return ret; } static int perldap_ldap_create_sort_control(LDAP *ld, LDAPsortkey **sortKeyList, char ctrl_iscritical, LDAPControl **ctrlp) { int ret = 0; #ifdef USE_OPENLDAP BerElement * ber = NULL; struct berval * berval = NULL; int i = 0; if ( sortKeyList == NULL || ctrlp == NULL ) { ret = LDAP_PARAM_ERROR; goto bail; } if ((ber = ber_alloc_t(LBER_USE_DER)) == NULL) { ret = LDAP_NO_MEMORY; goto bail; } if (ber_printf(ber, "{") == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } for(i = 0; sortKeyList[i] != NULL; i++) { if (ber_printf(ber, "{s", (sortKeyList[i])->attributeType) == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } if ((sortKeyList[i])->orderingRule != NULL ) { if (ber_printf(ber, "ts", LDAP_TAG_SK_MATCHRULE, (sortKeyList[i])->orderingRule) == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } } if ((sortKeyList[i])->reverseOrder) { if (ber_printf(ber, "tb}", LDAP_TAG_SK_REVERSE, (sortKeyList[i])->reverseOrder) == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } } else { if (ber_printf( ber, "}") == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } } } if (ber_printf(ber, "}") == -1) { ret = LDAP_ENCODING_ERROR; goto bail; } if (ber_flatten(ber, &berval) != LDAP_SUCCESS) { ret = LDAP_NO_MEMORY; goto bail; } ret = ldap_control_create(LDAP_CONTROL_SORTREQUEST, ctrl_iscritical, berval, 1, ctrlp); bail: ber_free(ber, 1); ber_bvfree(berval); ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else ret = ldap_create_sort_control(ld, sortKeyList, ctrl_iscritical, ctrlp); #endif return ret; } static int perldap_ldap_create_virtuallist_control(LDAP *ld, LDAPVirtualList *ldvlistp, LDAPControl **ctrlp) { int ret = 0; #ifdef USE_OPENLDAP LDAPVLVInfo ldvlvinfo; struct berval attrvalue; ldvlvinfo.ldvlv_before_count = ldvlistp->ldvlist_before_count; ldvlvinfo.ldvlv_after_count = ldvlistp->ldvlist_after_count; ldvlvinfo.ldvlv_offset = ldvlistp->ldvlist_index; ldvlvinfo.ldvlv_count = ldvlistp->ldvlist_size; if (ldvlistp->ldvlist_attrvalue) { attrvalue.bv_val = ldvlistp->ldvlist_attrvalue; attrvalue.bv_len = strlen(ldvlistp->ldvlist_attrvalue); ldvlvinfo.ldvlv_attrvalue = &attrvalue; } ret = ldap_create_vlv_control(ld, &ldvlvinfo, ctrlp); #else ret = ldap_create_virtuallist_control(ld, ldvlistp, ctrlp); #endif return ret; } static int perldap_ldap_multisort_entries(LDAP *ld, LDAPMessage **chain, char **attrs, LDAP_CMP_CALLBACK *cmp) { /* OpenLDAP doesn't implement any sort functions. This code is * largely borrowed from MozLDAP. */ #ifdef USE_OPENLDAP int i, count; struct entrything *et; LDAPMessage *e, *last; LDAPMessage **ep; if (ld == NULL || chain == NULL || cmp == NULL) { return( LDAP_PARAM_ERROR ); } count = ldap_count_entries( ld, *chain ); if (count < 0) { /* error, usually with bad ld or malloc */ return( LDAP_PARAM_ERROR ); } if (count < 2) { /* nothing to sort */ return( 0 ); } if ( (et = (struct entrything *)perldap_malloc( count * sizeof(struct entrything) )) == NULL ) { perldap_ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, NULL); return( -1 ); } e = ldap_first_message(ld, *chain); for ( i = 0; i < count; i++ ) { et[i].et_msg = e; et[i].et_vals = NULL; if ( attrs == NULL ) { char *dn; dn = ldap_get_dn( ld, e ); et[i].et_vals = ldap_explode_dn( dn, 1 ); perldap_free( dn ); } else { int attrcnt; struct berval **bvals; for ( attrcnt = 0; attrs[attrcnt] != NULL; attrcnt++ ) { bvals = ldap_get_values_len( ld, e, attrs[attrcnt] ); if (bvals && bvals[0]) { int bv_count = 0; int j = 0; /* Count the number of bvals we have. */ for (bv_count = 0; bvals[bv_count]; bv_count++) { ; } /* Advance to the end of et_vals. */ for (j = 0; et[i].et_vals[j]; j++) { ; } /* Realloc et_vals so we can append values from bvals. */ et[i].et_vals = (char **)perldap_realloc((char *)et[i].et_vals, sizeof(char *) * (j + bv_count + 1)); /* Copy vals from bvals to et_vals. */ for (bv_count = 0; bvals[bv_count]; bv_count++) { et[i].et_vals[j + bv_count] = StrDup(bvals[bv_count]->bv_val); } /* Null terminate the array. */ et[i].et_vals[j + bv_count] = 0; /* The values form bvals have been copied, so we can free bvals now. */ ldap_value_free_len(bvals); } } } e = ldap_next_message(ld, e); } last = e; perldap_et_cmp_fn = (LDAP_CHARCMP_CALLBACK *)cmp; qsort( (void *) et, (size_t) count, (size_t) sizeof(struct entrything), perldap_et_cmp ); ep = chain; for ( i = 0; i < count; i++ ) { *ep = et[i].et_msg; e = ldap_next_message(ld, *ep); ep = &e; perldap_ldap_value_free( et[i].et_vals ); } *ep = last; perldap_free((char *) et); return( 0 ); #else return(ldap_multisort_entries(ld, chain, attrs, cmp)); #endif } static int perldap_ldap_parse_entrychange_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *chgtypep, char **prevdnp, int *chgnumpresentp, ber_int_t *chgnump) { int ret = 0; #ifdef USE_OPENLDAP LDAPControl *entchg_control = NULL; if ((entchg_control = ldap_control_find(LDAP_CONTROL_PERSIST_ENTRY_CHANGE_NOTICE, ctrls, NULL)) != NULL) { BerElement *ber = NULL; ber_int_t changetype; ber_len_t len; char *previousdn; ber = ber_init(&entchg_control->ldctl_value); if (ber == NULL) { ret = LDAP_NO_MEMORY; } /* Get the changetype first. */ if ( ber_scanf( ber, "{e", &changetype ) == LBER_ERROR ) { ber_free( ber, 1 ); ret = LDAP_DECODING_ERROR; goto bail; } /* If this is a MODDN, get the previous DN. */ if (changetype == LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME) { if ( ber_scanf( ber, "a", &previousdn ) == LBER_ERROR ) { ber_free( ber, 1 ); ret = LDAP_DECODING_ERROR; goto bail; } } else { previousdn = NULL; } /* Set the return pointers for the changetype and previous DN. */ if ( chgtypep != NULL ) { *chgtypep = changetype; } if ( prevdnp != NULL ) { *prevdnp = previousdn; } else if ( previousdn != NULL ) { ber_memfree((void *)previousdn); } /* Get the optional changenumber if present. */ if ( chgnump != NULL ) { if ( ber_peek_tag( ber, &len ) == LBER_INTEGER && ber_get_int( ber, chgnump ) != LBER_ERROR ) { if ( chgnumpresentp != NULL ) { *chgnumpresentp = 1; } } else { if ( chgnumpresentp != NULL ) { *chgnumpresentp = 0; } } } ber_free( ber, 1 ); ret = LDAP_SUCCESS; } else { ret = LDAP_CONTROL_NOT_FOUND; } bail: ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else ret = ldap_parse_entrychange_control(ld, ctrls, chgtypep, prevdnp chgnumpresentp, chgnump); #endif return ret; } static int perldap_ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *result, char **attribute ) { int ret = 0; #ifdef USE_OPENLDAP LDAPControl *sort_ctrl = NULL; if ((sort_ctrl = ldap_control_find(LDAP_CONTROL_SORTRESPONSE, ctrls, NULL)) != NULL) { ret = ldap_parse_sortresponse_control(ld, sort_ctrl, result, attribute); } else { ret = LDAP_CONTROL_NOT_FOUND; } #else ret = ldap_parse_sort_control(ld, ctrls, result, attribute); #endif return ret; } static int perldap_ldap_parse_virtuallist_control(LDAP *ld, LDAPControl **ctrls, ber_int_t *target_posp, ber_int_t *list_sizep, int *errcodep) { int ret = 0; #ifdef USE_OPENLDAP LDAPControl * vlv_ctrl = NULL; if ((vlv_ctrl = ldap_control_find(LDAP_CONTROL_VLVRESPONSE, ctrls, NULL)) != NULL) { ret = ldap_parse_vlvresponse_control(ld, vlv_ctrl, target_posp, list_sizep, NULL, errcodep); } else { ret = LDAP_CONTROL_NOT_FOUND; } #else ret = ldap_parse_virtuallist_control(ld, ctrls, target_posp, list_sizep, errcodep); #endif return ret; } static void perldap_ldap_perror(LDAP *ld, const char *s) { #ifdef USE_OPENLDAP char * err_str = NULL; char * separator; int err; if ( s == NULL ) { s = separator = ""; } else { separator = ": "; } ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &err); err_str = ldap_err2string(err); printf("%s%s%s", s, separator, err_str); #else ldap_perror(ld, s); #endif } static int perldap_ldap_set_lderrno(LDAP *ld, int e, char *m, char *s) { int ret = 0; #ifdef USE_OPENLDAP ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &e); if (m) { ldap_set_option(ld, LDAP_OPT_MATCHED_DN, m); } if (s) { #ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE ldap_set_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, s); #else ldap_set_option(ld, LDAP_OPT_ERROR_STRING, s); #endif } #else /* !USE_OPENLDAP */ ret = ldap_set_lderrno(ld, e, m, s); #endif return ret; } static int perldap_ldap_sort_entries(LDAP *ld, LDAPMessage **chain, char *attr, LDAP_CMP_CALLBACK *cmp) { int ret = 0; #ifdef USE_OPENLDAP char *attrs[2]; attrs[0] = attr; attrs[1] = NULL; ret = perldap_ldap_multisort_entries(ld, chain, attr ? attrs : NULL, cmp); #else ret = ldap_sort_entries(ld, chain, attr, cmp); #endif return ret; } static int perldap_ldap_url_search(LDAP *ld, char *url, int attrsonly) { int ret = 0; #ifdef USE_OPENLDAP LDAPURLDesc *url_desc = NULL; char *old_urls = NULL; /* Get old URLs to preserve them. */ ldap_get_option(ld, LDAP_OPT_URI, &old_urls); /* Parse the search URL. */ ret = ldap_url_parse(url, &url_desc); if (ret == LDAP_SUCCESS) { /* Set the host/port from the URL. */ ret = ldap_set_option(ld, LDAP_OPT_URI, url); if (ret == LDAP_OPT_SUCCESS) { ldap_search_ext(ld, url_desc->lud_dn, url_desc->lud_scope, url_desc->lud_filter, url_desc->lud_attrs, attrsonly, NULL, NULL, NULL, 0, &ret); } } /* Reset the original URLs. */ ldap_set_option(ld, LDAP_OPT_URI, old_urls); /* Free parsed URL structure. */ ldap_free_urldesc(url_desc); #else ret = ldap_url_search(ld, url, attrsonly); #endif return ret; } static int perldap_ldap_url_search_s(LDAP *ld, char *url, int attrsonly, LDAPMessage **res) { int ret = 0; #ifdef USE_OPENLDAP LDAPURLDesc *url_desc; char *old_urls = NULL; /* Get old URLs to preserve them. */ ldap_get_option(ld, LDAP_OPT_URI, &old_urls); /* Parse the search URL. */ ret = ldap_url_parse(url, &url_desc); if (ret == LDAP_SUCCESS) { /* Set the host/port from the URL. */ ret = ldap_set_option(ld, LDAP_OPT_URI, url); if (ret == LDAP_OPT_SUCCESS) { ret = ldap_search_ext_s(ld, url_desc->lud_dn, url_desc->lud_scope, url_desc->lud_filter, url_desc->lud_attrs, attrsonly, NULL, NULL, NULL, 0, res); } } /* Reset the original URLs. */ ldap_set_option(ld, LDAP_OPT_URI, old_urls); /* Free parsed URL structure. */ ldap_free_urldesc(url_desc); #else ret = ldap_url_search_s(ld, url, attrsonly, res); #endif return ret; } static int perldap_ldap_url_search_st(LDAP *ld, char *url, int attrsonly, struct timeval *timeout, LDAPMessage **res) { int ret = 0; #ifdef USE_OPENLDAP LDAPURLDesc *url_desc; char *old_urls = NULL; /* Get old URLs to preserve them. */ ldap_get_option(ld, LDAP_OPT_URI, &old_urls); /* Parse the search URL. */ ret = ldap_url_parse(url, &url_desc); if (ret == LDAP_SUCCESS) { /* Set the host/port from the URL. */ ret = ldap_set_option(ld, LDAP_OPT_URI, url); if (ret == LDAP_OPT_SUCCESS) { ret = ldap_search_ext_s(ld, url_desc->lud_dn, url_desc->lud_scope, url_desc->lud_filter, url_desc->lud_attrs, attrsonly, NULL, NULL, timeout, 0, res); } } /* Reset the original URLs. */ ldap_set_option(ld, LDAP_OPT_URI, old_urls); /* Free parsed URL structure. */ ldap_free_urldesc(url_desc); #else ret = ldap_url_search_st(ld, url, attrsonly, timeout, res); #endif return ret; } static int perldap_ldapssl_client_init(const char *certdbpath, void *certdbhandle) { int ret = 0; #ifdef USE_OPENLDAP ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, certdbpath); #else ret = ldapssl_client_init(certdbpath, certdbhandle); #endif return ret; } static int perldap_ldapssl_enable_clientauth(LDAP *ld, char *keynickname, char *keypasswd, char *certnickname) { int ret = 0; #ifdef USE_OPENLDAP ret = ldap_set_option(ld, LDAP_OPT_X_TLS_KEYFILE, keynickname); if (ret == 0) { ret = ldap_set_option(ld, LDAP_OPT_X_TLS_CERTFILE, certnickname); } #else ret = ldapssl_enable_clientauth(ld, keynickname, keypasswd, certnickname); #endif return ret; } static LDAP * perldap_ldapssl_init(const char *host, const char *port, int secure) { LDAP *ret = NULL; #ifdef USE_OPENLDAP char *ldapurl; int ldapurl_len; if (host && port) { ldapurl_len = strlen(host) + strlen(port) + 11; ldapurl = (char *)perldap_malloc(ldapurl_len); snprintf(ldapurl, ldapurl_len, "ldap%s://%s:%s/", (secure != 0 ? "s" : ""), host, port); ldap_initialize(&ret, ldapurl); perldap_free((void *)ldapurl); } #else ret = ldapssl_init(host, atoi(port), secure); #endif return ret; } #ifdef USE_OPENLDAP static int perldap_et_cmp( const void *aa, const void *bb ) { int i, rc; struct entrything *a = (struct entrything *)aa; struct entrything *b = (struct entrything *)bb; if ( a->et_vals == NULL && b->et_vals == NULL ) return( 0 ); if ( a->et_vals == NULL ) return( -1 ); if ( b->et_vals == NULL ) return( 1 ); for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) { if ( (rc = (*perldap_et_cmp_fn)( a->et_vals[i], b->et_vals[i] )) != 0 ) { return( rc ); } } if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL ) return( 0 ); if ( a->et_vals[i] == NULL ) return( -1 ); return( 1 ); } #endif /* Return a char ** when passed a reference to an AV */ static char ** avref2charptrptr(SV *avref) { I32 avref_arraylen; int ix_av; SV **current_val; char **tmp_cpp; if ((! SvROK(avref)) || (SvTYPE(SvRV(avref)) != SVt_PVAV) || ((avref_arraylen = av_len((AV *)SvRV(avref))) < 0)) { return NULL; } Newz(1,tmp_cpp,avref_arraylen+2,char *); for (ix_av = 0;ix_av <= avref_arraylen;ix_av++) { current_val = av_fetch((AV *)SvRV(avref),ix_av,0); tmp_cpp[ix_av] = StrDup(SvPV(*current_val,PL_na)); } tmp_cpp[ix_av] = NULL; return (tmp_cpp); } /* Return a struct berval ** when passed a reference to an AV */ static struct berval ** avref2berptrptr(SV *avref) { I32 avref_arraylen; int ix_av,val_len; SV **current_val; char *tmp_char,*tmp2; struct berval **tmp_ber; if ((! SvROK(avref)) || (SvTYPE(SvRV(avref)) != SVt_PVAV) || ((avref_arraylen = av_len((AV *)SvRV(avref))) < 0)) { return NULL; } Newz(1,tmp_ber,avref_arraylen+2,struct berval *); for (ix_av = 0;ix_av <= avref_arraylen;ix_av++) { New(1,tmp_ber[ix_av],1,struct berval); current_val = av_fetch((AV *)SvRV(avref),ix_av,0); tmp_char = SvPV(*current_val,PL_na); val_len = SvCUR(*current_val); Newz(1,tmp2,val_len+1,char); Copy(tmp_char,tmp2,val_len,char); tmp_ber[ix_av]->bv_val = tmp2; tmp_ber[ix_av]->bv_len = val_len; } tmp_ber[ix_av] = NULL; return(tmp_ber); } /* Return an AV reference when given a char ** */ static SV* charptrptr2avref(char **cppval) { AV* tmp_av = newAV(); SV* tmp_ref = newRV((SV*)tmp_av); int ix; if (cppval != NULL) { for (ix = 0; cppval[ix] != NULL; ix++) { SV* SVval = newSVpv(cppval[ix],0); av_push(tmp_av,SVval); } perldap_ldap_value_free(cppval); } return(tmp_ref); } /* Return an AV Reference when given a struct berval ** */ static SV* berptrptr2avref(struct berval **bval) { AV* tmp_av = newAV(); SV* tmp_ref = newRV((SV*)tmp_av); int ix; if (bval != NULL) { for(ix = 0; bval[ix] != NULL; ix++) { SV *SVval = newSVpv(bval[ix]->bv_val,bval[ix]->bv_len); av_push(tmp_av,SVval); } ldap_value_free_len(bval); } return(tmp_ref); } /* parse1mod - Take a single reference, figure out if it is a HASH, */ /* ARRAY, or SCALAR, then extract the values and attributes and */ /* return a single LDAPMod pointer to this data. */ static LDAPMod * parse1mod(SV *ldap_value_ref,char *ldap_current_attribute, int ldap_add_func,int cont) { LDAPMod *ldap_current_mod; static HV *ldap_current_values_hv; HE *ldap_change_element; char *ldap_current_modop; SV *ldap_current_value_sv; I32 keylen; int ldap_isa_ber = 0; if (ldap_current_attribute == NULL) return(NULL); Newz(1,ldap_current_mod,1,LDAPMod); ldap_current_mod->mod_type = StrDup(ldap_current_attribute); if (SvROK(ldap_value_ref)) { if (SvTYPE(SvRV(ldap_value_ref)) == SVt_PVHV) { if (!cont) { ldap_current_values_hv = (HV *) SvRV(ldap_value_ref); hv_iterinit(ldap_current_values_hv); } if ((ldap_change_element = hv_iternext(ldap_current_values_hv)) == NULL) return(NULL); ldap_current_modop = hv_iterkey(ldap_change_element,&keylen); ldap_current_value_sv = hv_iterval(ldap_current_values_hv, ldap_change_element); if (ldap_add_func == 1) { ldap_current_mod->mod_op = 0; } else { if (strchr(ldap_current_modop,'a') != NULL) { ldap_current_mod->mod_op = LDAP_MOD_ADD; } else if (strchr(ldap_current_modop,'r') != NULL) { ldap_current_mod->mod_op = LDAP_MOD_REPLACE; } else if (strchr(ldap_current_modop,'d') != NULL) { ldap_current_mod->mod_op = LDAP_MOD_DELETE; } else { return(NULL); } } if (strchr(ldap_current_modop,'b') != NULL) { ldap_isa_ber = 1; ldap_current_mod->mod_op = ldap_current_mod->mod_op | LDAP_MOD_BVALUES; } if (SvTYPE(SvRV(ldap_current_value_sv)) == SVt_PVAV) { if (ldap_isa_ber == 1) { ldap_current_mod->mod_bvalues = avref2berptrptr(ldap_current_value_sv); } else { ldap_current_mod->mod_values = avref2charptrptr(ldap_current_value_sv); } } } else if (SvTYPE(SvRV(ldap_value_ref)) == SVt_PVAV) { if (cont) return NULL; if (ldap_add_func == 1) ldap_current_mod->mod_op = 0; else ldap_current_mod->mod_op = LDAP_MOD_REPLACE; ldap_current_mod->mod_values = avref2charptrptr(ldap_value_ref); if (ldap_current_mod->mod_values == NULL) { ldap_current_mod->mod_op = LDAP_MOD_DELETE; } } } else { if (cont) return NULL; if (strcmp(SvPV(ldap_value_ref,PL_na),"") == 0) { if (ldap_add_func != 1) { ldap_current_mod->mod_op = LDAP_MOD_DELETE; ldap_current_mod->mod_values = NULL; } else { return(NULL); } } else { if (ldap_add_func == 1) { ldap_current_mod->mod_op = 0; } else { ldap_current_mod->mod_op = LDAP_MOD_REPLACE; } New(1,ldap_current_mod->mod_values,2,char *); ldap_current_mod->mod_values[0] = StrDup(SvPV(ldap_value_ref,PL_na)); ldap_current_mod->mod_values[1] = NULL; } } return(ldap_current_mod); } /* calc_mod_size */ /* Calculates the number of LDAPMod's buried inside the ldap_change passed */ /* in. This is used by hash2mod to calculate the size to allocate in Newz */ static int calc_mod_size(HV *ldap_change) { int mod_size = 0; HE *ldap_change_element; SV *ldap_change_element_value_ref; HV *ldap_change_element_value; hv_iterinit(ldap_change); while((ldap_change_element = hv_iternext(ldap_change)) != NULL) { ldap_change_element_value_ref = hv_iterval(ldap_change,ldap_change_element); /* Hashes can take up multiple mod slots. */ if ( (SvROK(ldap_change_element_value_ref)) && (SvTYPE(SvRV(ldap_change_element_value_ref)) == SVt_PVHV) ) { ldap_change_element_value = (HV *)SvRV(ldap_change_element_value_ref); hv_iterinit(ldap_change_element_value); while ( hv_iternext(ldap_change_element_value) != NULL ) { mod_size++; } } /* scalars and array references only take up one mod slot */ else { mod_size++; } } return(mod_size); } /* hash2mod - Cycle through all the keys in the hash and properly call */ /* the appropriate functions to build a NULL terminated list of */ /* LDAPMod pointers. */ static LDAPMod ** hash2mod(SV *ldap_change_ref,int ldap_add_func,const char *func) { LDAPMod **ldapmod = NULL; LDAPMod *ldap_current_mod; int ldap_attribute_count = 0; HE *ldap_change_element; char *ldap_current_attribute; SV *ldap_current_value_sv; I32 keylen; HV *ldap_change; if (!SvROK(ldap_change_ref) || SvTYPE(SvRV(ldap_change_ref)) != SVt_PVHV) croak("Mozilla::LDAP::API::%s needs Hash reference as argument 3.",func); ldap_change = (HV *)SvRV(ldap_change_ref); Newz(1,ldapmod,1+calc_mod_size(ldap_change),LDAPMod *); hv_iterinit(ldap_change); while((ldap_change_element = hv_iternext(ldap_change)) != NULL) { ldap_current_attribute = hv_iterkey(ldap_change_element,&keylen); ldap_current_value_sv = hv_iterval(ldap_change,ldap_change_element); ldap_current_mod = parse1mod(ldap_current_value_sv, ldap_current_attribute,ldap_add_func,0); while (ldap_current_mod != NULL) { ldap_attribute_count++; ldapmod[ldap_attribute_count-1] = (LDAPMod *)ldap_current_mod; ldap_current_mod = parse1mod(ldap_current_value_sv, ldap_current_attribute,ldap_add_func,1); } } ldapmod[ldap_attribute_count] = NULL; return ldapmod; } /* StrCaseCmp - Replacement for strcasecmp, since it doesn't exist on many systems, including NT... */ static int StrCaseCmp(const char *s, const char *t) { while (*s && *t && toupper(*s) == toupper(*t)) { s++; t++; } return(toupper(*s) - toupper(*t)); } /* * StrDup * * Duplicates a string, but uses the Perl memory allocation * routines (so it can be free by the internal routines */ static char * StrDup(const char *source) { char *dest; STRLEN length; if ( source == NULL ) return(NULL); length = strlen(source); Newz(1,dest,length+1,char); Copy(source,dest,length+1,char); return(dest); } /* internal_rebind_proc - Wrapper to call a PERL rebind process. We * need separate rebind callbacks for MozLDAP and OpenLDAP. */ #ifdef USE_OPENLDAP static int LDAP_CALL internal_rebind_proc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *arg) { int ret; struct berval cred; int count = 0; int authmethod; char *pwd; char *dn; dSP; ENTER ; SAVETMPS ; count = perl_call_sv(ldap_perl_rebindproc,G_ARRAY|G_NOARGS); SPAGAIN; if (count != 3) croak("ldap_perl_rebindproc: Expected DN, PASSWORD, and AUTHTYPE returned.\n"); authmethod = POPi; pwd = StrDup(POPp); dn = StrDup(POPp); FREETMPS ; LEAVE ; cred.bv_val = pwd; cred.bv_len = strlen(pwd); ret = ldap_sasl_bind_s(ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); if (dn) { Safefree(dn); } if (pwd) { Safefree(pwd); } return ret; } /* NT and internal_rebind_proc hate each other, so they need this... */ static int LDAP_CALL ldap_default_rebind_proc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *arg) { int ret = 0; struct berval cred; if (!ldap_default_rebind_dn || !ldap_default_rebind_pwd) { return LDAP_OPERATIONS_ERROR; } cred.bv_val = ldap_default_rebind_pwd; cred.bv_len = strlen(ldap_default_rebind_pwd); ret = ldap_sasl_bind_s(ld, ldap_default_rebind_dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); return ret; } #else /* !USE_OPENLDAP */ static int LDAP_CALL internal_rebind_proc(LDAP *ld, char **dnp, char **pwp, int *authmethodp, int freeit, void *arg) { if (freeit == 0) { int count = 0; dSP; ENTER ; SAVETMPS ; count = perl_call_sv(ldap_perl_rebindproc,G_ARRAY|G_NOARGS); SPAGAIN; if (count != 3) croak("ldap_perl_rebindproc: Expected DN, PASSWORD, and AUTHTYPE returned.\n"); *authmethodp = POPi; *pwp = StrDup(POPp); *dnp = StrDup(POPp); PUTBACK ; FREETMPS ; LEAVE ; } else { if (dnp && *dnp) { Safefree(*dnp); } if (pwp && *pwp) { Safefree(*pwp); } } return(LDAP_SUCCESS); } /* NT and internal_rebind_proc hate each other, so they need this... */ static int LDAP_CALL ldap_default_rebind_proc(LDAP *ld, char **dn, char **pwd, int *auth, int freeit, void *arg) { if (!ldap_default_rebind_dn || !ldap_default_rebind_pwd) { *dn = NULL; *pwd = NULL; *auth = 0; return LDAP_OPERATIONS_ERROR; } *dn = ldap_default_rebind_dn; *pwd = ldap_default_rebind_pwd; *auth = ldap_default_rebind_auth; return LDAP_SUCCESS; } #endif /* internal_sortcmp_proc - Wrapper to call a PERL cmp function */ static int internal_sortcmp_proc(const char *s1, const char *s2) { int count; int res; dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(s1, 0))); XPUSHs(sv_2mortal(newSVpv(s2, 0))); PUTBACK; count = perl_call_sv(ldap_perl_sortcmp, G_SCALAR); SPAGAIN; if (count != 1) croak("ldap_perl_sortcmp: Expected an INT to be returned.\n"); res = POPi; PUTBACK; FREETMPS; LEAVE; return res; } MODULE = Mozilla::LDAP::API PACKAGE = Mozilla::LDAP::API PROTOTYPES: ENABLE BOOT: if ( perldap_init() != 0) { fprintf(stderr, "Error loading Mozilla::LDAP::API: perldap_init failed\n"); exit(1); } double constant(name,arg) char * name int arg int ldap_abandon(ld,msgid) LDAP * ld int msgid CODE: RETVAL = ldap_abandon_ext(ld, msgid, NULL, NULL); OUTPUT: RETVAL int ldap_abandon_ext(ld,msgid,serverctrls,clientctrls) LDAP * ld int msgid LDAPControl ** serverctrls LDAPControl ** clientctrls int ldap_add(ld,dn,attrs) LDAP * ld const char * dn LDAPMod ** attrs = hash2mod($arg,1,"$func_name"); CODE: ldap_add_ext(ld, dn, attrs, NULL, NULL, &RETVAL); OUTPUT: RETVAL CLEANUP: if (attrs) ldap_mods_free(attrs, 1); int ldap_add_ext(ld,dn,attrs,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn LDAPMod ** attrs = hash2mod($arg,1,"$func_name"); LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp CLEANUP: if (attrs) ldap_mods_free(attrs, 1); int ldap_add_ext_s(ld,dn,attrs,serverctrls,clientctrls) LDAP * ld const char * dn LDAPMod ** attrs = hash2mod($arg,1,"$func_name"); LDAPControl ** serverctrls LDAPControl ** clientctrls CLEANUP: if (attrs) ldap_mods_free(attrs, 1); int ldap_add_s(ld,dn,attrs) LDAP * ld const char * dn LDAPMod ** attrs = hash2mod($arg,1,"$func_name"); CODE: RETVAL = ldap_add_ext_s(ld, dn, attrs, NULL, NULL); OUTPUT: RETVAL CLEANUP: if (attrs) ldap_mods_free(attrs, 1); void ldap_ber_free(ber,freebuf) BerElement * ber int freebuf CODE: { if (ber) { ber_free(ber, freebuf); } } int ldap_bind(ld,dn,passwd,authmethod) LDAP * ld const char * dn char * passwd PREINIT: struct berval cred; CODE: cred.bv_val = passwd; cred.bv_len = ( passwd == NULL ) ? 0 : strlen( passwd ); ldap_sasl_bind(ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_bind_s(ld,dn,passwd,authmethod) LDAP * ld const char * dn char * passwd PREINIT: struct berval cred; CODE: cred.bv_val = passwd; cred.bv_len = ( passwd == NULL ) ? 0 : strlen( passwd ); RETVAL = ldap_sasl_bind_s(ld, dn, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); OUTPUT: RETVAL int ldap_compare(ld,dn,attr,value) LDAP * ld const char * dn const char * attr char * value PREINIT: struct berval bvalue; CODE: bvalue.bv_val = value; bvalue.bv_len = ( value == NULL ) ? 0 : strlen( value ); ldap_compare_ext(ld, dn, attr, &bvalue, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_compare_ext(ld,dn,attr,bvalue,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn const char * attr struct berval &bvalue LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp int ldap_compare_ext_s(ld,dn,attr,bvalue,serverctrls,clientctrls) LDAP * ld const char * dn const char * attr struct berval &bvalue LDAPControl ** serverctrls LDAPControl ** clientctrls int ldap_compare_s(ld,dn,attr,value) LDAP * ld const char * dn const char * attr char * value PREINIT: struct berval bvalue; CODE: bvalue.bv_val = value; bvalue.bv_len = ( value == NULL ) ? 0 : strlen( value ); RETVAL = ldap_compare_ext_s(ld, dn, attr, &bvalue, NULL, NULL); OUTPUT: RETVAL void ldap_control_free(ctrl) LDAPControl * ctrl #ifdef CONTROLS_COUNT_WORKS int ldap_controls_count(ctrls) LDAPControl ** ctrls #endif void ldap_controls_free(ctrls) LDAPControl ** ctrls int ldap_count_entries(ld,result) LDAP * ld LDAPMessage * result int ldap_count_messages(ld,result) LDAP * ld LDAPMessage * result int ldap_count_references(ld,result) LDAP * ld LDAPMessage * result int ldap_create_filter(buf,buflen,pattern,prefix,suffix,attr,value,valwords) char * buf unsigned long buflen char * pattern char * prefix char * suffix char * attr char * value char ** valwords CODE: /* This is a not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = LDAP_NOT_SUPPORTED; #else RETVAL = ldap_create_filter(buf, buflen, pattern, prefix, suffix, attr, value, valwords); #endif OUTPUT: RETVAL buf CLEANUP: if (valwords) perldap_ldap_value_free(valwords); int ldap_create_persistentsearch_control(ld,changetypes,changesonly,return_echg_ctrls,ctrl_iscritical,ctrlp) LDAP * ld int changetypes int changesonly int return_echg_ctrls char ctrl_iscritical LDAPControl ** ctrlp = NO_INIT CODE: RETVAL = perldap_ldap_create_persistentsearch_control(ld, changetypes, changesonly, return_echg_ctrls, ctrl_iscritical, ctrlp); OUTPUT: RETVAL ctrlp int ldap_create_sort_control(ld,sortKeyList,ctrl_iscritical,ctrlp) LDAP * ld LDAPsortkey ** sortKeyList char ctrl_iscritical LDAPControl ** ctrlp = NO_INIT CODE: RETVAL = perldap_ldap_create_sort_control(ld, sortKeyList, ctrl_iscritical, ctrlp); OUTPUT: RETVAL ctrlp int ldap_create_sort_keylist(sortKeyList,string_rep) LDAPsortkey ** &sortKeyList = NO_INIT char * string_rep OUTPUT: RETVAL sortKeyList int ldap_create_virtuallist_control(ld,ldvlistp,ctrlp) LDAP * ld LDAPVirtualList *ldvlistp LDAPControl ** ctrlp = NO_INIT CODE: RETVAL = perldap_ldap_create_virtuallist_control(ld, ldvlistp, ctrlp); OUTPUT: RETVAL ctrlp int ldap_delete(ld,dn) LDAP * ld const char * dn CODE: ldap_delete_ext(ld, dn, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_delete_ext(ld,dn,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp int ldap_delete_ext_s(ld,dn,serverctrls,clientctrls) LDAP * ld const char * dn LDAPControl ** serverctrls LDAPControl ** clientctrls int ldap_delete_s(ld,dn) LDAP * ld const char * dn CODE: RETVAL = ldap_delete_ext_s(ld, dn, NULL, NULL); OUTPUT: RETVAL char * ldap_dn2ufn(dn) const char * dn char * ldap_err2string(err) int err void ldap_explode_dn(dn,notypes) const char * dn const int notypes PPCODE: { char **MOZLDAP_VAL = ldap_explode_dn(dn,notypes); RET_CPP(MOZLDAP_VAL); } void ldap_explode_rdn(dn,notypes) const char * dn int notypes PPCODE: { char **MOZLDAP_VAL = ldap_explode_rdn(dn,notypes); RET_CPP(MOZLDAP_VAL); } int ldap_extended_operation(ld,requestoid,requestdata,serverctrls,clientctrls,msgidp) LDAP * ld const char * requestoid struct berval &requestdata LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp int ldap_extended_operation_s(ld,requestoid,requestdata,serverctrls,clientctrls,retoidp,retdatap) LDAP * ld const char * requestoid struct berval &requestdata LDAPControl ** serverctrls LDAPControl ** clientctrls char * &retoidp = NO_INIT struct berval *&retdatap = NO_INIT OUTPUT: RETVAL retoidp retdatap char * ldap_first_attribute(ld,entry,ber) LDAP * ld LDAPMessage * entry BerElement * &ber = NO_INIT OUTPUT: RETVAL ber CLEANUP: ldap_memfree(RETVAL); LDAPMessage * ldap_first_entry(ld,chain) LDAP * ld LDAPMessage * chain LDAPMessage * ldap_first_message(ld,res) LDAP * ld LDAPMessage * res LDAPMessage * ldap_first_reference(ld,res) LDAP * ld LDAPMessage * res void ldap_free_friendlymap(map) FriendlyMap * map CODE: /* This is a no-op when using OpenLDAP. */ #ifndef USE_OPENLDAP ldap_free_friendlymap(map); #endif void ldap_free_sort_keylist(sortKeyList) LDAPsortkey ** sortKeyList void ldap_free_urldesc(ludp) LDAPURLDesc * ludp char * ldap_friendly_name(filename,name,map) char * filename char * name FriendlyMap * map CODE: /* This is not implemented when using OpenLDAP. We just return * the original "un-friendly" name as MozLDAP does when there is * an error. */ #ifdef USE_OPENLDAP RETVAL = name; #else RETVAL = ldap_friendly_name(filename, name, map); #endif OUTPUT: RETVAL char * ldap_get_dn(ld,entry) LDAP * ld LDAPMessage * entry CLEANUP: ldap_memfree(RETVAL); int ldap_get_entry_controls(ld,entry,serverctrlsp) LDAP * ld LDAPMessage * entry LDAPControl ** &serverctrlsp = NO_INIT OUTPUT: RETVAL serverctrlsp void ldap_getfilter_free(lfdp) LDAPFiltDesc * lfdp CODE: /* This is a no-op when using OpenLDAP. */ #ifndef USE_OPENLDAP ldap_getfilter_free(lfdp); #endif LDAPFiltInfo * ldap_getfirstfilter(lfdp,tagpat,value) LDAPFiltDesc * lfdp char * tagpat char * value CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = NULL; #else RETVAL = ldap_getfirstfilter(lfdp, tagpat, value); #endif OUTPUT: RETVAL void ldap_get_lang_values(ld,entry,target,type) LDAP * ld LDAPMessage * entry const char * target char * type PPCODE: { /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP int ret = LDAP_NOT_SUPPORTED; char ** MOZLDAP_VAL = NULL; ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else char ** MOZLDAP_VAL = ldap_get_lang_values(ld,entry,target,&type); #endif RET_CPP(MOZLDAP_VAL); } void ldap_get_lang_values_len(ld,entry,target,type) LDAP * ld LDAPMessage * entry const char * target char * type PPCODE: { /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP int ret = LDAP_NOT_SUPPORTED; struct berval ** MOZLDAP_VAL = NULL; ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else struct berval ** MOZLDAP_VAL = ldap_get_lang_values_len(ld,entry,target,&type); #endif RET_BVPP(MOZLDAP_VAL); } int ldap_get_lderrno(ld, ...) LDAP * ld CODE: { char *match = (char *)NULL, *msg = (char *)NULL; SV *tmp, *m = (SV *)NULL, *s = (SV *)NULL; if (items > 1) { m = ST(1); if (items > 2) s = ST(2); } #ifdef USE_OPENLDAP ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &RETVAL); if (m && SvROK(m)) { ldap_get_option(ld, LDAP_OPT_MATCHED_DN, &match); } if (s && SvROK(s)) { #ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &msg); #else ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &msg); #endif } #else /* !USE_OPENLDAP */ RETVAL = ldap_get_lderrno(ld, (m && SvROK(m)) ? &match : (char **)NULL, (s && SvROK(s)) ? &msg : (char **)NULL); #endif if (match) { tmp = SvRV(m); if (SvTYPE(tmp) <= SVt_PV) sv_setpv(tmp, match); } if (msg) { tmp = SvRV(s); if (SvTYPE(tmp) <= SVt_PV) sv_setpv(tmp, msg); } } OUTPUT: RETVAL LDAPFiltInfo * ldap_getnextfilter(lfdp) LDAPFiltDesc *lfdp CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = NULL; #else RETVAL = ldap_getnextfilter(lfdp); #endif OUTPUT: RETVAL int ldap_get_option(ld,option,optdata) LDAP * ld int option int &optdata = NO_INIT OUTPUT: RETVAL optdata void ldap_get_values(ld,entry,target) LDAP * ld LDAPMessage * entry const char * target PPCODE: { /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP int ret = LDAP_NOT_SUPPORTED; char **MOZLDAP_VAL = NULL; ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &ret); #else char **MOZLDAP_VAL = ldap_get_values(ld,entry,target); #endif RET_CPP(MOZLDAP_VAL); } void ldap_get_values_len(ld,entry,target) LDAP * ld LDAPMessage * entry const char * target PPCODE: { struct berval **MOZLDAP_VAL = ldap_get_values_len(ld,entry,target); RET_BVPP(MOZLDAP_VAL); } LDAP * ldap_init(host,port) const char * host const char * port PREINIT: char * url = NULL; int url_len = 0; CODE: RETVAL = NULL; /* Create the LDAP URL */ if (host && port) { url_len = strlen(host) + strlen(port) + 10; url = (char *)perldap_malloc(url_len); snprintf(url, url_len, "ldap://%s:%s/", host, port); ldap_initialize(&RETVAL, url); perldap_free((void *)url); } OUTPUT: RETVAL LDAPFiltDesc * ldap_init_getfilter(fname) char * fname CODE: #ifdef USE_OPENLDAP RETVAL = NULL; #else RETVAL = ldap_init_getfilter(fname); #endif OUTPUT: RETVAL LDAPFiltDesc * ldap_init_getfilter_buf(buf,buflen) char * buf long buflen CODE: #ifdef USE_OPENLDAP RETVAL = NULL; #else RETVAL = ldap_init_getfilter_buf(buf,buflen); #endif OUTPUT: RETVAL int ldap_is_ldap_url(url) char * url void ldap_memcache_destroy(cache) LDAPMemCache * cache CODE: /* This is a no-op when using OpenLDAP. */ #ifndef USE_OPENLDAP ldap_memcache_destroy(cache); #endif void ldap_memcache_flush(cache,dn,scope) LDAPMemCache * cache char * dn int scope CODE: /* This is a no-op when using OpenLDAP. */ #ifndef USE_OPENLDAP ldap_memcache_flush(cache, dn, scope); #endif int ldap_memcache_get(ld,cachep) LDAP * ld LDAPMemCache ** cachep = NO_INIT CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = LDAP_NOT_SUPPORTED; #else RETVAL = ldap_memcache_get(ld, cachep); #endif OUTPUT: RETVAL cachep int ldap_memcache_init(ttl,size,baseDNs,cachep) unsigned long ttl unsigned long size char ** baseDNs LDAPMemCache ** cachep = NO_INIT CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = LDAP_NOT_SUPPORTED; #else RETVAL = ldap_memcache_init(ttl,size,baseDNs,NULL,cachep); #endif OUTPUT: RETVAL cachep CLEANUP: if (baseDNs) perldap_ldap_value_free(baseDNs); int ldap_memcache_set(ld,cache) LDAP * ld LDAPMemCache * cache CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = LDAP_NOT_SUPPORTED; #else RETVAL = ldap_memcache_set(ld, cache); #endif OUTPUT: RETVAL void ldap_memcache_update(cache) LDAPMemCache * cache CODE: /* This is a no-op when using OpenLDAP. */ #ifndef USE_OPENLDAP ldap_memcache_update(cache); #endif void ldap_memfree(p) void * p int ldap_modify(ld,dn,mods) LDAP * ld const char * dn LDAPMod ** mods = hash2mod($arg,0,"$func_name"); CODE: ldap_modify_ext(ld, dn, mods, NULL, NULL, &RETVAL); OUTPUT: RETVAL CLEANUP: if (mods) ldap_mods_free(mods, 1); int ldap_modify_ext(ld,dn,mods,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn LDAPMod ** mods = hash2mod($arg,0,"$func_name"); LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp OUTPUT: RETVAL msgidp CLEANUP: if (mods) ldap_mods_free(mods, 1); int ldap_modify_ext_s(ld,dn,mods,serverctrls,clientctrls) LDAP * ld const char * dn LDAPMod ** mods = hash2mod($arg,0,"$func_name"); LDAPControl ** serverctrls LDAPControl ** clientctrls CLEANUP: if (mods) ldap_mods_free(mods, 1); int ldap_modify_s(ld,dn,mods) LDAP * ld const char * dn LDAPMod ** mods = hash2mod($arg, 0, "$func_name"); CODE: RETVAL = ldap_modify_ext_s(ld, dn, mods, NULL, NULL); OUTPUT: RETVAL CLEANUP: if (mods) ldap_mods_free(mods, 1); int ldap_modrdn(ld,dn,newrdn) LDAP * ld const char * dn const char * newrdn CODE: ldap_rename(ld, dn, newrdn, NULL, 1, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_modrdn_s(ld,dn,newrdn) LDAP * ld const char * dn const char * newrdn CODE: RETVAL = ldap_rename_s(ld, dn, newrdn, NULL, 1, NULL, NULL); OUTPUT: RETVAL int ldap_modrdn2(ld,dn,newrdn,deleteoldrdn) LDAP * ld const char * dn const char * newrdn int deleteoldrdn CODE: ldap_rename(ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_modrdn2_s(ld,dn,newrdn,deleteoldrdn) LDAP * ld const char * dn const char * newrdn int deleteoldrdn CODE: RETVAL = ldap_rename_s(ld, dn, newrdn, NULL, deleteoldrdn, NULL, NULL); OUTPUT: RETVAL void ldap_mods_free(mods,freemods) LDAPMod ** mods int freemods int ldap_msgfree(lm) LDAPMessage * lm CODE: { if (lm) { RETVAL = ldap_msgfree(lm); } else { RETVAL = LDAP_SUCCESS; } } OUTPUT: RETVAL int ldap_msgid(lm) LDAPMessage * lm int ldap_msgtype(lm) LDAPMessage * lm int ldap_multisort_entries(ld,chain,attr,...) LDAP * ld LDAPMessage * &chain char ** attr CODE: { SV *cmp; LDAP_CMP_CALLBACK *func = &StrCaseCmp; if (items > 3) { cmp = ST(3); if (SvROK(cmp) && (SvTYPE(SvRV(cmp)) == SVt_PVCV)) { func = &internal_sortcmp_proc; ldap_perl_sortcmp = cmp; } } RETVAL = perldap_ldap_multisort_entries(ld,&chain,attr,func); } OUTPUT: RETVAL chain CLEANUP: if (attr) perldap_ldap_value_free(attr); char * ldap_next_attribute(ld,entry,ber) LDAP * ld LDAPMessage * entry BerElement * ber OUTPUT: RETVAL ber CLEANUP: ldap_memfree(RETVAL); LDAPMessage * ldap_next_entry(ld,entry) LDAP * ld LDAPMessage * entry LDAPMessage * ldap_next_message(ld,msg) LDAP * ld LDAPMessage * msg LDAPMessage * ldap_next_reference(ld,ref) LDAP * ld LDAPMessage * ref int ldap_parse_entrychange_control(ld,ctrls,chgtypep,prevdnp,chgnumpresentp,chgnump) LDAP * ld LDAPControl ** ctrls my_chgtype_t &chgtypep = NO_INIT char * &prevdnp = NO_INIT int &chgnumpresentp = NO_INIT my_chgnum_t &chgnump = NO_INIT CODE: RETVAL = perldap_ldap_parse_entrychange_control(ld, ctrls, &chgtypep, &prevdnp, &chgnumpresentp, &chgnump); OUTPUT: RETVAL chgtypep prevdnp chgnumpresentp chgnump int ldap_parse_extended_result(ld,res,retoidp,retdatap,freeit) LDAP * ld LDAPMessage * res char * &retoidp = NO_INIT struct berval *&retdatap = NO_INIT int freeit OUTPUT: RETVAL retoidp retdatap int ldap_parse_reference(ld,ref,referalsp,serverctrlsp,freeit) LDAP * ld LDAPMessage * ref char ** &referalsp = NO_INIT LDAPControl ** &serverctrlsp = NO_INIT int freeit OUTPUT: RETVAL referalsp serverctrlsp int ldap_parse_result(ld,res,errcodep,matcheddnp,errmsgp,referralsp,serverctrlsp,freeit) LDAP * ld LDAPMessage * res int &errcodep = NO_INIT char * &matcheddnp = NO_INIT char * &errmsgp = NO_INIT char ** &referralsp = NO_INIT LDAPControl ** &serverctrlsp = NO_INIT int freeit OUTPUT: RETVAL errcodep matcheddnp errmsgp referralsp serverctrlsp int ldap_parse_sasl_bind_result(ld,res,servercredp,freeit) LDAP * ld LDAPMessage * res struct berval * &servercredp int freeit int ldap_parse_sort_control(ld,ctrls,result,attribute) LDAP * ld LDAPControl ** ctrls my_result_t &result = NO_INIT char * &attribute = NO_INIT CODE: RETVAL = perldap_ldap_parse_sort_control(ld, ctrls, &result, &attribute); OUTPUT: RETVAL result attribute int ldap_parse_virtuallist_control(ld,ctrls,target_posp,list_sizep,errcodep) LDAP * ld LDAPControl ** ctrls my_vlvint_t &target_posp = NO_INIT my_vlvint_t &list_sizep = NO_INIT int &errcodep = NO_INIT CODE: RETVAL = perldap_ldap_parse_virtuallist_control(ld, ctrls, &target_posp, &list_sizep, &errcodep); OUTPUT: RETVAL target_posp list_sizep errcodep void ldap_perror(ld,s) LDAP * ld const char * s CODE: perldap_ldap_perror(ld, s); int ldap_rename(ld,dn,newrdn,newparent,deleteoldrdn,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn const char * newrdn const char * newparent int deleteoldrdn LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp int ldap_rename_s(ld,dn,newrdn,newparent,deleteoldrdn,serverctrls,clientctrls) LDAP * ld const char * dn const char * newrdn const char * newparent int deleteoldrdn LDAPControl ** serverctrls LDAPControl ** clientctrls int ldap_result(ld,msgid,all,timeout,result) LDAP * ld int msgid int all struct timeval &timeout LDAPMessage * &result = NO_INIT OUTPUT: RETVAL result int ldap_result2error(ld,r,freeit) LDAP * ld LDAPMessage * r int freeit CODE: ldap_parse_result(ld, r, &RETVAL, NULL, NULL, NULL, NULL, freeit); OUTPUT: RETVAL int ldap_sasl_bind(ld,dn,mechanism,cred,serverctrls,clientctrls,msgidp) LDAP * ld const char * dn const char * mechanism struct berval &cred LDAPControl ** serverctrls LDAPControl ** clientctrls int &msgidp = NO_INIT OUTPUT: RETVAL msgidp int ldap_sasl_bind_s(ld,dn,mechanism,cred,serverctrls,clientctrls,servercredp) LDAP * ld const char * dn const char * mechanism struct berval &cred LDAPControl ** serverctrls LDAPControl ** clientctrls struct berval *&servercredp OUTPUT: RETVAL servercredp int ldap_search(ld,base,scope,filter,attrs,attrsonly) LDAP * ld const char * base int scope const char * filter char ** attrs int attrsonly CODE: ldap_search_ext(ld, base, scope, filter, attrs, attrsonly, NULL, NULL, NULL, 0, &RETVAL); OUTPUT: RETVAL CLEANUP: if (attrs) perldap_ldap_value_free(attrs); int ldap_search_ext(ld,base,scope,filter,attrs,attrsonly,serverctrls,clientctrls,timeoutp,sizelimit,msgidp) LDAP * ld const char * base int scope const char * filter char ** attrs int attrsonly LDAPControl ** serverctrls LDAPControl ** clientctrls struct timeval &timeoutp int sizelimit int &msgidp = NO_INIT OUTPUT: RETVAL msgidp CLEANUP: if (attrs) perldap_ldap_value_free(attrs); int ldap_search_ext_s(ld,base,scope,filter,attrs,attrsonly,serverctrls,clientctrls,timeoutp,sizelimit,res) LDAP * ld const char * base int scope const char * filter char ** attrs int attrsonly LDAPControl ** serverctrls LDAPControl ** clientctrls struct timeval &timeoutp int sizelimit LDAPMessage * &res = NO_INIT OUTPUT: RETVAL res CLEANUP: if (attrs) perldap_ldap_value_free(attrs); int ldap_search_s(ld,base,scope,filter,attrs,attrsonly,res) LDAP * ld const char * base int scope const char * filter char ** attrs int attrsonly LDAPMessage * &res = NO_INIT CODE: RETVAL = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL, NULL, 0, &res); OUTPUT: RETVAL res CLEANUP: if (attrs) perldap_ldap_value_free(attrs); int ldap_search_st(ld,base,scope,filter,attrs,attrsonly,timeout,res) LDAP * ld const char * base int scope const char * filter char ** attrs int attrsonly struct timeval &timeout LDAPMessage * &res = NO_INIT CODE: RETVAL = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL, &timeout, 0, &res); OUTPUT: RETVAL res CLEANUP: if (attrs) perldap_ldap_value_free(attrs); int ldap_set_filter_additions(lfdp,prefix,suffix) LDAPFiltDesc * lfdp char * prefix char * suffix CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = LDAP_NOT_SUPPORTED; #else RETVAL = ldap_set_filter_additions(lfdp, prefix, suffix); #endif OUTPUT: RETVAL int ldap_set_lderrno(ld,e,m,s) LDAP * ld int e char * m char * s CODE: RETVAL = perldap_ldap_set_lderrno(ld, e, m, s); OUTPUT: RETVAL int ldap_set_option(ld,option,optdata) LDAP * ld int option int &optdata void ldap_set_rebind_proc(ld,rebindproc) LDAP * ld SV *rebindproc CODE: { if (SvTYPE(SvRV(rebindproc)) != SVt_PVCV) { ldap_set_rebind_proc(ld,NULL,NULL); } else { if (ldap_perl_rebindproc == (SV*)NULL) ldap_perl_rebindproc = newSVsv(rebindproc); else SvSetSV(ldap_perl_rebindproc,rebindproc); ldap_set_rebind_proc(ld,&internal_rebind_proc,NULL); } } void ldap_set_default_rebind_proc(ld, dn, pwd, auth) LDAP *ld char *dn char *pwd int auth CODE: { if ( ldap_default_rebind_dn != NULL ) { Safefree(ldap_default_rebind_dn); ldap_default_rebind_dn = NULL; } if ( ldap_default_rebind_pwd != NULL ) { Safefree(ldap_default_rebind_pwd); ldap_default_rebind_pwd = NULL; } ldap_default_rebind_dn = StrDup(dn); ldap_default_rebind_pwd = StrDup(pwd); ldap_default_rebind_auth = auth; ldap_set_rebind_proc(ld,&ldap_default_rebind_proc,NULL); } int ldap_simple_bind(ld,who,passwd) LDAP * ld const char * who char * passwd PREINIT: struct berval cred; CODE: cred.bv_val = passwd; cred.bv_len = strlen(passwd); ldap_sasl_bind(ld, who, LDAP_SASL_SIMPLE, &cred, NULL, NULL, &RETVAL); OUTPUT: RETVAL int ldap_simple_bind_s(ld,who,passwd) LDAP * ld const char * who char * passwd PREINIT: struct berval cred; CODE: cred.bv_val = passwd; cred.bv_len = strlen(passwd); RETVAL = ldap_sasl_bind_s(ld, who, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL); OUTPUT: RETVAL int ldap_sort_entries(ld,chain,attr,...) LDAP * ld LDAPMessage * &chain char * attr CODE: { SV *cmp; LDAP_CMP_CALLBACK *func = &StrCaseCmp; if (items > 3) { cmp = ST(3); if (SvROK(cmp) && (SvTYPE(SvRV(cmp)) == SVt_PVCV)) { func = &internal_sortcmp_proc; ldap_perl_sortcmp = cmp; } } RETVAL = perldap_ldap_sort_entries(ld,&chain,attr,func); } OUTPUT: RETVAL chain int ldap_unbind(ld) LDAP * ld CODE: RETVAL = ldap_unbind_ext(ld, NULL, NULL); OUTPUT: RETVAL int ldap_unbind_s(ld) LDAP * ld CODE: RETVAL = ldap_unbind_ext_s(ld, NULL, NULL); OUTPUT: RETVAL SV * ldap_url_parse(url) char * url CODE: { LDAPURLDesc *realcomp; int count,ret; HV* FullHash = newHV(); RETVAL = newRV((SV*)FullHash); ret = ldap_url_parse(url,&realcomp); if (ret == 0) { static char *host_key = "host"; static char *port_key = "port"; static char *dn_key = "dn"; static char *attr_key = "attr"; static char *scope_key = "scope"; static char *filter_key = "filter"; #ifdef USE_OPENLDAP static char *scheme_key = "scheme"; static char *exts_key = "exts"; static char *crit_exts_key = "crit_exts"; SV* scheme = newSVpv(realcomp->lud_scheme,0); SV* crit_exts = newSViv(realcomp->lud_crit_exts); AV* extsarray = newAV(); SV* extsref = newRV((SV*) extsarray); #else static char *options_key = "options"; SV* options = newSViv(realcomp->lud_options); #endif SV* host; /* = newSVpv(realcomp->lud_host,0); */ SV* port = newSViv(realcomp->lud_port); SV* dn; /* = newSVpv(realcomp->lud_dn,0); */ SV* scope = newSViv(realcomp->lud_scope); SV* filter = newSVpv(realcomp->lud_filter,0); AV* attrarray = newAV(); SV* attribref = newRV((SV*) attrarray); if (realcomp->lud_host) host = newSVpv(realcomp->lud_host,0); else host = newSVpv("",0); if (realcomp->lud_dn) dn = newSVpv(realcomp->lud_dn,0); else dn = newSVpv("",0); if (realcomp->lud_attrs != NULL) { for (count=0; realcomp->lud_attrs[count] != NULL; count++) { SV* SVval = newSVpv(realcomp->lud_attrs[count],0); av_push(attrarray, SVval); } } #ifdef USE_OPENLDAP if (realcomp->lud_exts != NULL) { for (count=0; realcomp->lud_exts[count] != NULL; count++) { SV* SVval = newSVpv(realcomp->lud_exts[count],0); av_push(extsarray, SVval); } } #endif hv_store(FullHash,host_key,strlen(host_key),host,0); hv_store(FullHash,port_key,strlen(port_key),port,0); hv_store(FullHash,dn_key,strlen(dn_key),dn,0); hv_store(FullHash,attr_key,strlen(attr_key),attribref,0); hv_store(FullHash,scope_key,strlen(scope_key),scope,0); hv_store(FullHash,filter_key,strlen(filter_key),filter,0); #ifdef USE_OPENLDAP hv_store(FullHash,scheme_key,strlen(scheme_key),scheme,0); hv_store(FullHash,exts_key,strlen(exts_key),extsref,0); hv_store(FullHash,crit_exts_key,strlen(crit_exts_key),crit_exts,0); #else hv_store(FullHash,options_key,strlen(options_key),options,0); #endif ldap_free_urldesc(realcomp); } else { RETVAL = &PL_sv_undef; } } OUTPUT: RETVAL int ldap_url_search(ld,url,attrsonly) LDAP * ld char * url int attrsonly CODE: RETVAL = perldap_ldap_url_search(ld, url, attrsonly); OUTPUT: RETVAL int ldap_url_search_s(ld,url,attrsonly,res) LDAP * ld char * url int attrsonly LDAPMessage * &res CODE: RETVAL = perldap_ldap_url_search_s(ld, url, attrsonly, &res); OUTPUT: RETVAL res int ldap_url_search_st(ld,url,attrsonly,timeout,res) LDAP * ld char * url int attrsonly struct timeval &timeout LDAPMessage * &res CODE: RETVAL = perldap_ldap_url_search_st(ld, url, attrsonly, &timeout, &res); OUTPUT: RETVAL res int ldap_version(ver) LDAPVersion * ver CODE: /* This is a no-op when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = 0; #else RETVAL = ldap_version(ver); #endif OUTPUT: RETVAL #ifdef USE_SSL int ldapssl_client_init(certdbpath,certdbhandle) const char * certdbpath void * certdbhandle CODE: RETVAL = perldap_ldapssl_client_init(certdbpath, certdbhandle); OUTPUT: RETVAL int ldapssl_clientauth_init(certdbpath,certdbhandle,needkeydb,keydbpath,keydbhandle) char * certdbpath void * certdbhandle int needkeydb char * keydbpath void * keydbhandle CODE: /* This is a no-op when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = 0; #else RETVAL = ldapssl_clientauth_init(certdbpath,certdbhandle,needkeydb,keydbpath,keydbhandle); #endif OUTPUT: RETVAL int ldapssl_enable_clientauth(ld,keynickname,keypasswd,certnickname) LDAP * ld char * keynickname char * keypasswd char * certnickname CODE: RETVAL = perldap_ldapssl_enable_clientauth(ld, keynickname, keypasswd, certnickname); OUTPUT: RETVAL LDAP * ldapssl_init(host,port,secure) const char * host const char * port int secure CODE: RETVAL = perldap_ldapssl_init(host,port,secure); OUTPUT: RETVAL int ldapssl_install_routines(ld) LDAP * ld CODE: /* This is a no-op when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = 0; #else RETVAL = ldapssl_install_routines(ld); #endif int ldap_start_tls_s(ld,serverctrls,clientctrls) LDAP *ld LDAPControl **serverctrls LDAPControl **clientctrls const char * ldapssl_err2string(prerrno) const int prerrno CODE: /* We just return "Unknown error." when using OpenLDAP. This * is the same string that MozLDAP returns when it has a problem * getting the error string. */ #ifdef USE_OPENLDAP RETVAL = "Unknown error."; #else RETVAL = ldapssl_err2string(prerrno); #endif OUTPUT: RETVAL int ldapssl_set_strength(ld,sslstrength) LDAP *ld int sslstrength CODE: /* This is not implemented when using OpenLDAP. */ #ifdef USE_OPENLDAP RETVAL = -1; #else RETVAL = ldapssl_set_strength(ld, sslstrength); #endif OUTPUT: RETVAL #endif #ifdef PRLDAP #ifndef USE_OPENLDAP #include #endif int prldap_install_routines(ld, shared) LDAP * ld int shared CODE: #ifdef USE_OPENLDAP RETVAL = 0; #else RETVAL = prldap_install_routines(ld, shared); #endif OUTPUT: RETVAL int prldap_set_session_option(ld, sessionarg, option, optdata) LDAP * ld void * sessionarg int option int optdata CODE: #ifdef USE_OPENLDAP RETVAL = 0; #else RETVAL = prldap_set_session_option(ld, sessionarg, option, optdata); #endif OUTPUT: RETVAL #endif /* PRLDAP */ # # local variables: # mode: c # c-basic-offset: 3 # indent-tabs-mode:t # end: perl-mozldap-1.5.3/constant.h0000444000076400007640000006277111426075705014616 0ustar richrich/* ******************************************************************************* * $Id: constant.h,v 1.8.2.5 2010/08/03 20:27:49 nkinder%redhat.com Exp $ * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is PerLDAP. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Clayton Donley * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* * DESCRIPTION * Constants. */ #ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef __cplusplus } #endif #include #ifdef PRLDAP #ifndef USE_OPENLDAP #include #endif #endif #ifdef USE_SSL #ifndef USE_OPENLDAP # include #endif #endif static int not_here(s) char *s; { croak("%s not implemented on this architecture", s); return -1; } double constant(name, arg) char *name; int arg; { errno = 0; if (name[0] == 'L' && name[1] == 'D' && name[2] == 'A' && name[3] == 'P' && name[4] == '_') { switch (name[5]) { case 'A': if (strEQ(name, "LDAP_ADMINLIMIT_EXCEEDED")) #ifdef LDAP_ADMINLIMIT_EXCEEDED return LDAP_ADMINLIMIT_EXCEEDED; #else goto not_there; #endif if (strEQ(name, "LDAP_AFFECTS_MULTIPLE_DSAS")) #ifdef LDAP_AFFECTS_MULTIPLE_DSAS return LDAP_AFFECTS_MULTIPLE_DSAS; #else goto not_there; #endif if (strEQ(name, "LDAP_ALIAS_DEREF_PROBLEM")) #ifdef LDAP_ALIAS_DEREF_PROBLEM return LDAP_ALIAS_DEREF_PROBLEM; #else goto not_there; #endif if (strEQ(name, "LDAP_ALIAS_PROBLEM")) #ifdef LDAP_ALIAS_PROBLEM return LDAP_ALIAS_PROBLEM; #else goto not_there; #endif if (strEQ(name, "LDAP_ALREADY_EXISTS")) #ifdef LDAP_ALREADY_EXISTS return LDAP_ALREADY_EXISTS; #else goto not_there; #endif if (strEQ(name, "LDAP_AUTH_METHOD_NOT_SUPPORTED")) #ifdef LDAP_AUTH_METHOD_NOT_SUPPORTED return LDAP_AUTH_METHOD_NOT_SUPPORTED; #else goto not_there; #endif if (strEQ(name, "LDAP_AUTH_NONE")) #ifdef LDAP_AUTH_NONE return LDAP_AUTH_NONE; #else goto not_there; #endif if (strEQ(name, "LDAP_AUTH_SASL")) #ifdef LDAP_AUTH_SASL return LDAP_AUTH_SASL; #else goto not_there; #endif if (strEQ(name, "LDAP_AUTH_SIMPLE")) #ifdef LDAP_AUTH_SIMPLE return LDAP_AUTH_SIMPLE; #else goto not_there; #endif if (strEQ(name, "LDAP_AUTH_UNKNOWN")) #ifdef LDAP_AUTH_UNKNOWN return LDAP_AUTH_UNKNOWN; #else goto not_there; #endif break; case 'B': if (strEQ(name, "LDAP_BUSY")) #ifdef LDAP_BUSY return LDAP_BUSY; #else goto not_there; #endif break; case 'C': if (strEQ(name, "LDAP_CACHE_CHECK")) #ifdef LDAP_CACHE_CHECK return LDAP_CACHE_CHECK; #else goto not_there; #endif if (strEQ(name, "LDAP_CACHE_LOCALDB")) #ifdef LDAP_CACHE_LOCALDB return LDAP_CACHE_LOCALDB; #else goto not_there; #endif if (strEQ(name, "LDAP_CACHE_POPULATE")) #ifdef LDAP_CACHE_POPULATE return LDAP_CACHE_POPULATE; #else goto not_there; #endif if (strEQ(name, "LDAP_CHANGETYPE_ADD")) #ifdef LDAP_CHANGETYPE_ADD return LDAP_CHANGETYPE_ADD; #else goto not_there; #endif if (strEQ(name, "LDAP_CHANGETYPE_ANY")) #ifdef LDAP_CHANGETYPE_ANY return LDAP_CHANGETYPE_ANY; #else goto not_there; #endif if (strEQ(name, "LDAP_CHANGETYPE_DELETE")) #ifdef LDAP_CHANGETYPE_DELETE return LDAP_CHANGETYPE_DELETE; #else goto not_there; #endif if (strEQ(name, "LDAP_CHANGETYPE_MODDN")) #ifdef LDAP_CHANGETYPE_MODDN return LDAP_CHANGETYPE_MODDN; #else goto not_there; #endif if (strEQ(name, "LDAP_CHANGETYPE_MODIFY")) #ifdef LDAP_CHANGETYPE_MODIFY return LDAP_CHANGETYPE_MODIFY; #else goto not_there; #endif if (strEQ(name, "LDAP_CLIENT_LOOP")) #ifdef LDAP_CLIENT_LOOP return LDAP_CLIENT_LOOP; #else goto not_there; #endif if (strEQ(name, "LDAP_COMPARE_FALSE")) #ifdef LDAP_COMPARE_FALSE return LDAP_COMPARE_FALSE; #else goto not_there; #endif if (strEQ(name, "LDAP_COMPARE_TRUE")) #ifdef LDAP_COMPARE_TRUE return LDAP_COMPARE_TRUE; #else goto not_there; #endif if (strEQ(name, "LDAP_CONFIDENTIALITY_REQUIRED")) #ifdef LDAP_CONFIDENTIALITY_REQUIRED return LDAP_CONFIDENTIALITY_REQUIRED; #else goto not_there; #endif if (strEQ(name, "LDAP_CONNECT_ERROR")) #ifdef LDAP_CONNECT_ERROR return LDAP_CONNECT_ERROR; #else goto not_there; #endif if (strEQ(name, "LDAP_CONSTRAINT_VIOLATION")) #ifdef LDAP_CONSTRAINT_VIOLATION return LDAP_CONSTRAINT_VIOLATION; #else goto not_there; #endif if (strEQ(name, "LDAP_DECODING_ERROR")) #ifdef LDAP_DECODING_ERROR return LDAP_DECODING_ERROR; #else goto not_there; #endif break; case 'D': if (strEQ(name, "LDAP_DEREF_ALWAYS")) #ifdef LDAP_DEREF_ALWAYS return LDAP_DEREF_ALWAYS; #else goto not_there; #endif if (strEQ(name, "LDAP_DEREF_FINDING")) #ifdef LDAP_DEREF_FINDING return LDAP_DEREF_FINDING; #else goto not_there; #endif if (strEQ(name, "LDAP_DEREF_NEVER")) #ifdef LDAP_DEREF_NEVER return LDAP_DEREF_NEVER; #else goto not_there; #endif if (strEQ(name, "LDAP_DEREF_SEARCHING")) #ifdef LDAP_DEREF_SEARCHING return LDAP_DEREF_SEARCHING; #else goto not_there; #endif break; case 'E': if (strEQ(name, "LDAP_ENCODING_ERROR")) #ifdef LDAP_ENCODING_ERROR return LDAP_ENCODING_ERROR; #else goto not_there; #endif break; case 'F': if (strEQ(name, "LDAP_FILTER_ERROR")) #ifdef LDAP_FILTER_ERROR return LDAP_FILTER_ERROR; #else goto not_there; #endif if (strEQ(name, "LDAP_FILT_MAXSIZ")) #ifdef LDAP_FILT_MAXSIZ return LDAP_FILT_MAXSIZ; #else goto not_there; #endif break; case 'I': if (strEQ(name, "LDAP_INAPPROPRIATE_AUTH")) #ifdef LDAP_INAPPROPRIATE_AUTH return LDAP_INAPPROPRIATE_AUTH; #else goto not_there; #endif if (strEQ(name, "LDAP_INAPPROPRIATE_MATCHING")) #ifdef LDAP_INAPPROPRIATE_MATCHING return LDAP_INAPPROPRIATE_MATCHING; #else goto not_there; #endif if (strEQ(name, "LDAP_INSUFFICIENT_ACCESS")) #ifdef LDAP_INSUFFICIENT_ACCESS return LDAP_INSUFFICIENT_ACCESS; #else goto not_there; #endif if (strEQ(name, "LDAP_INVALID_CREDENTIALS")) #ifdef LDAP_INVALID_CREDENTIALS return LDAP_INVALID_CREDENTIALS; #else goto not_there; #endif if (strEQ(name, "LDAP_INVALID_DN_SYNTAX")) #ifdef LDAP_INVALID_DN_SYNTAX return LDAP_INVALID_DN_SYNTAX; #else goto not_there; #endif if (strEQ(name, "LDAP_INVALID_SYNTAX")) #ifdef LDAP_INVALID_SYNTAX return LDAP_INVALID_SYNTAX; #else goto not_there; #endif if (strEQ(name, "LDAP_IS_LEAF")) #ifdef LDAP_IS_LEAF return LDAP_IS_LEAF; #else goto not_there; #endif break; case 'L': if (strEQ(name, "LDAP_LOCAL_ERROR")) #ifdef LDAP_LOCAL_ERROR return LDAP_LOCAL_ERROR; #else goto not_there; #endif if (strEQ(name, "LDAP_LOOP_DETECT")) #ifdef LDAP_LOOP_DETECT return LDAP_LOOP_DETECT; #else goto not_there; #endif break; case 'M': if (strEQ(name, "LDAP_MOD_ADD")) #ifdef LDAP_MOD_ADD return LDAP_MOD_ADD; #else goto not_there; #endif if (strEQ(name, "LDAP_MOD_BVALUES")) #ifdef LDAP_MOD_BVALUES return LDAP_MOD_BVALUES; #else goto not_there; #endif if (strEQ(name, "LDAP_MOD_DELETE")) #ifdef LDAP_MOD_DELETE return LDAP_MOD_DELETE; #else goto not_there; #endif if (strEQ(name, "LDAP_MOD_REPLACE")) #ifdef LDAP_MOD_REPLACE return LDAP_MOD_REPLACE; #else goto not_there; #endif if (strEQ(name, "LDAP_MORE_RESULTS_TO_RETURN")) #ifdef LDAP_MORE_RESULTS_TO_RETURN return LDAP_MORE_RESULTS_TO_RETURN; #else goto not_there; #endif if (strEQ(name, "LDAP_MSG_ALL")) #ifdef LDAP_MSG_ALL return LDAP_MSG_ALL; #else goto not_there; #endif if (strEQ(name, "LDAP_MSG_ONE")) #ifdef LDAP_MSG_ONE return LDAP_MSG_ONE; #else goto not_there; #endif if (strEQ(name, "LDAP_MSG_RECEIVED")) #ifdef LDAP_MSG_RECEIVED return LDAP_MSG_RECEIVED; #else goto not_there; #endif break; case 'N': if (strEQ(name, "LDAP_NAMING_VIOLATION")) #ifdef LDAP_NAMING_VIOLATION return LDAP_NAMING_VIOLATION; #else goto not_there; #endif if (strEQ(name, "LDAP_NOT_ALLOWED_ON_NONLEAF")) #ifdef LDAP_NOT_ALLOWED_ON_NONLEAF return LDAP_NOT_ALLOWED_ON_NONLEAF; #else goto not_there; #endif if (strEQ(name, "LDAP_NOT_ALLOWED_ON_RDN")) #ifdef LDAP_NOT_ALLOWED_ON_RDN return LDAP_NOT_ALLOWED_ON_RDN; #else goto not_there; #endif if (strEQ(name, "LDAP_NOT_SUPPORTED")) #ifdef LDAP_NOT_SUPPORTED return LDAP_NOT_SUPPORTED; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_LIMIT")) #ifdef LDAP_NO_LIMIT return LDAP_NO_LIMIT; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_MEMORY")) #ifdef LDAP_NO_MEMORY return LDAP_NO_MEMORY; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_OBJECT_CLASS_MODS")) #ifdef LDAP_NO_OBJECT_CLASS_MODS return LDAP_NO_OBJECT_CLASS_MODS; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_RESULTS_RETURNED")) #ifdef LDAP_NO_RESULTS_RETURNED return LDAP_NO_RESULTS_RETURNED; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_SUCH_ATTRIBUTE")) #ifdef LDAP_NO_SUCH_ATTRIBUTE return LDAP_NO_SUCH_ATTRIBUTE; #else goto not_there; #endif if (strEQ(name, "LDAP_NO_SUCH_OBJECT")) #ifdef LDAP_NO_SUCH_OBJECT return LDAP_NO_SUCH_OBJECT; #else goto not_there; #endif break; case 'O': if (strEQ(name, "LDAP_OBJECT_CLASS_VIOLATION")) #ifdef LDAP_OBJECT_CLASS_VIOLATION return LDAP_OBJECT_CLASS_VIOLATION; #else goto not_there; #endif if (strEQ(name, "LDAP_OPERATIONS_ERROR")) #ifdef LDAP_OPERATIONS_ERROR return LDAP_OPERATIONS_ERROR; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_CACHE_ENABLE")) #ifdef LDAP_OPT_CACHE_ENABLE return LDAP_OPT_CACHE_ENABLE; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_CACHE_FN_PTRS")) #ifdef LDAP_OPT_CACHE_FN_PTRS return LDAP_OPT_CACHE_FN_PTRS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_CACHE_STRATEGY")) #ifdef LDAP_OPT_CACHE_STRATEGY return LDAP_OPT_CACHE_STRATEGY; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_CLIENT_CONTROLS")) #ifdef LDAP_OPT_CLIENT_CONTROLS return LDAP_OPT_CLIENT_CONTROLS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_DEBUG_LEVEL")) #ifdef LDAP_OPT_DEBUG_LEVEL return LDAP_OPT_DEBUG_LEVEL; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_DEREF")) #ifdef LDAP_OPT_DEREF return LDAP_OPT_DEREF; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_DESC")) #ifdef LDAP_OPT_DESC return LDAP_OPT_DESC; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_DNS")) #ifdef LDAP_OPT_DNS return LDAP_OPT_DNS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_DNS_FN_PTRS")) #ifdef LDAP_OPT_DNS_FN_PTRS return LDAP_OPT_DNS_FN_PTRS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_ERROR_NUMBER")) #ifdef LDAP_OPT_ERROR_NUMBER return LDAP_OPT_ERROR_NUMBER; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_ERROR_STRING")) #ifdef LDAP_OPT_ERROR_STRING return LDAP_OPT_ERROR_STRING; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_HOST_NAME")) #ifdef LDAP_OPT_HOST_NAME return LDAP_OPT_HOST_NAME; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_IO_FN_PTRS")) #ifdef LDAP_OPT_IO_FN_PTRS return LDAP_OPT_IO_FN_PTRS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_MEMALLOC_FN_PTRS")) #ifdef LDAP_OPT_MEMALLOC_FN_PTRS return LDAP_OPT_MEMALLOC_FN_PTRS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_PREFERRED_LANGUAGE")) #ifdef LDAP_OPT_PREFERRED_LANGUAGE return LDAP_OPT_PREFERRED_LANGUAGE; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_PROTOCOL_VERSION")) #ifdef LDAP_OPT_PROTOCOL_VERSION return LDAP_OPT_PROTOCOL_VERSION; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_REBIND_ARG")) #ifdef LDAP_OPT_REBIND_ARG return LDAP_OPT_REBIND_ARG; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_REBIND_FN")) #ifdef LDAP_OPT_REBIND_FN return LDAP_OPT_REBIND_FN; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_RECONNECT")) #ifdef LDAP_OPT_RECONNECT return LDAP_OPT_RECONNECT; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_REFERRALS")) #ifdef LDAP_OPT_REFERRALS return LDAP_OPT_REFERRALS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_REFERRAL_HOP_LIMIT")) #ifdef LDAP_OPT_REFERRAL_HOP_LIMIT return LDAP_OPT_REFERRAL_HOP_LIMIT; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_RESTART")) #ifdef LDAP_OPT_RESTART return LDAP_OPT_RESTART; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_RETURN_REFERRALS")) #ifdef LDAP_OPT_RETURN_REFERRALS return LDAP_OPT_RETURN_REFERRALS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_SERVER_CONTROLS")) #ifdef LDAP_OPT_SERVER_CONTROLS return LDAP_OPT_SERVER_CONTROLS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_SIZELIMIT")) #ifdef LDAP_OPT_SIZELIMIT return LDAP_OPT_SIZELIMIT; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_SSL")) #ifdef LDAP_OPT_SSL return LDAP_OPT_SSL; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_THREAD_FN_PTRS")) #ifdef LDAP_OPT_THREAD_FN_PTRS return LDAP_OPT_THREAD_FN_PTRS; #else goto not_there; #endif if (strEQ(name, "LDAP_OPT_TIMELIMIT")) #ifdef LDAP_OPT_TIMELIMIT return LDAP_OPT_TIMELIMIT; #else goto not_there; #endif if (strEQ(name, "LDAP_OTHER")) #ifdef LDAP_OTHER return LDAP_OTHER; #else goto not_there; #endif break; case 'P': if (strEQ(name, "LDAP_PARAM_ERROR")) #ifdef LDAP_PARAM_ERROR return LDAP_PARAM_ERROR; #else goto not_there; #endif if (strEQ(name, "LDAP_PARTIAL_RESULTS")) #ifdef LDAP_PARTIAL_RESULTS return LDAP_PARTIAL_RESULTS; #else goto not_there; #endif if (strEQ(name, "LDAP_PORT")) #ifdef LDAP_PORT return LDAP_PORT; #else goto not_there; #endif if (strEQ(name, "LDAP_PORT_MAX")) #ifdef LDAP_PORT_MAX return LDAP_PORT_MAX; #else goto not_there; #endif if (strEQ(name, "LDAP_PROTOCOL_ERROR")) #ifdef LDAP_PROTOCOL_ERROR return LDAP_PROTOCOL_ERROR; #else goto not_there; #endif break; case 'R': if (strEQ(name, "LDAP_REFERRAL")) #ifdef LDAP_REFERRAL return LDAP_REFERRAL; #else goto not_there; #endif if (strEQ(name, "LDAP_REFERRAL_LIMIT_EXCEEDED")) #ifdef LDAP_REFERRAL_LIMIT_EXCEEDED return LDAP_REFERRAL_LIMIT_EXCEEDED; #else goto not_there; #endif if (strEQ(name, "LDAP_RESULTS_TOO_LARGE")) #ifdef LDAP_RESULTS_TOO_LARGE return LDAP_RESULTS_TOO_LARGE; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_ADD")) #ifdef LDAP_RES_ADD return LDAP_RES_ADD; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_ANY")) #ifdef LDAP_RES_ANY return LDAP_RES_ANY; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_BIND")) #ifdef LDAP_RES_BIND return LDAP_RES_BIND; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_COMPARE")) #ifdef LDAP_RES_COMPARE return LDAP_RES_COMPARE; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_DELETE")) #ifdef LDAP_RES_DELETE return LDAP_RES_DELETE; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_EXTENDED")) #ifdef LDAP_RES_EXTENDED return LDAP_RES_EXTENDED; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_MODIFY")) #ifdef LDAP_RES_MODIFY return LDAP_RES_MODIFY; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_MODRDN")) #ifdef LDAP_RES_MODRDN return LDAP_RES_MODRDN; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_RENAME")) #ifdef LDAP_RES_RENAME return LDAP_RES_RENAME; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_SEARCH_ENTRY")) #ifdef LDAP_RES_SEARCH_ENTRY return LDAP_RES_SEARCH_ENTRY; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_SEARCH_REFERENCE")) #ifdef LDAP_RES_SEARCH_REFERENCE return LDAP_RES_SEARCH_REFERENCE; #else goto not_there; #endif if (strEQ(name, "LDAP_RES_SEARCH_RESULT")) #ifdef LDAP_RES_SEARCH_RESULT return LDAP_RES_SEARCH_RESULT; #else goto not_there; #endif break; case 'S': if (strEQ(name, "LDAP_SASL_BIND_IN_PROGRESS")) #ifdef LDAP_SASL_BIND_IN_PROGRESS return LDAP_SASL_BIND_IN_PROGRESS; #else goto not_there; #endif if (strEQ(name, "LDAP_SASL_SIMPLE")) #ifdef LDAP_SASL_SIMPLE #ifdef USE_OPENLDAP return 0; #else return LDAP_SASL_SIMPLE; #endif #else goto not_there; #endif if (strEQ(name, "LDAP_SCOPE_BASE")) #ifdef LDAP_SCOPE_BASE return LDAP_SCOPE_BASE; #else goto not_there; #endif if (strEQ(name, "LDAP_SCOPE_ONELEVEL")) #ifdef LDAP_SCOPE_ONELEVEL return LDAP_SCOPE_ONELEVEL; #else goto not_there; #endif if (strEQ(name, "LDAP_SCOPE_SUBTREE")) #ifdef LDAP_SCOPE_SUBTREE return LDAP_SCOPE_SUBTREE; #else goto not_there; #endif if (strEQ(name, "LDAP_SECURITY_NONE")) #ifdef LDAP_SECURITY_NONE return LDAP_SECURITY_NONE; #else goto not_there; #endif if (strEQ(name, "LDAP_SERVER_DOWN")) #ifdef LDAP_SERVER_DOWN return LDAP_SERVER_DOWN; #else goto not_there; #endif if (strEQ(name, "LDAP_SIZELIMIT_EXCEEDED")) #ifdef LDAP_SIZELIMIT_EXCEEDED return LDAP_SIZELIMIT_EXCEEDED; #else goto not_there; #endif if (strEQ(name, "LDAP_SORT_CONTROL_MISSING")) #ifdef LDAP_SORT_CONTROL_MISSING return LDAP_SORT_CONTROL_MISSING; #else goto not_there; #endif if (strEQ(name, "LDAP_STRONG_AUTH_NOT_SUPPORTED")) #ifdef LDAP_STRONG_AUTH_NOT_SUPPORTED return LDAP_STRONG_AUTH_NOT_SUPPORTED; #else goto not_there; #endif if (strEQ(name, "LDAP_STRONG_AUTH_REQUIRED")) #ifdef LDAP_STRONG_AUTH_REQUIRED return LDAP_STRONG_AUTH_REQUIRED; #else goto not_there; #endif if (strEQ(name, "LDAP_SUCCESS")) #ifdef LDAP_SUCCESS return LDAP_SUCCESS; #else goto not_there; #endif break; case 'T': if (strEQ(name, "LDAP_TIMELIMIT_EXCEEDED")) #ifdef LDAP_TIMELIMIT_EXCEEDED return LDAP_TIMELIMIT_EXCEEDED; #else goto not_there; #endif if (strEQ(name, "LDAP_TIMEOUT")) #ifdef LDAP_TIMEOUT return LDAP_TIMEOUT; #else goto not_there; #endif if (strEQ(name, "LDAP_TYPE_OR_VALUE_EXISTS")) #ifdef LDAP_TYPE_OR_VALUE_EXISTS return LDAP_TYPE_OR_VALUE_EXISTS; #else goto not_there; #endif break; case 'U': if (strEQ(name, "LDAP_UNAVAILABLE")) #ifdef LDAP_UNAVAILABLE return LDAP_UNAVAILABLE; #else goto not_there; #endif if (strEQ(name, "LDAP_UNAVAILABLE_CRITICAL_EXTENSION")) #ifdef LDAP_UNAVAILABLE_CRITICAL_EXTENSION return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; #else goto not_there; #endif if (strEQ(name, "LDAP_UNDEFINED_TYPE")) #ifdef LDAP_UNDEFINED_TYPE return LDAP_UNDEFINED_TYPE; #else goto not_there; #endif if (strEQ(name, "LDAP_UNWILLING_TO_PERFORM")) #ifdef LDAP_UNWILLING_TO_PERFORM return LDAP_UNWILLING_TO_PERFORM; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_ERR_BADSCOPE")) #ifdef LDAP_URL_ERR_BADSCOPE return LDAP_URL_ERR_BADSCOPE; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_ERR_MEM")) #ifdef LDAP_URL_ERR_MEM return LDAP_URL_ERR_MEM; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_ERR_NODN")) #ifdef LDAP_URL_ERR_NODN return LDAP_URL_ERR_NODN; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_ERR_NOTLDAP")) #ifdef LDAP_URL_ERR_NOTLDAP return LDAP_URL_ERR_NOTLDAP; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_ERR_PARAM")) #ifdef LDAP_URL_ERR_PARAM return LDAP_URL_ERR_PARAM; #else goto not_there; #endif if (strEQ(name, "LDAP_URL_OPT_SECURE")) #ifdef LDAP_URL_OPT_SECURE return LDAP_URL_OPT_SECURE; #else goto not_there; #endif if (strEQ(name, "LDAP_USER_CANCELLED")) #ifdef LDAP_USER_CANCELLED return LDAP_USER_CANCELLED; #else goto not_there; #endif break; case 'V': if (strEQ(name, "LDAP_VERSION")) #ifdef LDAP_VERSION return LDAP_VERSION; #else goto not_there; #endif if (strEQ(name, "LDAP_VERSION1")) #ifdef LDAP_VERSION1 return LDAP_VERSION1; #else goto not_there; #endif if (strEQ(name, "LDAP_VERSION2")) #ifdef LDAP_VERSION2 return LDAP_VERSION2; #else goto not_there; #endif if (strEQ(name, "LDAP_VERSION3")) #ifdef LDAP_VERSION3 return LDAP_VERSION3; #else goto not_there; #endif if (strEQ(name, "LDAP_VERSION_MAX")) #ifdef LDAP_VERSION_MAX return LDAP_VERSION_MAX; #else goto not_there; #endif break; } } else { /* One-offs */ if (strEQ(name, "LDAPS_PORT")) #ifdef LDAPS_PORT return LDAPS_PORT; #else goto not_there; #endif if (strEQ(name, "PRLDAP_OPT_IO_MAX_TIMEOUT")) #ifdef PRLDAP_OPT_IO_MAX_TIMEOUT return PRLDAP_OPT_IO_MAX_TIMEOUT; #else goto not_there; #endif if (strEQ(name, "LDAPSSL_AUTH_WEAK")) #ifdef LDAPSSL_AUTH_WEAK return LDAPSSL_AUTH_WEAK; #else goto not_there; #endif if (strEQ(name, "LDAPSSL_AUTH_CERT")) #ifdef LDAPSSL_AUTH_CERT return LDAPSSL_AUTH_CERT; #else goto not_there; #endif if (strEQ(name, "LDAPSSL_AUTH_CNCHECK")) #ifdef LDAPSSL_AUTH_CNCHECK return LDAPSSL_AUTH_CNCHECK; #else goto not_there; #endif } errno = EINVAL; return 0; not_there: errno = ENOENT; return 0; } perl-mozldap-1.5.3/Makefile.PL0000444000076400007640000003171411426075705014557 0ustar richrich############################################################################# # $Id: Makefile.PL,v 1.16.2.16 2010/08/03 20:27:49 nkinder%redhat.com Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # The Makefile "source". require 5.005; use ExtUtils::MakeMaker; use ExtUtils::Liblist; use Config; use Carp; $osname = $Config{'osname'}; if ($osname =~ /mswin/i) { $dir_sep = "\\"; } else { $dir_sep = "/"; } $ldapsdk_loc = $ENV{"LDAPSDKDIR"}; # Full Path to C SDK Top-Level $include_ldap = $ENV{"LDAPSDKINCDIR"}; # Full Path to C SDK Include file directory $lib_ldap = $ENV{"LDAPSDKLIBDIR"}; # Full Path to C SDK Library directory $ldapsdk_ssl = $ENV{"LDAPSDKSSL"}; # N to exclude SSL $ldapsdk_pr = $ENV{"LDAPPR"}; # Y to include prldap_ functions $nspr_loc = $ENV{"NSPRDIR"}; # Full Path to NSPR Top-Level $include_nspr = $ENV{"NSPRINCDIR"}; # Full Path to NSPR include dir $lib_nspr = $ENV{"NSPRLIBDIR"}; # Full Path to NSPR lib dir $nss_loc = $ENV{"NSSDIR"}; # Full Path to NSS Top-Level $lib_nss = $ENV{"NSSLIBDIR"}; # Full Path to NSS lib dir $use_openldap = $ENV{"USE_OPENLDAP"}; # Y to use OpenLDAP instead of MozLDAP $libexts = "so|sl|a|lib|dll|dylib"; $default_root = "${dir_sep}usr"; # every linux distribution has the OpenLDAP SDK in /usr/lib and /usr/include, so # we need to use a different default to avoid problems if (!$use_openldap) { if ($osname eq "linux") { $default_root = "/opt/mozldap"; } # examine our build environment - see if we are being built as part of the overall # mozilla build process - if so, we can default a lot of things based on that # for example, if perldap was checked out in mozilla/directory/perldap, and # nspr in mozilla/nsprpub, and nss in mozilla/security, and the ldap c sdk in # mozilla/directory/c-sdk, and everything was built according to the usual # build instructions, then we can just use ../../dist/public/ldap as our # include file location and ../../dist/lib as our lib location if ( !$include_ldap && -d '../../dist/public/ldap' ) { $include_ldap = "..${dir_sep}..${dir_sep}dist${dir_sep}public${dir_sep}ldap"; } if ( !$lib_ldap && -d '../../dist/lib' ) { $lib_ldap = "..${dir_sep}..${dir_sep}dist${dir_sep}lib"; } # find the path to NSPR if (!$nspr_loc && !$include_nspr && !$lib_nspr && -d '../../dist') { require File::Find; $nspr_loc = findNSPR('../../dist'); $include_nspr = $nspr_loc . "/include"; $lib_nspr = $nspr_loc . "/lib"; } } else { if ($osname eq "linux") { $default_root = "/usr"; } } print "\nPerLDAP - Perl 5 Module for LDAP\n"; print "================================\n"; $silent = 1; if ($use_openldap) { print "Directory containing 'include' and 'lib' directory of the OpenLDAP\n"; print "LDAP client libraries (default: $default_root, Enter \"n\" to specify\n" . "explicit include and lib directories): "; } else { print "Directory containing 'include' and 'lib' directory of the Mozilla\n"; print "LDAP Software Developer Kit (default: $default_root, Enter \"n\" to\n" . "specify explicit include and lib directories): "; } if (!$ldapsdk_loc) { $silent = 0; chomp ($ldapsdk_loc = ); $ldapsdk_loc = $default_root unless $ldapsdk_loc =~ /\S/; if (! -d $ldapsdk_loc) { $ldapsdk_loc = undef; } } else { print "$ldapsdk_loc\n"; } if (!$include_ldap && $ldapsdk_loc) { $include_ldap = $ldapsdk_loc . $dir_sep . "include"; } if (!$ldapsdk_loc) { if ($use_openldap) { print "Directory containing 'include' files of the OpenLDAP\n"; print "LDAP client libraries (default: $include_ldap): "; } else { print "Directory containing 'include' files of the Mozilla\n"; print "LDAP Software Developer Kit (default: $include_ldap): "; } if (! -f "$include_ldap${dir_sep}ldap.h") { $silent = 0; chomp ($input = ); $include_ldap = $input if $input =~ /\S/; croak("Missing required include file $include_ldap${dir_sep}ldap.h") unless -f "$include_ldap${dir_sep}ldap.h"; } else { print "$include_ldap\n"; } } if (!$lib_ldap && $ldapsdk_loc) { $lib_ldap = $ldapsdk_loc . $dir_sep . "lib"; } if (!$ldapsdk_loc) { if ($use_openldap) { print "Directory containing 'lib' files of the OpenLDAP\n"; print "LDAP client libraries (default: $lib_ldap): "; } else { print "Directory containing 'lib' files of the Mozilla\n"; print "LDAP Software Developer Kit (default: $lib_ldap): "; } if (! -d "$lib_ldap") { $silent = 0; chomp ($input = ); $lib_ldap = $input if $input =~ /\S/; croak("Missing required lib directory $lib_ldap") unless -d "$lib_ldap"; } else { print "$lib_ldap\n"; } } print "Include SSL Support (default: yes)? "; if (!$ldapsdk_ssl) { $silent = 0; chomp ($ldapsdk_ssl = ); } else { print "$ldapsdk_ssl\n"; } $ssl_def = "-DUSE_SSL" unless ($ldapsdk_ssl =~ /^n/i); if (!$use_openldap) { # see if ldap and nspr files are in the same place if ( -f "$include_ldap${dir_sep}nspr.h" ) { $nspr_loc = $ldapsdk_loc; } print "Directory containing NSPR API 'include' and 'lib'\n"; print "directories for NSPR support (type 'n' or 'none' to omit) (default: $nspr_loc): "; if (!$ENV{NSPRDIR} && !$ENV{NSPRINCDIR} && !$ENV{NSPRLIBDIR}) { $silent = 0; chomp ($input = ); if ($input =~ /^n/i) { $nspr_loc = undef; } elsif ($input =~ /\S/) { $nspr_loc = $input; } } else { print "$nspr_loc\n"; } if ($nspr_loc) { if (!$lib_nspr) { $lib_nspr = $nspr_loc . ${dir_sep} . 'lib'; } if (!$include_nspr) { $include_nspr = $nspr_loc . ${dir_sep} . 'include'; } croak("Missing required include file $include_nspr${dir_sep}nspr.h") unless -f "$include_nspr${dir_sep}nspr.h"; $pr_def = "-DPRLDAP" } print "Directory containing NSS API 'lib'\n"; print "directories for NSS support (type 'n' or 'none' to omit) (default: $nss_loc): "; if (!$ENV{NSSDIR} && !$ENV{NSSLIBDIR}) { $silent = 0; chomp ($input = ); if ($input =~ /^n/i) { $nss_loc = undef; } elsif ($input =~ /\S/) { $nss_loc = $input; } } else { print "$nss_loc\n"; } if ($nss_loc) { if (!$lib_nss) { $lib_nss = $nss_loc . ${dir_sep} . 'lib'; } } } opendir(DIR,$lib_ldap); if (!$use_openldap && $ssl_def) { @libfiles = grep{/ldap\d|ssl\d|nss\d|pl[cd]\d|nspr\d|ldappr\d/} readdir(DIR); } else { @libfiles = grep{/ldap|lber/} readdir(DIR); } closedir(DIR); if (!$use_openldap) { if ($lib_nspr && -d $lib_nspr) { opendir(DIR,$lib_nspr); push @libfiles, grep{/pl[cd]\d|nspr\d|ssl\d|nss\d/} readdir(DIR); closedir(DIR); } if ($lib_nss && -d $lib_nss) { opendir(DIR,$lib_nss); push @libfiles, grep{/ssl\d|nss\d/} readdir(DIR); closedir(DIR); } } @libs = (); foreach $candidate (@libfiles) { next if $candidate !~ /($libexts)$/; $candidate =~ s/^lib//; if ($osname !~ /mswin/i) { $candidate =~ s/\.($libexts)$//; } push(@libs, $candidate) unless grep(/^$candidate$/, @libs); } if (!$use_openldap) { if ($osname =~ /mswin/i) { @ldaplib = grep{/^nsldap\d.*$/} @libs; @prldaplib = grep{/^nsldappr.*$/} @libs; @lberlib = grep{/^nslber.*$/} @libs; @ldapslib = grep{/^nsldapssl.*$/} @libs if $ssl_def; } else { @ldaplib = grep{/^ldap\d.*$/} @libs; @prldaplib = grep{/^prldap.*$/} @libs; @lberlib = grep{/^lber.*$/} @libs; @ldapslib = grep{/^ssldap.*$/} @libs if $ssl_def; } @ssllib = grep{/^ssl\d.*$/} @libs if $ssl_def; @nsslib = grep{/^nss\d.*$/} @libs if $ssl_def; @plclib = grep{/^plc\d.*$/} @libs if $ssl_def; @pldslib = grep{/^plds\d.*$/} @libs if $ssl_def; @nsprlib = grep{/^nspr\d.*$/} @libs; } else { # We only need to link with libldap and lilber when using OpenLDAP. @ldaplib = grep{/^ldap\.*$/} @libs; @lberlib = grep{/^lber\.*$/} @libs; # We don't really use PRLDAP when using OpenLDAP, but we want to provide # stubs for the PRLDAP functions. $openldap_def = "-DUSE_OPENLDAP -DPRLDAP"; } if ($#ldaplib < 0) { die "No LDAP libraries found."; } if ($use_openldap && ($#lberlib < 0)) { die "No LBER libraries found."; } if ($#ldaplib > 0) { print "Located multiple libraries:\n"; foreach $alib (@ldaplib) { print " - $alib\n"; } } # construct linker libraries string $lline = ""; # add libraries in order of dependencies $lline .= " -l$ldapslib[0]" if ($#ldapslib >= 0); # # Add "main" LDAP library to link line, and the NSPR version # as well (if available). # $lline .= " -l$prldaplib[0]" if ($#prldaplib >= 0); $lline .= " -l$ldaplib[0]"; # # Add lber library if using OpenLDAP # if ($use_openldap) { $lline .= " -l$lberlib[0]"; } # # Add SSL libraries, if needed # $lline .= " -L$lib_nss" if ($lib_nss); $lline .= " -l$ssllib[0]" if ($#ssllib >= 0); $lline .= " -l$nsslib[0]" if ($#nsslib >= 0); # Add the NSS/NSPR libraries, if needed $lline .= " -L$lib_nspr" if ($lib_nspr); $lline .= " -l$plclib[0]" if ($#plclib >= 0); $lline .= " -l$pldslib[0]" if ($#pldslib >= 0); $lline .= " -l$nsprlib[0]" if ($#nsprlib >= 0); print "Libraries to link with (default: $lline): "; if (!$silent) { chomp ($lib_line = ); $lib_line = $lline unless $lib_line =~ /\S/; } else { $lib_line = $lline; print "\n"; } $lib_line = "-L$lib_ldap $lib_line"; # Include directories etc. $my_includes = ""; $my_includes .= " -I$include_ldap" unless ($include_ldap eq "/usr/include"); $my_includes .= " -I$include_nspr" if $pr_def; # Add system dependant stuff here... @extras = (); if ($osname =~ /mswin/i) { $my_extlib = "$lib_ldap\\$ldaplib[0]"; $my_extlib .= " $lib_ldap\\$lberlib[0]" if $#lberlib >= 0; push(@extras, 'dynamic_lib' => { 'OTHERLDFLAGS' => "kernel32.lib oldnames.lib" }); } else { $my_extlib = ""; } if ($^O eq 'MSWin32' and $Config{archname} =~ /-object\b/i) { push(@extras, CAPI => 'TRUE'); } # # See if we need to add an LD_RUN_PATH. This seems to have changed # somewhere between Perl 5.8.0 and 5.8.5. So, on some systems this # will add an extra LD_RUN_PATH ... # @liblist = ExtUtils::Liblist->ext($lib_line); if ($liblist[3] ne "") { use Config; push(@extras, 'LD' => 'LD_RUN_PATH=$(LD_RUN_PATH)' . " $Config{ld}", ); } # # Ok, let's do it! # print "\n######### before WriteMakefile #############\n"; WriteMakefile( 'ABSTRACT' => 'Perl methods for LDAP C API calls', 'AUTHOR' => 'Leif Hedstrom ', 'NAME' => 'Mozilla::LDAP::API', 'DISTNAME' => 'PerLDAP', 'VERSION_FROM' => 'API.pm', 'INC' => $my_includes, 'LIBS' => [$lib_line], 'MYEXTLIB' => $my_extlib, 'DEFINE' => "$ssl_def $pr_def $openldap_def", 'XSOPT' => "-nolinenumbers", @extras ); print "\n######### after WriteMakefile #############\n"; # # Generate a "make HTML" target # sub MY::postamble { ' .SUFFIXES: .pm .html .PHONY: html .pm.html: pod2html --netscape $< > $@ html: Entry.html Conn.html Utils.html API.html LDIF.html $(FIRST_MAKEFILE) @rm -f pod2html-itemcache pod2html-dircache ' } sub find_helper { if (/nspr\.h/) { $nspr_loc = File::Basename::dirname($File::Find::dir); } } sub findNSPR { my $dir = shift; File::Find::find(\&find_helper, $dir); return $nspr_loc; } perl-mozldap-1.5.3/CREDITS0000444000076400007640000000174407743316252013627 0ustar richrichThis is a short list of people that have contributed to the success of this project. * Leif Hedstrom - Project lead. - Wrote some of the API code, and most of OO layers (Conn.pm, Entry.pm etc.) - Unix portability test. - Port to Windows/NT and ActivePerl. * Kevin McCarthy - Bug fixes, tons of contribution, particularly to the API.xs file. * Michelle Hedstrom - Testing, bug fixes, and documentation, as well as working on new modules for PerLDAP v2.0. * Clayton Donley - Wrote some of the initial API code (API.xs and API.pm). * John Kristian - Rewrote the entire LDIF module, great stuff! * Netscape Netcenter team (Kevin Burns, Max Block, Mark Takacs etc.) - Tons of ideas and requests for features. - Discovering bugs daily (great, thanks... ;-). * Bob Ferguson - Primary guinea pig for all my NT builds. * Everyone else that I've forgot to mention: - Thanks for testing and debugging this package! perl-mozldap-1.5.3/Utils.pm0000444000076400007640000002074410634204213014230 0ustar richrich############################################################################# # $Id: Utils.pm,v 1.14.2.6 2007/06/14 09:21:15 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Lots of Useful Little Utilities, for LDAP related operations. require 5.005; package Mozilla::LDAP::Utils; use Mozilla::LDAP::API 1.5 qw(:constant); use Mozilla::LDAP::Conn; use Exporter; use strict; use vars qw($VERSION @ISA %EXPORT_TAGS); @ISA = qw(Exporter); $VERSION = "1.5"; %EXPORT_TAGS = ( all => [qw(normalizeDN isUrl printEntry printentry str2Scope askPassword ldapArgs userCredentials answer)] ); # Add Everything in %EXPORT_TAGS to @EXPORT_OK Exporter::export_ok_tags('all'); ############################################################################# # Normalize the DN string (first argument), and return the new, normalized, # string (DN). This is useful to make sure that two syntactically # identical DNs compare (eq) as the same string. # sub normalizeDN { my ($dn) = @_; my (@vals); return "" unless (defined($dn) && ($dn ne "")); @vals = Mozilla::LDAP::API::ldap_explode_dn(lc $dn, 0); return join(",", @vals); } ############################################################################# # Checks if a string is a properly formed LDAP URL. # sub isURL { return ldap_is_ldap_url($_[0]); } ############################################################################# # Print an entry, in LDIF format. This is sort of obsolete, we encourage # you to use the :;LDAP::LDIF class instead. # sub printEntry { my $entry = $_[0]; my ($attr); local $_; print "dn: ", $entry->{"dn"},"\n"; foreach $attr (@{$entry->{"_oc_order_"}}) { next if ($attr =~ /^_.+_$/); next if $entry->{"_${attr}_deleted_"}; foreach (@{$entry->{$attr}}) { print "$attr: $_\n"; } } print "\n"; } *printentry = \*printEntry; ############################################################################# # Convert a "human" readable string to an LDAP scope value # sub str2Scope { my ($str) = $_[0]; return $str if ($str =~ /^[0-9]+$/); if ($str =~ /^sub/i) { return LDAP_SCOPE_SUBTREE; } elsif ($str =~ /^base/i) { return LDAP_SCOPE_BASE; } elsif ($str =~ /^one/i) { return LDAP_SCOPE_ONELEVEL; } # Default... return LDAP_SCOPE_SUBTREE; } ############################################################################# # Ask for a password, without displaying it on the TTY. # sub askPassword { my ($prompt) = shift; my ($promptstr) = shift; my ($hasReadKey) = 0; eval "use Term::ReadKey"; $hasReadKey=1 unless ($@); if ($prompt) { if ($promptstr) { print $promptstr; } else { print "LDAP password: "; } } if ($hasReadKey) { ReadMode(2); chop($_ = ReadLine(0)); ReadMode(0); } else { system('/bin/stty -echo'); chop($_ = ); system('/bin/stty echo'); } print "\n"; return $_; } ############################################################################# # Handle some standard LDAP options, and construct a nice little structure # that we can use later on. We really should have some appropriate defaults, # perhaps from an Mozilla::LDAP::Config module. # sub ldapArgs { my ($bind, $base) = @_; my (%ld); $main::opt_v = $main::opt_n if defined($main::opt_n); $main::opt_p = LDAPS_PORT if (!defined($main::opt_p) && defined($main::opt_P) && ($main::opt_P ne "")); $ld{"host"} = $main::opt_h || "ldap"; $ld{"port"} = $main::opt_p || LDAP_PORT; $ld{"base"} = $main::opt_b || $base || $ENV{'LDAP_BASEDN'}; $ld{"root"} = $ld{"base"}; $ld{"bind"} = $main::opt_D || $bind || ""; $ld{"pswd"} = $main::opt_w || ""; $ld{"cert"} = $main::opt_P || ""; $ld{"certname"} = $main::opt_N || ""; $ld{"keypwd"} = $main::opt_W || ""; $ld{"starttls"} = (defined($main::opt_Z) ? 1 : 0); $ld{"scope"} = (defined($main::opt_s) ? $main::opt_s : LDAP_SCOPE_SUBTREE); $ld{"vers"} = (defined($main::opt_V) && $main::opt_V eq "2") ? LDAP_VERSION2 : LDAP_VERSION3; if (($ld{"bind"} ne "") && ($ld{"pswd"} eq "")) { $ld{pswd} = askPassword(1); } if (($ld{"certname"} ne "") && ($ld{"keypwd"} eq "")) { $ld{keypwd} = askPassword(1, "Enter PIN for " . $ld{"certname"} . ": "); } return %ld; } ############################################################################# # Try to find a user to bind as, and possibly ask for the password. Pass # a pointer to the hash array with LDAP parameters to this function. # sub userCredentials { my ($ld) = @_; my ($conn, $entry, $pswd, $search); if ($ld->{"bind"} eq "") { my ($base) = $ld->{"base"} || $ld->{"root"}; $conn = Mozilla::LDAP::Conn->new($ld); die "Couldn't connect to LDAP server " . $ld->{"host"} unless $conn; $search = "(&(objectclass=inetOrgPerson)(uid=$ENV{USER}))"; $entry = $conn->search($base, "subtree", $search, 0, ("uid")); return 0 if (!$entry || $conn->nextEntry()); $conn->close(); $ld->{"bind"} = $entry->getDN(); } if ($ld->{"pswd"} eq "") { $ld->{"pswd"} = Mozilla::LDAP::Utils::askPassword(1); } } ############################################################################# # Ask a Y/N question, return "Y" or "N". # sub answer { die "Default string must be Y or N." unless (($_[0] eq "Y") || ($_[0] eq "N")); chop($_ = ); return $_[0] if /^$/; return "Y" if /^[yY]/; return "N" if /^[nN]/; } ############################################################################# # Mandatory TRUE return value. # 1; ############################################################################# # POD documentation... # __END__ =head1 NAME Mozilla::LDAP::Utils.pm - Collection of useful little utilities. =head1 SYNOPSIS use Mozilla::LDAP::Utils; =head1 ABSTRACT =head1 DESCRIPTION =head1 OBJECT CLASS METHODS =over 13 =item B This function will remove all extraneous white spaces in the DN, and also change all upper case characters to lower case. The only argument is the DN string to normalize, and the return value is the new, clean DN. =back =head1 EXAMPLES There are plenty of examples to look at, in the examples directory. We are adding more examples every day (almost). =head1 INSTALLATION Installing this package is part of the Makefile supplied in the package. See the installation procedures which are part of this package. =head1 AVAILABILITY This package can be retrieved from a number of places, including: http://www.mozilla.org/directory/ Your local CPAN server =head1 CREDITS Most of this code was developed by Leif Hedstrom, Netscape Communications Corporation. =head1 BUGS None. :) =head1 SEE ALSO L, L, L, and of course L. =cut perl-mozldap-1.5.3/INSTALL0000444000076400007640000000663110551225014013622 0ustar richrichPerLDAP installation instructions ================================== Building this package is fairly straight forward, but requires some knowledge about using compilers and compiler tools on your system. If you are uncomfortable using these tools, we recommend you get one of the prebuilt binary distributions instead. Prerequisites ============= In order to build the module, you'll need - Perl, version 5.005 or later, although it's only been tested and developed using 5.008. - An ANSI-C compiler, e.g. gcc-2.x, or Visual C++ 5.0. - The LDAP client libraries and include files, either from the mozilla.org source, or precompiled packages from sun.com (http://wwws.sun.com/software/download/app_dev.html#sdks) See the README file for information on retrieving binaries. You can download (or CVS checkout) the Directory SDK source, see further information available on http://www.mozilla.org/directory/ RedHat also provide C-SDK builds, available at ftp://ftp.redhat.com/pub/redhat/ldapsdk/ For NSPR and NSS (SSL) support, you might also need to download those SDKs, for instance ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v4.6.1/ ftp://ftp.mozilla.org/pub/mozilla.org/security/nss/releases/NSS_3_11_RTM/ There's also a semi-obsoloete FAQ at http://www.mozilla.org/directory/faq/perldap-faq.html Building ======== This package uses the normal Perl5 MakeMaker installation system. To generate a Makefile appropriate for your platform, run perl on the provided Makefile.PL script, e.g. % perl Makefile.PL You might have to use the command `perl5' or `perl-5.004', depending on how you installed Perl-5. The script will now ask you a few questions to find the necessary library and include files. A typical configuration session is computer (13:19) 1096/1 $ perl Makefile.PL PerLDAP - Perl 5 Module for LDAP ================================ Directory containing 'include' and 'lib' directory of the Netscape LDAP Software Developer Kit (default: /usr): /usr/local/ldapsdk5 Using LDAPv3 Developer Kit (default: yes)? Include SSL Support (default: yes)? Libraries to link with (default: -lldap50 -lssldap50 -lssl3): Writing Makefile for Mozilla::LDAP::API The important question is where your LDAP SDK is installed, in the example above the base directory is /usr/local/ldapsdk5. This directory should have two subdirectories, named "lib" and "include". If you installed the SDK in the standard /usr hierarchy, use the default value as provided by the install script. Assuming you get no errors or warning, proceed with the build and install: $ make $ make install That should be it! Automated Configuration and Installs ==================================== The Makefile.PL script also honors a set of environment variables to make it possible to do configuration and installs non-interactively. The variables are LDAPSDKDIR - Full path to the C SDK base directory LDAPSDKSSL - Set to "N" to disable SSL (SSL is default) LDAPPR - Enable prldap_ functionality (off by default) With these variables set, you will not be asked any of the questions above (but it will echo the paramaters). Just run the Makefile.PL script, and finish the build, e.g. $ perl5 Makefile.PL $ make $ make install RPM === The script Makefile.PL.rpm is used instead of Makefile.PL for building the RPM. See the spec file perl-Mozilla-LDAP.spec for more details. perl-mozldap-1.5.3/typemap0000444000076400007640000000616210634204213014172 0ustar richrich############################################################################# # $Id: typemap,v 1.5.2.6 2007/06/14 09:21:15 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # Kevin McCarthy # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Typemap to declare XSUB data types. const int T_IV char * T_PV const char * T_PV char ** T_charptrptr void * T_PTR LDAP * T_PTR LDAPMessage * T_PTR LDAPMessage ** T_PTR BerElement * T_PTR LDAPControl * T_PTR LDAPVersion * T_PTR struct berval T_berval struct berval * T_bervalptr struct berval ** T_bervalptrptr FriendlyMap * T_PTR LDAPsortkey ** T_PTR LDAPVirtualList * T_PTR LDAPURLDesc * T_PTR LDAPControl ** T_PTR LDAPFiltDesc * T_PTR LDAPFiltInfo * T_PTR LDAPMemCache * T_PTR LDAPMemCache ** T_PTR struct ldap_thread_fns * T_PTR LDAPMod ** T_PTR LDAP_CMP_CALLBACK * T_PTR LDAP_REBINDPROC_CALLBACK * T_PTR struct timeval T_timeval my_chgtype_t T_IV my_chgnum_t T_IV my_result_t T_IV my_vlvint_t T_IV ######### INPUT T_timeval $var.tv_sec = (long)atof((char *)SvPV($arg,PL_na)); $var.tv_usec = 0 T_berval $var.bv_val = (char *)SvPV($arg,PL_na); $var.bv_len = PL_na T_charptrptr $var = (char **)avref2charptrptr($arg) T_bervalptr $var = NULL T_bervalptrptr $var = (struct berval **)avref2berptrptr($arg) OUTPUT T_charptrptr $arg = charptrptr2avref($var); T_bervalptr if ($var) { sv_setpvn($arg,$var->bv_val,$var->bv_len); ber_bvfree($var); } T_bervalptrptr $arg = berptrptr2avref((struct berval **)$var); perl-mozldap-1.5.3/Entry.pm0000444000076400007640000011471310634204212014230 0ustar richrich############################################################################# # $Id: Entry.pm,v 1.13.2.9 2007/06/14 09:21:14 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # Michelle Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # This package defines an object class to manage one single LDAP # entry. This entry can either be a newly created one, or one # retrieved from an LDAP server, using the Mozilla::LDAP::Conn class. require 5.005; package Mozilla::LDAP::Entry; use Mozilla::LDAP::Utils 1.5 qw(normalizeDN); use Tie::Hash; use strict; use vars qw($VERSION @ISA); @ISA = ('Tie::StdHash'); $VERSION = "1.5"; ############################################################################# # Constructor, for convenience. # sub new { my $class = shift; my (%entry, $obj); tie %entry, $class; $obj = bless \%entry, $class; return $obj; } ############################################################################# # Creator, make a new tie hash instance, which will keep track of all # changes made to the hash array. This is needed so we only update modified # attributes. # sub TIEHASH { my $class = shift; my $self = {}; return bless $self, $class; } ############################################################################# # Destructor, free a bunch of memory. This makes a lot more sense now, # since apparently Perl does not handle self references properly within an # object(??). # sub DESTROY { my $self = shift; if (defined($self)) { # This casuses Perl to segfault ... Go figure. # undef %{$self} if (%{$self}); undef $self; } } ############################################################################# # Store method, to keep track of changes on an entire array of values (per # attribute, of course). # sub STORE { my $self = shift; my $attr = lc shift; my $val = shift; return unless (defined($val) && ($val ne "")); return unless (defined($attr) && ($attr ne "")); # We don't "track" internal values, or DNs... if (($attr =~ /^_.+_$/) || ($attr eq "dn")) { $self->{$attr} = $val; return; } if (defined($self->{$attr})) { $self->{"_${attr}_save_"} = [ @{$self->{$attr}} ] unless defined($self->{"_${attr}_save_"}); } $self->{$attr} = $val; $self->{"_${attr}_modified_"} = 1; delete $self->{"_${attr}_deleted_"} if defined($self->{"_${attr}_deleted_"}); # Potentially add the attribute to the OC order list. if (! grep(/^$attr$/i, @{$self->{"_oc_order_"}})) { push(@{$self->{"_oc_order_"}}, $attr); $self->{"_oc_numattr_"}++; } } ############################################################################# # Fetch method, this is case insensitive (since LDAP is...). # sub FETCH { my $self = shift; my $attr = lc shift; return unless defined($self->{$attr}); return if defined($self->{"_${attr}_deleted_"}); return $self->{$attr}; } ############################################################################# # Delete method, to keep track of changes. Note that we actually don't # delete the attribute, just mark it as deleted. Now, the $1M question is, # why don't we delete this? Seriously guys, this looks wrong... # sub DELETE { my $self = shift; my $attr = lc shift; return unless (defined($attr) && ($attr ne "")); return unless defined($self->{$attr}); if ($attr =~ /^_.+_$/) { delete $self->{$attr}; } else { $self->{"_${attr}_deleted_"} = 1; } } ############################################################################# # See if an attribute/key exists in the entry (could still be undefined). # The exists() (lowercase) is a kludge, kept for backward compatibility. # Please use the EXISTS method (or just exists ... instead). # sub EXISTS { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 if defined($self->{"_${attr}_deleted_"}); return exists $self->{$attr}; } sub exists { my $self = shift; my $attr = lc shift; return exists $self->{$attr}; } ############################################################################# # Reset the each()/key() session, and return the first key. This honors # the oc_order, i.e. the order the attributes were returned in. # sub FIRSTKEY { my ($self, $idx) = ($_[$[], 0); my (@attrs, $key); return unless defined($self->{"_oc_order_"}); @attrs = @{$self->{"_oc_order_"}}; while ($idx < $self->{"_oc_numattr_"}) { $key = $attrs[$idx++]; next if ($key =~ /^_.+_$/); next if defined($self->{"_${key}_deleted_"}); $self->{"_oc_keyidx_"} = $idx; return $key; } $self->{"_oc_keyidx_"} = $idx; return; } ############################################################################# # Get the next key, if appropriate. # sub NEXTKEY { my $self = shift; my $idx = $self->{"_oc_keyidx_"}; my (@attrs, $key); return unless defined($self->{"_oc_order_"}); @attrs = @{$self->{"_oc_order_"}}; while ($idx < $self->{"_oc_numattr_"}) { $key = $attrs[$idx++]; next if ($key =~ /^_.+_$/); next if defined($self->{"_${key}_deleted_"}); last; } $self->{"_oc_keyidx_"} = $idx; return unless (defined($key) && ($key ne "")); return if ($key =~ /^_.+_$/); return if defined($self->{"_${key}_deleted_"}); return $key; } ############################################################################# # Check if anything in the entry has been modified # sub isEntryModified { my $self = shift; foreach (@{$self->{'_oc_order_'}}) { return(1) if ($self->isModified($_) || $self->isDeleted($_)); } return(0); } ############################################################################# # Mark an attribute as changed. Normally you shouldn't have to use this, # unless you're doing something really weird... # sub attrModified { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); return 0 if defined($self->{"_${attr}_deleted_"}); return 0 if ($attr eq "dn"); $self->{"_${attr}_save_"} = [ @{$self->{$attr}} ] unless defined($self->{"_${attr}_save_"}); $self->{"_${attr}_modified_"} = 1; return 1; } *markModified = \*attrModified; ############################################################################# # Mark an attribute as "clean", meaning nothing has been changed in it. # You should probably not use this method, unless you really know what # you are doing... It is however used heavily by the Conn.pm package. # sub attrClean { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 if ($attr eq "dn"); delete $self->{"_${attr}_modified_"} if defined($self->{"_${attr}_modified_"}); delete $self->{"_${attr}_deleted_"} if defined($self->{"_${attr}_deleted_"}); if (defined($self->{"_${attr}_save_"})) { undef @{$self->{"_${attr}_save_"}}; delete $self->{"_${attr}_save_"}; } } ############################################################################# # Ask if a particular attribute has been modified already. Return True or # false depending on the internal status of the attribute. # sub isModified { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); return 0 unless defined($self->{"_${attr}_modified_"}); return 1; } ############################################################################# # Ask if a particular attribute has been deleted already. Return True or # false depending on the internal status of the attribute. # sub isDeleted { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{"_${attr}_deleted_"}); return 1; } ############################################################################# # Test if a attribute name is actually a real attribute, and not part of # the internal structures. # sub isAttr { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); return 0 if defined($self->{"_${attr}_deleted_"}); return ($attr !~ /^_.+_$/); } ############################################################################# # Remove an attribute from the entry, basically the same as the DELETE # method. We also make an alias for "delete" here, just in case (and to be # somewhat backward compatible). # sub remove { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); $self->{"_${attr}_deleted_"} = 1; return 1; } *delete = \*remove; ############################################################################# # Move (rename) an attribute, return TRUE or FALSE depending on the outcome. # The first argument is the name of the old attribute (e.g. CN), and the last # argument is the new name (e.g. SN). Note that the "new" attribute can not # already exist, and the old attribute must exist. # # The "force" argument can be used to override the check if the new # attribute already exists. This is potentially dangerous. # sub move { my $self = shift; my ($old, $new, $force); if (ref $_[$[] eq "HASH") { my $hash = shift; $old = lc $hash->{"old"}; $new = lc $hash->{"new"}; $force = $hash->{"force"} || 0; } else { $old = lc shift; $new = lc shift; $force = shift; } return 0 if ($self->isAttr($new) && (!defined($force) || !$force)); return 0 unless $self->isAttr($old); $self->setValues($new, @{$self->{$old}}) || return 0; $self->remove($old); return 1; } *rename = \*move; ############################################################################# # Copy an attribute, return TRUE or FALSE depending on the outcome. This # is almost identical to the move method, except we don't delete the source. # sub copy { my $self = shift; my ($old, $new, $force); if (ref $_[$[] eq "HASH") { my $hash = shift; $old = lc $hash->{"old"}; $new = lc $hash->{"new"}; $force = $hash->{"force"} || 0; } else { $old = lc shift; $new = lc shift; $force = shift; } return 0 if ($self->isAttr($new) && (!defined($force) || !$force)); return 0 unless $self->isAttr($old); $self->setValues($new, @{$self->{$old}}) || return 0; return 1; } ############################################################################# # Undo a remove(), or set of removeValues() fairly useless, to restore an # attribute to it's original state. This is fairly useless, but hey... # sub unRemove { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 if ($attr eq "dn"); # ToDo: We need to verify that this sucker works... delete $self->{"_${attr}_deleted_"}; if (defined($self->{"_${attr}_save_"})) { undef @{$self->{$attr}}; $self->{$attr} = [ @{$self->{"_${attr}_save_"}} ]; undef @{$self->{"_${attr}_save_"}}; delete $self->{"_${attr}_save_"}; } return 1; } *unDelete = \*unRemove; ############################################################################# # Delete a value from an attribute, if it exists. NOTE: If it was the last # value, we'll actually remove the entire attribute! # sub removeValue { my $self = shift; my ($attr, $val, $norm); my $i = 0; my $attrval; local $_; if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $val = $hash->{"val"}; $norm = $hash->{"norm"} || 0; } else { $attr = lc shift; ($val, $norm) = @_; } return 0 unless (defined($val) && ($val ne "")); return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); return 0 if ($attr eq "dn"); $val = normalizeDN($val) if (defined($norm) && $norm); $self->{"_${attr}_save_"} = [ @{$self->{$attr}} ] unless defined($self->{"_${attr}_save_"}); foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); if ($_ eq $val) { splice(@{$self->{$attr}}, $i, 1); if ($self->size($attr) > 0) { $self->{"_${attr}_modified_"} = 1; } else { $self->{"_${attr}_deleted_"} = 1; } return 1; } $i++; } return 0; } *deleteValue = \*removeValue; ############################################################################# # Just like removeValue(), but force the DN normalization of the value. # sub removeDNValue { my $self = shift; my ($attr, $val); if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $val = $hash->{"val"}; } else { $attr = lc shift; $val = shift; } return $self->removeValue($attr, $val, 1); } *deleteDNValue = \*removeDNValue; ############################################################################# # Add a value to an attribute. The optional third argument indicates that # we should not enforce the uniqueness on this attibute, thus bypassing # the test and always add the value. # sub addValue { my $self = shift; my ($attr, $val, $force, $norm, $nocase); local $_; if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $val = $hash->{"val"}; $force = $hash->{"force"}; $norm = $hash->{"norm"}; $nocase = $hash->{"nocase"}; } else { $attr = lc shift; ($val, $force, $norm, $nocase) = @_; } return 0 unless (defined($val) && ($val ne "")); return 0 unless (defined($attr) && ($attr ne "")); return 0 if ($attr eq "dn"); if (defined($self->{$attr}) && (!defined($force) || !$force)) { my $nval = $val; my $attrval; $nval = normalizeDN($val) if (defined($norm) && $norm); foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); $_ = lc $_ if (defined($nocase) && $nocase); return 0 if ($_ eq $nval); } } if (defined($self->{$attr})) { $self->{"_${attr}_save_"} = [ @{$self->{$attr}} ] unless defined($self->{"_${attr}_save_"}); } else { $self->{"_${attr}_save_"} = [] unless defined($self->{"_${attr}_save_"}); } $self->{"_${attr}_modified_"} = 1; if (defined($self->{"_${attr}_deleted_"})) { delete $self->{"_${attr}_deleted_"}; $self->{$attr} = [$val]; } else { push(@{$self->{$attr}}, $val); } # Potentially add the attribute to the OC order list. if (! grep(/^$attr$/i, @{$self->{"_oc_order_"}})) { push(@{$self->{"_oc_order_"}}, $attr); $self->{"_oc_numattr_"}++; } return 1; } ############################################################################# # Just like addValue(), but force the DN normalization of the value. Note # that we also have an $norm argument here, to normalize the DN value # before we add it. # sub addDNValue { my $self = shift; my ($attr, $val, $force, $norm, $nocase); if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $val = $hash->{"val"}; $force = $hash->{"force"}; $norm = $hash->{"norm"}; $nocase = $hash->{"nocase"}; } else { $attr = lc shift; ($val, $force, $norm, $nocase) = @_; } $val = normalizeDN($val) if (defined($norm) && $norm); return $self->addValue($attr, $val, $force, 1, $nocase); } ############################################################################# # Set the entire value of an attribute, removing whatever was already set. # The arguments are the name of the attribute, and then one or more values, # passed as scalar or an array (not pointer). # sub setValues { my $self = shift; my $attr = lc shift; my @vals = @_; local $_; return 0 unless ($#vals >= $[); return 0 unless (defined($attr) && ($attr ne "")); return 0 if ($attr eq "dn"); if (defined($self->{$attr})) { $self->{"_self_obj_"}->{"_${attr}_save_"} = [ @{$self->{$attr}} ] unless defined($self->{"_${attr}_save_"}); } else { $self->{"_self_obj_"}->{"_${attr}_save_"} = [ ] unless defined($self->{"_${attr}_save_"}); } $self->{$attr} = [ @vals ]; $self->{"_${attr}_modified_"} = 1; delete $self->{"_${attr}_deleted_"} if defined($self->{"_${attr}_deleted_"}); if (! grep(/^$attr$/i, @{$self->{"_oc_order_"}})) { push(@{$self->{"_oc_order_"}}, $attr); $self->{"_oc_numattr_"}++; } return 1; } *setValue = \*setValues; ############################################################################# # Get the entire array of attribute values. This returns the array, not # the pointer to the array... # in a scalar context, returns the first attribute # sub getValues { my $self = shift; my $attr = lc shift; return unless (defined($attr) && ($attr ne "")); return unless defined($self->{$attr}); return (wantarray ? @{$self->{$attr}} : $self->{$attr}->[0]); } *getValue = \*getValues; ############################################################################# # Return TRUE or FALSE, if the attribute has the specified value. The # optional third argument says we should do case insensitive search. # This is very unfortunate that $nocase and $norm are reversersed ... :-/. # sub hasValue { my $self = shift; my ($attr, $val, $nocase, $norm, $attrval); local $_; if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $val = $hash->{"val"}; $nocase = $hash->{"nocase"}; $norm = $hash->{"norm"}; } else { $attr = lc shift; ($val, $nocase, $norm) = @_; } return 0 unless (defined($val) && ($val ne "")); return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); $val = normalizeDN($val) if (defined($norm) && $norm); if ($nocase) { foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); return 1 if /^\Q$val\E$/i; } } else { foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); return 1 if /^\Q$val\E$/; } } return 0; } ############################################################################# # Just like hasValue(), but force the DN normalization of the value. # sub hasDNValue { my $self = shift; my ($attr, $val, $nocase); if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = $hash->{"attr"}; $val = $hash->{"val"}; $nocase = $hash->{"nocase"}; } else { ($attr, $val, $nocase) = @_; } # We don't need to lc the attribute, since hasValue() does that for us. return $self->hasValue($attr, $val, $nocase, 1); } ############################################################################# # Return TRUE or FALSE, if the attribute matches the specified regexp. The # optional third argument says we should do case insensitive search, and the # optional fourth argument indicates we should normalize for DN matches. # sub matchValue { my $self = shift; my ($attr, $regex, $nocase, $norm, $attrval); if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = lc $hash->{"attr"}; $regex = $hash->{"regex"}; $nocase = $hash->{"nocase"}; $norm = $hash->{"norm"}; } else { $attr = lc shift; ($regex, $nocase, $norm) = @_; } return 0 unless (defined($regex) && ($regex ne "")); return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); if ($nocase) { foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); return 1 if /$regex/i; } } else { foreach $attrval (@{$self->{$attr}}) { $_ = ((defined($norm) && $norm) ? normalizeDN($attrval) : $attrval); return 1 if /$regex/; } } return 0; } ############################################################################# # Just like matchValue(), but force the DN normalization of the values. # sub matchDNValue { my $self = shift; my ($attr, $regex, $nocase); if (ref $_[$[] eq "HASH") { my $hash = shift; $attr = $hash->{"attr"}; $regex = $hash->{"regex"}; $nocase = $hash->{"nocase"}; } else { ($attr, $regex, $nocase) = @_; } # We don't need to lc the attribute, since hasValue() does that for us. return $self->matchValue($attr, $regex, $nocase, 1); } ############################################################################# # Set the DN of this entry. # sub setDN { my $self = shift; my ($val, $norm); if (ref $_[$[] eq "HASH") { my $hash = shift; $val = $hash->{"val"}; $norm = $hash->{"norm"}; } else { ($val, $norm) = @_; } return 0 unless (defined($val) && ($val ne "")); $val = normalizeDN($val) if (defined($norm) && $norm); $self->{"dn"} = $val; return 1; } ############################################################################# # Get the DN of this entry. # sub getDN { my ($self, $norm) = @_; return normalizeDN($self->{"dn"}) if (defined($norm) && $norm); return $self->{"dn"}; } ############################################################################# # # Return the number of elements in an attribute. # sub size { my $self = shift; my $attr = lc shift; return 0 unless (defined($attr) && ($attr ne "")); return 0 unless defined($self->{$attr}); return scalar(@{$self->{$attr}}); } ############################################################################# # # Return LDIF entries. # sub getLDIFrecords # called from LDIF.pm (at least) { my $self = shift; my (@record) = (dn => $self->getDN()); my ($attr, $values); while (($attr, $values) = each %$self) { next if "dn" eq lc $attr; # this shouldn't happen; should it? push @record, ($attr => $values); # This is dangerous: @record and %$self now both contain # references to @$values. To avoid this, copy it: # push @record, ($attr => [@$values]); # But that's not necessary, because the array and its # contents are not modified as a side-effect of getting # other attributes, from this or other objects. } return \@record; } ############################################################################# # Print an entry, in LDIF format. # use vars qw($_no_LDIF_module $_tested_LDIF_module); undef $_no_LDIF_module; undef $_tested_LDIF_module; sub printLDIF { my $self = shift; if (not defined($_tested_LDIF_module)) { eval {require Mozilla::LDAP::LDIF; Mozilla::LDAP::LDIF->VERSION(0.07)}; $_no_LDIF_module = $@; $_tested_LDIF_module = 1; } if ($_no_LDIF_module) { my $record = $self->getLDIFrecords(); my ($attr, $values); while (($attr, $values) = splice @$record, 0, 2) { grep((print "$attr: $_\n"), ((ref($values) eq "ARRAY") ? @$values : $values)); } print "\n"; } else { Mozilla::LDAP::LDIF::put_LDIF(select(), 78, $self); } } ############################################################################# # Mandatory TRUE return value. # 1; ############################################################################# # POD documentation... # __END__ =head1 NAME Mozilla::LDAP::Entry.pm - Object class to hold one LDAP entry. =head1 SYNOPSIS use Mozilla::LDAP::Conn; use Mozilla::LDAP::Entry; =head1 ABSTRACT The LDAP::Conn object is used to perform LDAP searches, updates, adds and deletes. All such functions works on LDAP::Entry objects only. All modifications and additions you'll do to an LDAP entry, will be done through this object class. =head1 DESCRIPTION The LDAP::Entry object class is built on top of the Tie::Hash standard object class. This gives us several powerful features, the main one being to keep track of what is changing in the LDAP entry. This makes it very easy to write LDAP clients that needs to update/modify entries, since you'll just do the changes, and this object class will take care of the rest. We define local functions for STORE, FETCH, DELETE, EXISTS, FIRSTKEY and NEXTKEY in this object class, and inherit the rest from the super class. Overloading these specific functions is how we can keep track of what is changing in the entry, which turns out to be very convenient. We can also easily "loop" over the attribute types, ignoring internal data, or deleted attributes. Most of the methods here either return the requested LDAP value, or a status code. The status code (either 0 or 1) indicates the failure or success of a certain operation. 0 (False) meaning the operation failed, and a return code of 1 (True) means complete success. One thing to remember is that in LDAP, attribute names are case insensitive. All methods in this class are aware of this, and will convert all attribute name arguments to lower case before performing any operations. This does not mean that the values are case insensitive. On the contrary, all values are considered case sensitive by this module, even if the LDAP server itself treats it as a CIS attribute. =head1 OBJECT CLASS METHODS The LDAP::Entry class implements many methods you can use to access and modify LDAP entries. It is strongly recommended that you use this API as much as possible, and avoid using the internals of the class directly. Failing to do so may actually break the functionality. =head2 Creating a new entry To create a completely new entry, use the B method, for instance $entry = Mozilla::LDAP::Entry->new() $entry->setDN("uid=leif,ou=people,dc=netscape,dc=com"); $entry->{objectclass} = [ "top", "person", "inetOrgPerson" ]; $entry->addValue("cn", "Leif Hedstrom"); $entry->addValue("sn", "Hedstrom"); $entry->addValue("givenName", "Leif"); $entry->addValue("mail", "leif@netscape.com); $conn->add($entry); This is the minimum requirements for an LDAP entry. It must have a DN, and it must have at least one objectclass. As it turns out, by adding the I and I classes, we also must provide some more attributes, like I and I. This is because the object classes have these attributes marked as "required", and we'd get a schema violation without those values. In the example above we use both native API methods to add values, and setting an attribute entire value set directly. Note that the value set is a pointer to an array, and not the array itself. In the example above, the object classes are set using an anonymous array, which the API handles properly. It's important to be aware that the attribute value list is indeed a pointer. Finally, as you can see there's only only one way to add new LDAP entries, and it's called add(). It normally takes an LDAP::Entry object instance as argument, but it can also be called with a regular hash array if so desired. =head2 Adding and removing attributes and values This is the main functionality of this module. Use these methods to do any modifications and updates to your LDAP entries. =over 13 =item B Add a value to an attribute. If the attribute value already exists, or we couldn't add the value for any other reason, we'll return FALSE (0), otherwise we return TRUE (1). The first two arguments are the attribute name, and the value to add. The optional third argument is a flag, indicating that we want to add the attribute without checking for duplicates. This is useful if you know the values are unique already, or if you perhaps want to allow duplicates for a particular attribute. The fourth argument (again optional) is a flag indicating that we want to perform DN normalization on the attribute. The final, fifth, optional argument indicates that the attribute values are case insensitive (CIS). To add a CN to an existing entry/attribute, do: $entry->addValue("cn", "Leif Hedstrom"); =item B Just like B, except this method assume the value is a DN attribute, and will enforce DN normalization. For instance $dn = "uid=Leif, dc=Netscape, dc=COM"; $entry->addDNValue("uniqueMember", $dn); will only add the DN for "uid=leif" if it does not exist as a DN in the uniqueMember attribute. =item B This is an internal function, that can be used to force the API to consider an attribute (value) to have been modified. The only argument is the name of the attribute. In almost all situation, you never, ever, should call this. If you do, please contact the developers, and as us to fix the API. Example $entry->attrModified("cn"); =item B Copy the value of one attribute to another. Requires at least two arguments. The first argument is the name of the attribute to copy, and the second argument is the name of the new attribute to copy to. The new attribute can not currently exist in the entry, else the copy will fail. There is an optional third argument (a boolean flag), which, when set to 1, will force an override and copy to the new attribute even if it already exists. Returns TRUE if the copy was successful. $entry->copy("cn", "description"); =item B Return TRUE if the specified attribute is defined in the LDAP entry. This is useful to know if an entry has a particular attribute, regardless of the value. For instance: if ($entry->exists("jpegphoto")) { # do something special } =item B Return the DN for the entry. For instance print "The DN is: ", $entry->getDN(), "\n"; Just like B, this method also has an optional argument, which indicates we should normalize the DN before returning it to the caller. =item B Returns an entire array of values for the attribute specified. Note that this returns an array, and not a pointer to an array. In a scalar context, this returns the first value. This is different - this method used to always return an array, which meant the array size in a scalar context. If you need to get the array size, use the B method described below. @someArray = $entry->getValues("description"); $scalval = $entry->getValues("cn"); =item B Return TRUE or FALSE if the attribute has the specified value. A typical usage is to see if an entry is of a certain object class, e.g. if ($entry->hasValue("objectclass", "person", 1)) { # do something } The (optional) third argument indicates if the string comparison should be case insensitive or not, and the (optional) fourth argument indicats wheter we should normalize the string as if it was a DN. The first two arguments are the name and value of the attribute, respectively. =item B Exactly like B, except we assume the attribute values are DN attributes. =item B This method can be used to decide if an attribute name really is a valid LDAP attribute in the current entry. Use of this method is fairly limited, but could potentially be useful. Usage is like previous examples, like if ($entry->isAttr("cn")) { # do something } The code section will only be executed if these criterias are true: 1. The name of the attribute is a non-empty string. 2. The name of the attribute does not begin, and end, with an underscore character (_). 2. The attribute has one or more values in the entry. =item B This is almost identical to B, except it tests if an attribute has been deleted. You use it the same way as above, like if (! $entry->isDeleted("cn")) { # do something } =item B This is a somewhat more useful method, which will return the internal modification status of a particular attribute. The argument is the name of the attribute, and the return value is True or False. If the attribute has been modified, in any way, we return True (1), otherwise we return False (0). For example: if ($entry->isModified("cn")) { # do something } =item B This is a wrapper over isModified(), and it will check if any attribute in the entry object has been modified or deleted. =item B This is very similar to B, except it does a regular expression match instead of a full string match. It takes the same arguments, including the optional third argument to specify case insensitive matching. The usage is identical to the example for hasValue, e.g. if ($entry->matchValue("objectclass", "pers", 1)) { # do something } =item B Like B, except the attribute values are considered being DNs. =item B Identical to the copy method, except the original attribute is deleted once the move to the new attribute is complete. $entry->move("cn", "sn"); =item B Print the entry in a format called LDIF (LDAP Data Interchange Format, RFC xxxx). An example of an LDIF entry is: dn: uid=leif,ou=people,dc=netscape,dc=com objectclass: top objectclass: person objectclass: inetOrgPerson uid: leif cn: Leif Hedstrom mail: leif@netscape.com The above would be the result of $entry->printLDIF(); If you need to write to a file, open and then select() it. For more useful LDIF functionality, check out the Mozilla::LDAP::LDIF.pm module. =item B This will remove the entire attribute, including all it's values, from the entry. The only argument is the name of the attribute to remove. Let's say you want to nuke all I values (i.e. the entire attribute should be removed from the entry): $entry->remove("mailAlternateAddress"); =item B Remove a value from an attribute, if it exists. Of course, if the attribute has no such value, we won't try to remove it, and instead return a False (0) status code. The arguments are the name of the attribute, and the particular value to remove. Note that values are considered case sensitive, so make sure you preserve case properly. An example is: $entry->removeValue("objectclass", "nscpPerson"); =item B This is almost identical to B, except it will normalize the attribute values before trying to remove them. This is useful if you know that the attribute is a DN value, but perhaps the values are not cosistent in all LDAP entries. For example $dn = "uid=Leif, dc=Netscape, dc=COM"; $entry->removeDNValue("owner", $dn); will remove the owner "uid=leif,dc=netscape,dc=com", no matter how it's capitalized and formatted in the entry. =item B Set the DN to the specified value. Only do this on new entries, it will not work well if you try to do this on an existing entry. If you wish to rename an entry, use the Mozilla::Conn::modifyRDN method instead. Eventually we'll provide a complete "rename" method. To set the DN for a newly created entry, we can do $entry->setDN("uid=leif,ou=people,dc=netscape,dc=com"); There is an optional third argument, a boolean flag, indicating that we should normalize the DN before setting it. This will assure a consistent format of your DNs. =item B Set the specified attribute to the new value (or values), overwriting whatever old values it had before. This is a little dangerous, since you can lose attribute values you didn't intend to remove. Therefore, it's usually recommended to use B and B. If you know exactly what the new values should be like, you can use this method like $entry->setValues("cn", "Leif Hedstrom", "The Swede"); $entry->setValues("mail", @mailAddresses); or if it's a single value attribute, $entry->setValues("uidNumber", "12345"); =item B Return the number of values for a particular attribute. For instance $entry->{cn} = [ "Leif Hedstrom", "The Swede" ]; $numVals = $entry->size("cn"); This will set C<$numVals> to two (2). The only argument is the name of the attribute, and the return value is the size of the value array. =back =head2 Deleting entries To delete an LDAP entry from the LDAP server, you have to use the B method from the Mozilla::LDAP::Conn module. It will actually delete any entry, if you provide an legitimate DN. =head2 Renaming entries Again, there's no functionality in this object class to rename the entry (i.e. changing it's DN). For now, there is a way to modify the RDN component of a DN through the Mozilla::LDAP::Conn module, with B. Eventually we hope to have a complete B method, which should be capable of renaming any entry, in any way, including moving it to a different part of the DIT (Directory Information Tree). =head1 EXAMPLES There are plenty of examples to look at, in the examples directory. We are adding more examples every day (almost). =head1 INSTALLATION Installing this package is part of the Makefile supplied in the package. See the installation procedures which are part of this package. =head1 AVAILABILITY This package can be retrieved from a number of places, including: http://www.mozilla.org/directory/ Your local CPAN server =head1 CREDITS Most of this code was developed by Leif Hedstrom, Netscape Communications Corporation. =head1 BUGS None. :) =head1 SEE ALSO L, L, and of course L. =cut perl-mozldap-1.5.3/examples/0000775000076400007640000000000011426105703014411 5ustar richrichperl-mozldap-1.5.3/examples/ChangeLog0000444000076400007640000000344510166655034016174 0ustar richrich2005-01-04 Leif Hedstrom * All examples: Changed all calls to new to use the class method directly. 2004-10-13 Leif Hedstrom * modattr.pl: Added a -i option, for case insentive "adds" to an attribute. This means that trying to add "foo" or "Foo" will only generate one value for the server. * monitor.pl: Added -V option (for version). * psoftsync.pl: Added -V option (for version). * changes2ldif.pl: Added -V option (for version). * tabdump.pl: Added -V option (for version). * rmentry.pl: Added -V option (for version). * rename.pl: Added -V option (for version). * rand_mods.pl: Added -V option (for version). * modattr.pl: Added -V option (for version). * lfinger.pl: Added -V option (for version). * ldappasswd.pl: Added -V option (for version). * qsearch.pl: Added -V option (for version). 1999-06-30 Leif Hedstrom * rmentry.pl: Added support for "-p". 1999-01-05 Leif Hedstrom * psoftsync.pl (delAttr): Fixed annoying bug where I missed to "my" $entry. 1999-01-04 Leif Hedstrom * modattr.pl: Bug fixes for handling bad cases better (like missing attribute, adding empty values etc). 1998-12-11 Leif Hedstrom * modattr.pl: Modified slightly to enable the rebind proc. 1998-08-03 Leif Hedstrom * psoftsync.pl: New file, also merged in some modules from LdapUtils.pm, to make sure this works. NOTE: This script currently doesn't work, since all "modify" operations are horked. 1998-07-30 Leif Hedstrom * tabdump.pl: Actually works! * ldappasswd.pl: Cleaned out some code, and moved it over to the ::Utils module. 1998-07-29 Leif Hedstrom * qsearch.pl: First working version. perl-mozldap-1.5.3/examples/modattr.pl0000555000076400007640000002406510634204215016424 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: modattr.pl,v 1.9.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # This script can be used to do a number of different modification # operations on a script. Like adding/deleting values, or entire # attributes. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use strict; no strict "vars"; ############################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "modattr"; $USAGE = "$APPNAM [-dnvW] -b base -h host -D bind -w pswd -P cert -V ver attr=value filter"; ############################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('adnvWb:h:D:p:s:w:P:V:i:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; $nocase = (defined($opt_i) && $opt_i) ? 1 : 0; ############################################################################# # Let's process the changes requested, and commit them unless the "-n" # option was given. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; $conn->setDefaultRebindProc($ld{bind}, $ld{pswd}); ($change, $search) = @ARGV; if (($change eq "") || ($search eq "")) { print "usage: $APPNAM $USAGE\n"; exit; } ($attr, $value) = split(/=/, $change, 2); $entry = $conn->search($ld{root}, $ld{scope}, $search); while ($entry) { $changed = 0; if ($opt_d) { if (defined $entry->{$attr}) { if ($value) { $changed = $entry->removeValue($attr, $value); if ($changed && $opt_v) { print "Removed value from ", $entry->getDN(), "\n" if $opt_v; } } else { delete $entry->{$attr}; print "Deleted attribute $attr for ", $entry->getDN(), "\n" if $opt_v; $changed = 1; } } else { print "No attribute values for: $attr\n"; } } else { if (!defined($value) || !$value) { print "No value provided for the attribute $attr\n"; } elsif ($opt_a) { $changed = $entry->addValue($attr, $value, 0, 0, $nocase); if ($changed && $opt_v) { print "Added attribute to ", $entry->getDN(), "\n" if $opt_v; } } else { $entry->setValue($attr, $value); $changed = 1; print "Set attribute for ", $entry->getDN(), "\n" if $opt_v; } } if ($changed && ! $opt_n) { if (!$conn->update($entry)) { $conn->printError(); } } $entry = $conn->nextEntry(); } ############################################################################# # Close the connection. # $conn->close if $conn; ############################################################################# # POD documentation... # __END__ =head1 NAME modattr - Modify an attribute for one or more LDAP entries =head1 SYNOPSIS modattr [-adnvW] -b base -h host -D bind DN -w pwd -P cert attr=value filter =head1 ABSTRACT This command line utility can be used to modify one attribute for one or more LDAP entries. As simple as this sounds, this turns out to be a very common operation. For instance, let's say you want to change "mailHost" for all users on a machine named I, to be I. With this script all you have to do is modattr mailHost=judge '(mailHost=dredd)' =head1 DESCRIPTION There are four primary operations that can be made with this utility: =over 4 =item * Set an attribute to a (single) specified value. =item * Add a value to an attribute (for multi-value attributes). =item * Delete a value from an attribute. If it's the last value (or if it's a single value), this will remove the entire attribute. =item * Delete an entire attribute, even if it has multiple values. =back The first three requires an option of the form B, while the last one only takes the name of the attribute as the option. The last argument is always an LDAP search filter, specifying which entries the operation should be applied to. =head1 OPTIONS All but the first two command line options for this tool are standard LDAP options, to set parameters for the LDAP connection. The two new options are I<-a> and I<-d> to add and remove attribute values. Without either of these two options specified (they are both optional), the default action is to set the attribute to the specified value. That will effectively remove any existing values for this attribute. =over 12 =item -a Specify that the operation is an I, to add a value to the attribute. If there is no existing value for this attribute, we'll create a new attribute, otherwise we add the new value if it's not already there. =item -d Delete the attribute value, or the entire attribute if there's no value specified. As you can see this option has two forms, and it's function depends on the last arguments. Be careful here, if you forget to specify the value to delete, you will remove all of them. =item -h Name of the LDAP server to connect to. =item -p TCP port for the LDAP connection. =item -b Base DN for the search =item -D User (DN) to bind as. We support a few convenience shortcuts here, like I, I and I. =item -w This specifies the password to use when connecting to the LDAP server. This is strongly discouraged, and without this option the script will ask for the password interactively. =item -s Search scope, default is I, the other possible values are I and I. You can also specify the numeric scopes, I<0>, I<1> or I<2>. =item -P Use SSL for the LDAP connection, using the specified cert.db file for certificate information. =item -n Don't do anything, only show the changes that would have been made. This is very convenient, and can save you from embarrassing mistakes. =item -v Verbose output. =back The last two arguments are special for this script. The first argument specifies the attribute (and possibly the value) to operate on, and the last argument is a properly formed LDAP search filter. =head1 EXAMPLES We'll give one example for each of the four operations this script can currently handle. Since the script itself is quite flexible, you'll probably find you can use this script for a lot of other applications, or call it from other scripts. Note that we don't specify any LDAP specific options here, we assume you have configured your defaults properly. To set the I attribute for user "leif", you would do modattr 'description=Company Swede' '(uid=leif)' The examples shows how to use this command without either of the I<-a> or the I<-d> argument. To add an e-mail alias (alternate address) to the same user, you would do modattr -a 'mailAlternateAddress=theSwede@netscape.com' '(uid=leif)' To remove an object class from all entries which uses it, you could do modattr -d 'objectclass=dummyClass' '(objectclass=dummyClass)' This example is not great, since unless you've assured that no entries uses any of the attributes in this class, you'll get schema violations. But don't despair, you can use this tool to clean up all entries first! To completely remove all usage of an attribute named I, you'd simply do modattr -d dummyAttr '(dummyAttr=*)' This shows the final format of this command, notice how we don't specify a value, to assure that the entire attribute is removed. This is potentially dangerous, so again be careful. =head1 INSTALLATION In order to use this script, you'll need Perl version 5.004 or later, the LDAP SDK, and also the LDAP Perl module (aka PerLDAP). Once you've installed these packages, just copy this file to where you keep your admin binaries, e.g. /usr/local/bin. In order to get good performance, you should make sure you have indexes on the attributes you typically use with this script. Our experience has been that in most cases the standard indexes in the Directory Server are sufficient, e.g. I, I and I. =head1 AVAILABILITY This package can be retrieved from a number of places, including: http://www.mozilla.org/directory/ Your local CPAN server =head1 CREDITS This little tool was developed internally at Netscape, by Leif Hedstrom. =head1 BUGS None, of course... =head1 SEE ALSO L and L =cut perl-mozldap-1.5.3/examples/changes2ldif.pl0000555000076400007640000001023610634204215017276 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: changes2ldif.pl,v 1.3.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Search the changelog, and produce an LDIF file suitable for ldapmodify # for instance. This should be merged into LDIF.pm eventually. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use strict; no strict "vars"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "changes2ldif"; $USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert -V ver [min [max]]"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvb:h:D:p:s:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); $ld{root} = "cn=changelog" if (!defined($ld{root}) || $ld{root} eq ""); ################################################################################# # Instantiate an LDAP object, which also binds to the LDAP server. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; ################################################################################# # Create the search filter. # $min = $ARGV[$[]; $max = $ARGV[$[ + 1]; if ($min ne "") { if ($max ne "") { $search = "(&(changenumber>=$min)(changenumber<=$max))"; } else { $search = "(changenumber>=$min)"; } } else { $search = "(changenumber=*)"; } ################################################################################# # Do the searches, and print the results. # $entry = $conn->search($ld{root}, "ONE", "$search"); while ($entry) { print "dn: ", $entry->{targetdn}[0], "\n"; $type = $entry->{changetype}[0]; print "changetype: $type\n"; if ($type =~ /modify/i) { # Should we filter out modifiersname and modifytimestamp ? We do chop # off the trailing \0 though. chop($entry->{changes}[0]); print $entry->{changes}[0], "\n"; } elsif ($type =~ /add/i) { print $entry->{changes}[0], "\n"; } else { print "\n"; } $entry = $conn->nextEntry; } ################################################################################# # Close the connection. # $ld{conn}->close if $ld{conn}; perl-mozldap-1.5.3/examples/lfinger.pl0000555000076400007640000001156010634204215016374 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: lfinger.pl,v 1.11.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # "finger" version using LDAP information (using RFC 2307 objectclass). use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ############################################################################# # Constants, shouldn't have to edit these... The HIDE mechanism is a very # Netscape internal specific feature. We use this objectclass to mark some # entries to be "hidden", and some of our applications will honor this. With # more recent versions of the Directory Server this can be accomplished more # effectively with appropriate ACI/ACLs. # $APPNAM = "lfinger"; $USAGE = "$APPNAM -m -b base -h host -D bind -w pswd -P cert -V ver user_info"; @ATTRIBUTES = ("uid", "cn", "homedirectory", "loginshell", "pager", "telephonenumber", "facsimiletelephonenumber", "mobile"); $HIDE = "(objectclass=nscphidethis)"; ############################################################################# # Print a "finger" entry. # sub printIt { my($entry) = @_; print "Login name: $entry->{uid}[0]"; print " " x (39 - 11 - length($entry->{uid}[0])); print "In real life: $entry->{cn}[0]\n"; if ($entry->{homedirectory}[0] || $entry->{loginshell}[0]) { print "Directory: $entry->{homedirectory}[0]"; print " " x (39 - 10 - length($entry->{homedirectory}[0])); print "Shell: $entry->{loginshell}[0]\n"; } if ($entry->{telephonenumber}[0] || $entry->{pager}[0]) { print "Phone: $entry->{telephonenumber}[0]"; print " " x (39 - 6 - length($entry->{telephonenumber}[0])); print "Pager: $entry->{pager}[0]\n"; } if ($entry->{mobile}[0] || $entry->{facsimiletelephonenumber}[0]) { print "Mobile: $entry->{mobile}[0]"; print " " x (39 - 7 - length($entry->{mobile}[0])); print "Fax: $entry->{facsimiletelephonenumber}[0]\n"; } print "\n"; } ############################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('mb:h:D:p:w:P:V:') || !defined($ARGV[$[])) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); $user=$ARGV[$[]; ############################################################################# # Instantiate an LDAP object, which also binds to the LDAP server. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; ############################################################################# # Ok, lets generate the filter, and do the search! # if ($opt_m) { $search = "(&(uid=$user)(!$HIDE))"; } else { $search = "(&(|(cn=*$user*)(uid=*$user*)(telephonenumber=*$user*))(!$HIDE))"; } $entry = $conn->search($ld{root}, "subtree", $search, 0, @ATTRIBUTES); $conn->printError() if $conn->getErrorCode(); while($entry) { printIt($entry); $entry = $conn->nextEntry(); } ############################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/monitor.pl0000555000076400007640000000616710634204215016444 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: monitor.pl,v 1.3.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Ask the directory server for it's monitor entry, to see some # performance and usage stats. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "monitor"; $USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert -V ver"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('b:h:D:p:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs("", "cn=monitor"); ################################################################################# # Instantiate an LDAP object, which also binds to the LDAP server, and then # do the simple search. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; $entry = $conn->search($ld{root}, "base", "objectclass=*"); Mozilla::LDAP::Utils::printEntry($entry) if ($entry); ################################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/rename.pl0000555000076400007640000000752410634204215016222 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: rename.pl,v 1.5.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Rename an LDAP entry, changing it's DN. Note that currently this only # works with RDNs. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ############################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "rename"; $USAGE = "$APPNAM [-nvI] -b base -h host -D bind -w pswd -P cert -V ver filter new_rdn"; ############################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvIb:h:D:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; ($search, $rdn) = @ARGV; if (($search eq "") || ($rdn eq "")) { print "usage: $APPNAM $USAGE\n"; exit; } ############################################################################# # Instantiate an LDAP object, which also binds to the LDAP server. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; $key = "Y" if $opt_I; $entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @ATTRIBUTES); $conn->printError() if $conn->getErrorCode(); if (! $entry || $conn->nextEntry()) { print "Error: The search did not return exactly one match, abort!\n"; exit; } if (! $opt_I) { print "Rename ", $entry->getDN(), " with $rdn [N]? "; $key = Mozilla::LDAP::Utils::answer("N") unless $opt_I; } if ($key eq "Y") { # Note: I have to explicitly specify the original DN below, since the call # to nextEntry() above blows the DN away from the ::Conn object. if (! $opt_n) { $conn->modifyRDN($rdn, $entry->getDN()); $conn->printError() if $conn->getErrorCode(); } print "Renamed $entry->{dn}\n" if $opt_v; } ################################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/rmentry.pl0000555000076400007640000000722310634204215016447 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: rmentry.pl,v 1.6.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Remove one or several LDAP objects. By default this tool is # interactive, which can be disabled with the "-I" option (but # please be careful...). use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "rmentry"; $USAGE = "$APPNAM [-nvI] -b base -h host -p port -D bind -w pswd" . "-P cert -V ver filter ..."; @ATTRIBUTES = ("uid"); ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvIb:h:p:D:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; ################################################################################# # Do the search, and process all the entries. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; $key = "Y" if $opt_I; foreach $search (@ARGV) { $entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @ATTRIBUTES); $conn->printError() if $conn->getErrorCode(); while ($entry) { if (! $opt_I) { print "Delete $entry->{dn} [N]? "; $key = Mozilla::LDAP::Utils::answer("N") unless $opt_I; } if ($key eq "Y") { if (! $opt_n) { $conn->delete($entry); $conn->printError() if $conn->getErrorCode(); } print "Deleted $entry->{dn}\n" if $opt_v; } $entry = $conn->nextEntry(); } } ################################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/ldappasswd.pl0000555000076400007640000001017010634204215017104 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: ldappasswd.pl,v 1.7.2.5 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # This is an LDAP version of the normal passwd/yppasswd command found # on most Unix systems. Note that this will only use the {crypt} # encryption/hash algorithm (at this point). use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ############################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "ldappasswd"; $USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert -V ver search ..."; @ATTRIBUTES = ("uid", "userpassword"); ############################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvb:s:h:D:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; ############################################################################# # Ask for the new password, and confirm it's correct. # do { print "New password: "; $new = Mozilla::LDAP::Utils::askPassword(); print "New password (again): "; $new2 = Mozilla::LDAP::Utils::askPassword(); print "Passwords didn't match, try again!\n\n" if ($new ne $new2); } until ($new eq $new2); print "\n"; ############################################################################# # Now do all the searches, one by one. If there are no search criteria, we # will change the password for the user running the script. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; foreach $search ($#ARGV >= $[ ? @ARGV : $ld{bind}) { $entry = $conn->search($search, "subtree", "ALL", 0, @ATTRIBUTES); $entry = $conn->search($ld{root}, "subtree", $search, 0, @ATTRIBUTES) unless $entry; print "No such user: $search\n" unless $entry; while ($entry) { $entry->{userpassword} = [$new]; print "Changing password for: $entry->{dn}\n" if $opt_v; if (!$opt_n) { $conn->update($entry); $conn->printError() if $conn->getErrorCode(); } $entry = $conn->nextEntry(); } } ############################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/psoftsync.pl0000555000076400007640000003540710634204215017004 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: psoftsync.pl,v 1.6.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Synchronise some LDAP info with a PeopleSoft "dump". This "dump" file # is a "tab" separated file, as generated by an SQL utility on the # Oracle server. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ############################################################################# # Local configurations, check these out . Note that SYNCS and ORDER has to # have the same fields, this is because the hash array doesn't preserve # the order of it's entries... :-( The "codes" are bit fields, where the # three LSB are used as # # 1 Force the update, even if attribute is empty (i.e. delete it) # 2 The attribute is the base for a DN (e.g. "manager"). # 4 The attribute should be deleted if the user is not in PeopleSoft. # 8 Don't warn if the attribute is missing in the Psoft file (-W option). # 16 Always delete this attribute in the PeopleSoft entry. # 32 Delete this attribute if the account has "expired". # %SYNCS = ( "nscpharold" => 1 + 4, "uid" => 0, "" => 0, "" => 0, "employeenumber" => 1 + 4 + 32, "departmentnumber" => 1 + 4, "" => 0, "" => 0, "" => 0, "manager" => 1 + 2, "title" => 1 + 4 + 16 + 32, "ou" => 1 + 4 + 32, "businesscategory" => 1 + 4 + 32, "employeetype" => 0, "nscppersonexpdate" => 1 + 8 ); @ORDER = ( "nscpharold", "uid", "", "", "employeenumber", "departmentnumber", "", "", "", "manager", "title", "ou", "businesscategory", "employeetype", "nscppersonexpdate" ); # This is used for mapping the employeeType attribute into a readable format. %EMPCODES = ( "A" => "Applicant", "C" => "Contractor", "E" => "Employee", "O" => "OEM Partner", "T" => "Interim", "V" => "Vendor" ); # Expiration policy for other attributes, the EXPDELAY is a convenience # default setting. $EXPDELAY = 24 * 7; %EXPIRES = ( "carlicense" => $EXPDELAY, "mailautoreplymode" => $EXPDELAY, "mailautoreplytext" => $EXPDELAY, "mailforwardingaddress" => $EXPDELAY, "facsimiletelephonenumber" => $EXPDELAY ); $NOTYPE = "Unknown"; $DELIMITER = "%%"; $SENDMAIL = "/usr/lib/sendmail"; $SEARCH = "(&(uid=*)(!(objectclass=pseudoAccount)))"; $MAILTO = "leif\@netscape.com"; #$LDAP_DEBUG = 1; ############################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "psoftsync"; $USAGE = "$APPNAM [-nvW] -b base -h host -D bind -w passwd -P cert -V ver PS_file"; @ATTRIBUTES = uniq(@ORDER); push(@ATTRIBUTES, "objectclass"); $TODAY = `/usr/bin/date '+%Y%m%d'`; chop($TODAY); ############################################################################# # Print an error for the PeopleSoft data. Note that we use the "__XXX__" fields # here, to avoid the problem when an attribute is "expired" or modified. # sub psoftError { my ($str, $entry) = @_; print "Error: $str: "; print $entry->key(), " ("; print $entry->{__employeenumber__}, ", "; print $entry->{__employeetype__}, ", "; print $entry->{__departmentnumber__}, ")\n"; } ############################################################################# # Read in a PeopleSoft file, and create all the entries. # sub readDump { my ($file) = @_; my (@info, %entries); my $val; if (!open(PSOFT, $file)) { print "Error: Can't read file $file\n"; exit(1); } while () { next unless /$DELIMITER/; @info = split(/\s*%%\s*/); $entry = PsoftEntry->new($info[$[]); foreach $attr (@ORDER) { $val = shift(@info); next if ($attr eq ""); $entry->add($attr, $val, $SYNCS{$attr}); } # # Perhaps we should do some sanity checks here on the PeopleSoft data? # # Clean up some data if the user has expired ("best before...") if ($entry->expired($entry->{nscppersonexpdate})) { foreach $attr (@ORDER) { next unless $attr; delete($entry->{$attr}) if ($SYNCS{$attr} & 32); } } if ($entry->{uid}) { $entries{$entry->{uid}} = $entry; } elsif ($opt_W) { psoftError("No UID", $entry); } } close(PSOFT); return %entries; } ############################################################################# # Make a list "uniq", just like the Unix command. # sub uniq { # uniq(elements[]) my %tmp; grep($tmp{$_}++, @_); return sort(keys(%tmp)); } ############################################################################# # Delete an attribute from an entry. # sub delAttr { # delAttr(ENTRY, ATTR) my ($entry, $attr) = @_; if (defined($entry->{$attr})) { $out->write("Deleted $attr for user: $entry->{uid}[0]") if $opt_v; delete($entry->{$attr}); return 1; } return 0; } ############################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvMWb:h:D:p:s:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; $out = Mail->new(); if ($opt_M) { $out->set("to", $MAILTO); $out->set("subject", "Hoth: PeopleSoft synchronization report"); } else { $out->echo(); $out->nomail(); } ############################################################################# # Read in all the PeopleSoft entries, and then instantiate an LDAP object, # which also binds to the LDAP server. # %psoft = readDump(@ARGV[$[]); $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; ############################################################################# # Now process all the users, one by one. # $entry = $conn->search($ld{root}, "subtree", $SEARCH, 0, @ATTRIBUTES); while ($entry) { $uid = $entry->{"uid"}[0]; $changed = 0; $psent = $psoft{$uid}; if (!$psent) { print "Error: LDAP user $uid: No entry in PeopleSoft\n" if $opt_W; foreach $attr (@ORDER) { next unless $attr; $changed += delAttr($entry, $attr) if ($SYNCS{$attr} & 4); } if ($entry->{employeetype}[0] ne "$NOTYPE") { $entry->{employeetype} = ["$NOTYPE"]; $changed = 1; $out->write("Set employeeType to $NOTYPE for user: $uid") if $opt_v; } } else { $psent->handled(1); foreach $attr (@ORDER) { next unless $attr; if (!defined($psent->{$attr}) || ($psent->{$attr} eq "")) { $changed += delAttr($entry, $attr) if ($SYNCS{$attr} & 1); } elsif ($entry->{$attr}[0] ne $psent->{$attr}) { $entry->{$attr} = [$psent->{$attr}]; $changed = 1; $out->write("Set $attr to $psent->{$attr} for user: $uid") if $opt_v; } } # Now handle the Expire date special case... if ($psent->expired() ne "") { if ($entry->addValue("objectclass", "nscphidethis")) { $changed = 1; $out->write("Expiring the user: $uid") if $opt_v; } # Expire other attributes, IFF the expire is over a certain # treshhold (e.g. a week). } elsif ($entry->removeValue("objectclass", "nscphidethis")) { $changed = 1; $out->write("Enabling the user: $uid") if $opt_v; } } $conn->update($entry) if ($changed && ! $opt_n); $entry = $conn->nextEntry(); } ############################################################################# # Close the LDAP connection. # $conn->close if $conn; ############################################################################# # Post process, figure out which PSoft entries have no entry in LDAP. # if ($opt_W) { foreach (keys(%psoft)) { $ent=$psoft{$_}; psoftError("No LDAP entry", $ent) unless $ent->handled(); } } ############################################################################# # Package to an entry from the PeopleSoft database. # package PsoftEntry; ############################################################################# # Creator. # sub new { my ($class, $key) = @_; my $self = {}; bless $self, ref $class || $class; $self->{__key__} = $key; return $self; } ############################################################################# # Add an attribute/field to the entry. # sub add { my ($self, $attr, $val, $lev) = @_; return if ($lev & 16); $attr = lc $attr; if ($attr eq "employeetype") { if (defined($main::EMPCODES{$val})) { $self->{$attr} = $main::EMPCODES{$val}; } else { $self->{$attr} = $main::NOTYPE; } $self->{__employeetype__} = $val; } elsif (!defined($val) || ($val eq "")) { main::psoftError("No attribute $attr", $self) if ($main::opt_W && ($lev & 1) && !($lev & 8)); } else { $self->{$attr} = ($lev & 2) ? "uid=$val,$main::ld{root}" : $val; $self->{"__${attr}__"} = $val; } } ############################################################################# # Return the value for an attribute/field. # sub get { my ($self, $attr) = @_; return $self->{$attr}; } ############################################################################# # Mark the entry as "expired". If there is no "date" argument, we'll return # the current entries expire status. # sub expired { my ($self, $date) = @_; if ($date) { # Only expire entries with reasonable expire dates... if (length($date) != 8) { main::psoftError("Bad expire date", $self) if $main::opt_W; return 0; } if ($date lt $main::TODAY) { $self->{employeetype} = "$main::NOTYPE"; $self->{__expired__} = 1; return 1; } } return $self->{__expired__}; } ############################################################################# # Mark the entry as "handled", i.e. it exists in LDAP. # sub handled { my ($self, $flag) = @_; $self->{__handled__} = 1 if $flag; return $self->{__handled__}; } ############################################################################# # Return the "key" of this entry, typically the name field. # sub key { my ($self) = @_; return $self->{__key__}; } ################################################################################# # This sub-package will send mail to some recipients, IFF there is anything to # send, or your force it to send. Note that the Subject doesn't qualify it to # send a message (force it to send if you have to). # package Mail; ################################################################################# # The constructor, which optionally takes the TO, FROM and SUBJECT. # sub new { my ($class, $to, $from, $subject) = @_; my $self = {}; bless $self, ref $class || $class; $self->{to} = $to || "root"; $self->{from} = $from || "ldap"; $self->{subject} = $subject || "Output from LDAP script\n"; @{$self->{message}} = (); $self->{send} = 0; $self->{nomail} = 0; $self->{echo} = 0; return $self; } ################################################################################# # Destructor, which will also send the message, if appropriate. # sub DESTROY { my ($self) = @_; if ($self->{send} && !$self->{nomail}) { $self->send(); $self->{send} = 0; } } ################################################################################# # Set a field for this entry, e.g. From:, To: etc. # sub set { my ($self, $field, $string) = @_; if ($field && $string) { $field = lc $field; $self->{$field} = $string; } } ################################################################################# # Add a line to the message, the argument is the string. # sub write { my ($self, $string) = @_; if ($string ne "") { push(@{$self->{message}}, $string); print "$string\n" if $self->{echo}; $self->{send}++; } } ################################################################################# # Force the object to send the message, no matter if there's anything in the # body or not. # sub force { my ($self) = @_; $self->{send} = 1; $self->{nomail} = 0; } ################################################################################# # Don't send the mail, this is the oppositte to "force... # sub nomail { my ($self) = @_; $self->{send} = 0; $self->{nomail} = 1; } ################################################################################# # Enable echo-mode, where we will also print everything to STDOUT. # sub echo { my ($self) = @_; $self->{echo} = 1; } ################################################################################# # Actually send the message. This is automatically done by the DESTROY method, # but we can force it to do it this way. # sub send { my ($self) = @_; if ($self->{send} && !$self->{nomail}) { open(MAILER, "|$main::SENDMAIL -t"); print MAILER "From: $self->{from}\n"; print MAILER "To: $self->{to}\n"; print MAILER "Subject: $self->{subject}\n\n"; foreach (@{$self->{message}}) { print MAILER "$_\n"; } print MAILER ".\n"; close(MAILER); $self->{send} = 0; } } perl-mozldap-1.5.3/examples/rand_mods.pl0000555000076400007640000001117510634204215016716 0ustar richrich#!/usr/bin/perl5 ################################################################################# # $Id: rand_mods.pl,v 1.3.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # SYNOPSIS: # Modify an attribute for one or more entries, or possibly delete it. # # USAGE: # rand_mods [-adnvW] -b base -h host -D bind DN -w pwd -P cert filter loops # attribute ... ################################################################################# # Modules we need. Note that we depend heavily on the Ldapp module, # which needs to be built from the C code. It also requires an LDAP SDK. # use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use Carp; use strict; no strict "vars"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "rand_mods"; $USAGE = "$APPNAM [-dnvW] -b base -h host -D bind -w pswd -V ver filter loops attr ..."; $AUTHOR = "Leif Hedstrom "; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('adnvWb:h:D:p:s:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); ################################################################################# # Instantiate an LDAP object, which also binds to the LDAP server. # if (!getopts('b:h:D:p:s:w:P:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); $conn = Mozilla::LDAP::Conn->new(\%ld); croak "Could't connect to LDAP server $ld{host}" unless $conn; ################################################################################# # Parse some extra argumens # my $srch, $loop; my (@attrs) = ("givenName", "sn"); if (! ($srch = shift(@ARGV))) { print "Usage: $APPNAME $USAGE\n"; exit; } $srch = "(&(!(objectclass=nscpHideThis))(uid=*))" if ($srch eq ""); if (! ($loops = shift(@ARGV))) { print "Usage: $APPNAME $USAGE\n"; exit; } @attrs = @ARGV if ($#ARGV > $[); $num_attrs = $#attrs; ################################################################################# # Find all the argument # my $num = 0; $entry = $conn->search($ld{root}, $ld{scope}, $srch, 0, ("0.0")); while ($entry) { push(@users, $entry->getDN()); $num++; $entry = $conn->nextEntry(); } print "Found $num users, randomizing changes now...\n"; srand(time ^ $$); my $tmp, $tmp2, $dn, $loop2; while ($loops--) { $dn = $users[rand($num)]; print "$loops loops left...\n" if (($loops % 100) == 0); $entry = $conn->browse($dn, @attrs); if ($entry) { $loop2 = $num_attrs + 1; while ($loop2--) { $tmp = $entry->{$attrs[$loop2]}[0]; $tmp2 = rand($num_attrs); $entry->{$attrs[$loop2]} = [ $entry->{$attrs[$tmp2]}[0] ]; $entry->{$attrs[$tmp2]} = [ $tmp] ; $entry->printLDIF(); } $conn->update($entry); } } perl-mozldap-1.5.3/examples/tabdump.pl0000555000076400007640000000672310634204215016407 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: tabdump.pl,v 1.4.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Generate a TAB separate "dump" of entries matching the search criteria, # using the list of attributes specified. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "tabdump"; $USAGE = "$APPNAM [-nv] -b base -h host -D bind -w pswd -P cert -V ver -t attr1,attr2,.. srch"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('nvb:h:D:p:s:w:P:t:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); $separator = (defined($opt_t) ? $opt_t : "\t"); $attributes = $ARGV[$[]; $search = $ARGV[$[ + 1]; die "Need to specify a list of attributes and the search filter.\n" unless ($attributes && $search); ################################################################################# # Do the searches, and produce the output. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; @attr = split(/,/, $attributes); $entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @attr); $conn->printError() if $conn->getErrorCode(); while ($entry) { foreach (@attr) { print $entry->{$_}[0], $separator; } print "\n"; $entry = $conn->nextEntry; } ################################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/examples/qsearch.pl0000555000076400007640000000671210634204215016377 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: qsearch.pl,v 1.9.2.5 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Quick Search, like ldapsearch, but in Perl. Look how simple it is. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use strict; no strict "vars"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "qsearch"; $USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert -V ver filter [attr...]"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('b:h:D:p:s:w:P:V:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(); ################################################################################# # Now do all the searches, one by one. # $conn = Mozilla::LDAP::Conn->new(\%ld); die "Could't connect to LDAP server $ld{host}" unless $conn; foreach (@ARGV) { if (/\=/) { push(@srch, $_); } else { push(@attr, $_); } } foreach $search (@srch) { if ($#attr >= $[) { $entry = $conn->search($ld{root}, $ld{scope}, $search, 0, @attr); } else { $entry = $conn->search($ld{root}, $ld{scope}, "$search"); } print "Searched for `$search':\n\n"; while ($entry) { $entry->printLDIF(); $entry = $conn->nextEntry; } $conn->printError() if $conn->getErrorCode(); print "\n"; } ################################################################################# # Close the connection. # $conn->close if $conn; perl-mozldap-1.5.3/t/0000775000076400007640000000000011426105703013036 5ustar richrichperl-mozldap-1.5.3/t/ChangeLog0000444000076400007640000000103110166655035014607 0ustar richrich2005-01-04 Leif Hedstrom * entry.pl: Changed all calls to new to use the class method directly. * conn.pl: Changed all calls to new to use the class method directly. 1999-08-06 Leif Hedstrom * conn.pl: Added support for browse() and compare(). 1999-03-19 Leif Hedstrom * conn.pl: Added test for add() with a hash array. 1999-01-05 Leif Hedstrom * entry.pl: New script, to test all Entry:: methods. * conn.pl: Added test for modifyRDN(). perl-mozldap-1.5.3/t/conn.pl0000555000076400007640000002174710634204215014340 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: conn.pl,v 1.5.2.3 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Test most (all?) of the LDAP::Mozilla::Conn methods. This code # needs to be rewritten to use the standard test harness in Perl... use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use Mozilla::LDAP::API; use strict; no strict "vars"; # Uncomment for somewhat more verbose messages from core modules #$LDAP_DEBUG = 1; ################################################################################# # Configurations, modify these as needed. # $BASE = "o=ogre.com"; $PEOPLE = "ou=people"; $UID = "leif-test"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "conn.pl"; $USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('b:h:D:p:s:w:P:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(undef, $BASE); $BASE = $ld{"base"}; Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; ################################################################################# # Get an LDAP connection # sub getConn { my ($conn); if ($main::reuseConn) { if (!defined($main::mainConn)) { $main::mainConn = Mozilla::LDAP::Conn->new(\%main::ld); die "Could't connect to LDAP server $main::ld{host}" unless $main::mainConn; } return $main::mainConn; } else { $conn = Mozilla::LDAP::Conn->new(\%main::ld); die "Could't connect to LDAP server $main::ld{host}" unless $conn; } return $conn; } ################################################################################# # Some small help functions... # sub dotPrint { my ($str) = shift; print $str . '.' x (20 - length($str)); } sub attributeEQ { my (@a, @b); my ($i); @a = @{$_[0]}; @b = @{$_[1]}; return 1 if (($#a < 0) && ($#b < 0)); return 0 unless ($#a == $#b); @a = sort(@a); @b = sort(@b); for ($i = 0; $i <= $#a; $i++) { return 0 unless ($a[$i] eq $b[$i]);; } return 1; # We passed all the tests, we're ok. } ################################################################################# # Test adding, deleting and retrieving entries. # undef $reuseConn; $filter = "(uid=$UID)"; $conn = getConn(); $nentry = Mozilla::LDAP::Conn->newEntry(); $hash = { "dn" => "uid=$UID, $PEOPLE, $BASE", "objectclass" => [ "top", "person", "inetOrgPerson"], "uid" => [ $UID ], "sn" => [ "Hedstrom" ], "givenName" => [ "Leif" ], "mail" => [ "leif\@ogre.com" ], "cn" => [ "Leif Hedstrom", "Leif P. Hedstrom" ], "description" => [ "Hockey Goon", "LDAP dolt" ] }; $ent = $conn->search($ld{root}, $ld{scope}, $filter); $conn->delete($ent->getDN()) if $ent; $nentry->setDN("uid=$UID, $PEOPLE, $BASE"); $nentry->{objectclass} = [ "top", "person", "inetOrgPerson"]; $nentry->addValue("uid", $UID); $nentry->addValue("sn", "Hedstrom"); $nentry->addValue("givenName", "Leif"); $nentry->addValue("cn", "Leif Hedstrom"); $nentry->addValue("cn", "Leif P. Hedstrom"); $nentry->addValue("cn", "The Swede"); ($nentry->size("cn") != 3) && die "Entry->addValue() is broken!\n"; $nentry->addValue("mail", "leif\@ogre.com"); $nentry->setValue("description", "Hockey Goon", "LDAP dolt"); $nentry->setValue("jpegPhoto", "Before-Bin: f¤›Š›¡ :After-Bin"); dotPrint("Conn/newEntry"); $conn->add($nentry) || print "not "; print "ok\n"; dotPrint("Conn/delete"); $conn->delete($nentry) || print "not "; print "ok\n"; dotPrint("Conn/add"); $conn->add($nentry) || print "not "; print "ok\n"; dotPrint("Conn/delete-2"); $conn->delete($nentry) || print "not "; print "ok\n"; dotPrint("Conn/add-with-hash"); $conn->add($hash) || print "not "; print "ok\n"; $nentry->addValue("description", "Solaris rules"); $nentry->addValue("description", "LDAP weenie"); dotPrint("Conn/add+update"); $conn->update($nentry) || print "not "; print "ok\n"; dotPrint("Conn/delete(DN)"); $conn->delete($nentry->getDN()) || print "not "; print "ok\n"; $conn->add($nentry) || die "Can't create entry again...\n"; dotPrint("Conn/search"); $ent = $conn->search($ld{root}, $ld{scope}, $filter); $err = 0; foreach (keys (%{$nentry})) { $err = 1 unless (defined($ent->{$_}) && attributeEQ($nentry->{$_}, $ent->{$_})); } print "not " if $err; print "ok\n"; $conn->close(); ################################################################################# # Test LDAP URL handling. # $conn = getConn(); $url1 = "ldap:///" . $ld{root} . "??sub?$filter"; $url2 = "ldaps:///" . $ld{root} . "??sub?$filter"; $badurl1 = "ldap:" . $ld{root} . "??sub?$filter"; $badurl2 = "http://" . $ld{root} . "??sub?$filter"; dotPrint("Conn/isURL"); print "not " unless ($conn->isURL($url1) && $conn->isURL($url2) && !$conn->isURL($badurl2) && !$conn->isURL($badurl1)); print "ok\n"; dotPrint("Conn/searchURL"); $ent = $conn->searchURL($url1); $err = 0; foreach (keys (%{$nentry})) { $err = 1 unless (defined($ent->{$_}) && attributeEQ($nentry->{$_}, $ent->{$_})); } print "not " if $err; print "ok\n"; $conn->close(); ################################################################################# # Test some small internal stuff. # $conn = getConn(); $ent = $conn->search($ld{root}, $ld{scope}, $filter); print "Can't locate entry again" unless $ent; dotPrint("Conn/getLD+getRes"); $err = 0; $cld = $conn->getLD(); $res = $conn->getRes(); $err = 1 unless $cld; $err = 1 unless $res; $count = Mozilla::LDAP::API::ldap_count_entries($cld, $res); $err = 1 unless ($count == 1); print "not " if $err; print "ok\n"; $conn->close(); ################################################################################# # Test browse and compare methods. # $conn = getConn(); dotPrint("Conn/browse"); $ent = $conn->browse($nentry->getDN()); print "not " unless $ent; print "ok\n"; dotPrint("Conn/compare"); print "not " unless $conn->compare($nentry->getDN(), "SN", "Hedstrom"); print "ok\n"; $conn->close(); ################################################################################# # Test the simple authentication method # #$conn = Mozilla::LDAP::Conn->new($ld{host}, $ld{port}); $conn = getConn(); $ent = $conn->search($ld{root}, $ld{scope}, $filter); die "Can't locate entry again" unless $ent; dotPrint("Conn/simpleAuth"); $err = 0; $conn->simpleAuth($ld{bind}, $ld{pswd}) || ($err = 1); $ent = $conn->search($ld{root}, $ld{scope}, $filter); $err = 1 unless $ent; print "not " if $err; print "ok\n"; $conn->close(); ################################################################################# # Test the modifyRDN functionality # $conn = getConn(); $ent = $conn->search($ld{root}, $ld{scope}, $filter); die "Can't locate entry again" unless $ent; dotPrint("Conn/modifyRDN"); $err = 0; $rdn = "uid=$UID-rdn"; $conn->modifyRDN($rdn, $ent->getDN()) || ($err = 1); $filter = "($rdn)"; $ent = $conn->search($ld{root}, $ld{scope}, $filter); $err = 1 unless $ent; print "not " if $err; print "ok\n"; $conn->delete($ent->getDN()) if $ent; ################################################################################# # Test error handling (ToDo!) # perl-mozldap-1.5.3/t/utils.t0000444000076400007640000000011406760616437014373 0ustar richrichprint "This is not a real test, yet...\n"; print "1..1\n"; print "ok 1\n"; perl-mozldap-1.5.3/t/ssl.pl0000444000076400007640000000607710634204215014200 0ustar richrich#!/usr/bin/env perl ############################################################################# # $Id: ssl.pl,v 1.1.2.2 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Rich Megginson # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Test most (all?) of the LDAP::Mozilla::Conn methods. This code # needs to be rewritten to use the standard test harness in Perl... use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use Mozilla::LDAP::API; use strict; no strict "vars"; # Uncomment for somewhat more verbose messages from core modules #$LDAP_DEBUG = 1; ################################################################################# # Configurations, modify these as needed. # $BASE = "dc=example,dc=com"; $PEOPLE = "ou=people"; $UID = "scarter"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "ssl.pl"; $USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert -N certname -W keypassword -Z"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('b:h:D:p:s:w:P:N:W:Z')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs(undef, $BASE); $BASE = $ld{"base"}; Mozilla::LDAP::Utils::userCredentials(\%ld) unless $opt_n; perl-mozldap-1.5.3/t/api.t0000444000076400007640000000011406760616435014002 0ustar richrichprint "This is not a real test, yet...\n"; print "1..1\n"; print "ok 1\n"; perl-mozldap-1.5.3/t/conn.t0000444000076400007640000000011406760616436014167 0ustar richrichprint "This is not a real test, yet...\n"; print "1..1\n"; print "ok 1\n"; perl-mozldap-1.5.3/t/ldif.t0000444000076400007640000000457610634204215014147 0ustar richrich#!/usr/bin/perl ############################################################################# # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerlDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Test the LDIF module use Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils qw(normalizeDN); use Mozilla::LDAP::API qw(ldap_explode_dn); use Mozilla::LDAP::LDIF; use strict; my $testldif = "t/test.ldif"; print "1..1\n"; open( LDIF, "$testldif" ) || die "Can't open $testldif: $!"; my $in = new Mozilla::LDAP::LDIF(*LDIF) ; my $ent; while ($ent = readOneEntry $in) { print "The Entry is:\n"; Mozilla::LDAP::LDIF::put_LDIF(select(), 78, $ent); my $desc = $ent->getValue('description'); # this tests the base64 decoding die "Error: the description is not hello world" if ($desc ne 'hello world'); } close LDIF; print "ok 1\n"; perl-mozldap-1.5.3/t/ssl.sh0000555000076400007640000000143310472674523014206 0ustar richrich#!/bin/sh LD_LIBRARY_PATH=/home/rich/mozilla/dist/lib ; export LD_LIBRARY_PATH #argsfile=.gdbinit #echo "break main" > $argsfile #echo "run -I../blib/arch -I../blib/lib ssl.pl -h localhost -p 10202 -P /home/rich/102srv/alias/slapd-localhost-cert8.db -N Server-Cert -W 723d1e6cf342e1d133c69876e938be08e41bad41 -b '' objectclass=*" >> $argsfile #gdb -x $argsfile perl #rm -f $argsfile perl -d -I../blib/arch -I../blib/lib ssl.pl -h localhost -Z -p 10200 -P /home/rich/102srv/alias/slapd-localhost-cert8.db -N "Server-Cert" -W `cat /home/rich/102srv/alias/pwdfile.txt` -b "" "objectclass=*" #perl -d -I../blib/arch -I../blib/lib ssl.pl -h localhost -p 10202 -P /home/rich/102srv/alias/slapd-localhost-cert8.db -N "Server-Cert" -W `cat /home/rich/102srv/alias/pwdfile.txt` -b "" "objectclass=*" perl-mozldap-1.5.3/t/test.ldif0000444000076400007640000000032010612246007014643 0ustar richrichdn: uid=user,dc=example,dc=com objectclass: top objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: user cn: Jay User sn: User givenName: Jay description:: aGVsbG8gd29ybGQ= perl-mozldap-1.5.3/t/entry.pl0000555000076400007640000001141110634204215014527 0ustar richrich#!/usr/bin/perl5 ############################################################################# # $Id: entry.pl,v 1.3.2.4 2007/06/14 09:21:17 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # Test most (all?) of the LDAP::Mozilla::Conn methods. use Getopt::Std; # To parse command line arguments. use Mozilla::LDAP::Conn; # Main "OO" layer for LDAP use Mozilla::LDAP::Utils; # LULU, utilities. use Mozilla::LDAP::API; use strict; no strict "vars"; ################################################################################# # Configurations, modify these as needed. # $BIND = "uid=ldapadmin"; $BASE = "o=ogre.com"; $PEOPLE = "ou=people"; $UID = "leif-test"; ################################################################################# # Constants, shouldn't have to edit these... # $APPNAM = "entry.pl"; $USAGE = "$APPNAM -b base -h host -D bind -w pswd -P cert"; ################################################################################# # Check arguments, and configure some parameters accordingly.. # if (!getopts('b:h:D:p:s:w:P:')) { print "usage: $APPNAM $USAGE\n"; exit; } %ld = Mozilla::LDAP::Utils::ldapArgs($BIND, $BASE); ################################################################################# # Get an LDAP connection # sub getConn { my $conn; if ($main::reuseConn) { if (!defined($main::mainConn)) { $main::mainConn = Mozilla::LDAP::Conn->new(\%main::ld); die "Could't connect to LDAP server $main::ld{host}" unless $main::mainConn; } return $main::mainConn; } else { $conn = Mozilla::LDAP::Conn->new(\%main::ld); die "Could't connect to LDAP server $main::ld{host}" unless $conn; } return $conn; } ################################################################################# # Some small help functions... # sub dotPrint { my $str = shift; print $str . '.' x (20 - length($str)); } sub attributeEQ { my (@a, @b); my $i; @a = @{$_[0]}; @b = @{$_[1]}; return 1 if (($#a < 0) && ($#b < 0)); return 0 unless ($#a == $#b); @a = sort(@a); @b = sort(@b); for ($i = 0; $i <= $#a; $i++) { return 0 unless ($a[$i] eq $b[$i]);; } return 1; # We passed all the tests, we're ok. } ################################################################################# # Setup the test entries. # undef $reuseConn; $filter = "(uid=$UID)"; $conn = getConn(); $nentry = $conn->newEntry("uid=$UID, $PEOPLE, $BASE"); $nentry->{objectclass} = [ "top", "person", "inetOrgPerson", "mailRecipient" ]; $nentry->addValue("uid", $UID); $nentry->addValue("sn", "Hedstrom"); $nentry->addValue("givenName", "Leif"); $nentry->addValue("cn", "Leif Hedstrom"); $nentry->addValue("cn", "Leif P. Hedstrom"); $nentry->addValue("cn", "The Swede"); $nentry->addValue("description", "Test1"); $nentry->addValue("description", "Test2"); $nentry->addValue("description", "Test3"); $nentry->addValue("description", "Test4"); $nentry->addValue("description", "Test5"); $nentry->addValue("mail", "leif\@ogre.com"); $ent = $conn->search($ld{root}, $ld{scope}, $filter); $conn->delete($ent->getDN()) if $ent; $conn->add($nentry); $nentry->printLDIF(); $conn->close(); perl-mozldap-1.5.3/t/entry.t0000444000076400007640000000011406760616436014373 0ustar richrichprint "This is not a real test, yet...\n"; print "1..1\n"; print "ok 1\n"; perl-mozldap-1.5.3/API.pm0000444000076400007640000016372710634204212013551 0ustar richrich############################################################################# # $Id: API.pm,v 1.16.2.5 2007/06/14 09:21:14 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # Kevin McCarthy # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # This is a description. package Mozilla::LDAP::API; use strict; use Carp; use vars qw($VERSION @ISA %EXPORT_TAGS @EXPORT @EXPORT_OK $AUTOLOAD); require Exporter; require DynaLoader; require AutoLoader; @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. %EXPORT_TAGS = (constant => [qw( LDAPS_PORT LDAP_ADMINLIMIT_EXCEEDED LDAP_AFFECTS_MULTIPLE_DSAS LDAP_ALIAS_DEREF_PROBLEM LDAP_ALIAS_PROBLEM LDAP_ALL_USER_ATTRS LDAP_ALREADY_EXISTS LDAP_AUTH_METHOD_NOT_SUPPORTED LDAP_AUTH_NONE LDAP_AUTH_SASL LDAP_AUTH_SIMPLE LDAP_AUTH_UNKNOWN LDAP_BUSY LDAP_CACHE_CHECK LDAP_CACHE_LOCALDB LDAP_CACHE_POPULATE LDAP_CHANGETYPE_ADD LDAP_CHANGETYPE_ANY LDAP_CHANGETYPE_DELETE LDAP_CHANGETYPE_MODDN LDAP_CHANGETYPE_MODIFY LDAP_CLIENT_LOOP LDAP_COMPARE_FALSE LDAP_COMPARE_TRUE LDAP_CONFIDENTIALITY_REQUIRED LDAP_CONNECT_ERROR LDAP_CONSTRAINT_VIOLATION LDAP_CONTROL_ENTRYCHANGE LDAP_CONTROL_MANAGEDSAIT LDAP_CONTROL_NOT_FOUND LDAP_CONTROL_PERSISTENTSEARCH LDAP_CONTROL_PWEXPIRED LDAP_CONTROL_PWEXPIRING LDAP_CONTROL_REFERRALS LDAP_CONTROL_SORTREQUEST LDAP_CONTROL_SORTRESPONSE LDAP_CONTROL_VLVREQUEST LDAP_CONTROL_VLVRESPONSE LDAP_DECODING_ERROR LDAP_DEREF_ALWAYS LDAP_DEREF_FINDING LDAP_DEREF_NEVER LDAP_DEREF_SEARCHING LDAP_ENCODING_ERROR LDAP_FILTER_ERROR LDAP_FILT_MAXSIZ LDAP_INAPPROPRIATE_AUTH LDAP_INAPPROPRIATE_MATCHING LDAP_INSUFFICIENT_ACCESS LDAP_INVALID_CREDENTIALS LDAP_INVALID_DN_SYNTAX LDAP_INVALID_SYNTAX LDAP_IS_LEAF LDAP_LOCAL_ERROR LDAP_LOOP_DETECT LDAP_MOD_ADD LDAP_MOD_BVALUES LDAP_MOD_DELETE LDAP_MOD_REPLACE LDAP_MORE_RESULTS_TO_RETURN LDAP_MSG_ALL LDAP_MSG_ONE LDAP_MSG_RECEIVED LDAP_NAMING_VIOLATION LDAP_NOT_ALLOWED_ON_NONLEAF LDAP_NOT_ALLOWED_ON_RDN LDAP_NOT_SUPPORTED LDAP_NO_ATTRS LDAP_NO_LIMIT LDAP_NO_MEMORY LDAP_NO_OBJECT_CLASS_MODS LDAP_NO_RESULTS_RETURNED LDAP_NO_SUCH_ATTRIBUTE LDAP_NO_SUCH_OBJECT LDAP_OBJECT_CLASS_VIOLATION LDAP_OPERATIONS_ERROR LDAP_OPT_CACHE_ENABLE LDAP_OPT_CACHE_FN_PTRS LDAP_OPT_CACHE_STRATEGY LDAP_OPT_CLIENT_CONTROLS LDAP_OPT_DEBUG_LEVEL LDAP_OPT_DEREF LDAP_OPT_DESC LDAP_OPT_DNS LDAP_OPT_DNS_FN_PTRS LDAP_OPT_ERROR_NUMBER LDAP_OPT_ERROR_STRING LDAP_OPT_HOST_NAME LDAP_OPT_IO_FN_PTRS LDAP_OPT_MEMALLOC_FN_PTRS LDAP_OPT_OFF LDAP_OPT_ON LDAP_OPT_PREFERRED_LANGUAGE LDAP_OPT_PROTOCOL_VERSION LDAP_OPT_REBIND_ARG LDAP_OPT_REBIND_FN LDAP_OPT_RECONNECT LDAP_OPT_REFERRALS LDAP_OPT_REFERRAL_HOP_LIMIT LDAP_OPT_RESTART LDAP_OPT_RETURN_REFERRALS LDAP_OPT_SERVER_CONTROLS LDAP_OPT_SIZELIMIT LDAP_OPT_SSL LDAP_OPT_THREAD_FN_PTRS LDAP_OPT_TIMELIMIT LDAP_OTHER LDAP_PARAM_ERROR LDAP_PARTIAL_RESULTS LDAP_PORT LDAP_PORT_MAX LDAP_PROTOCOL_ERROR LDAP_REFERRAL LDAP_REFERRAL_LIMIT_EXCEEDED LDAP_RESULTS_TOO_LARGE LDAP_RES_ADD LDAP_RES_ANY LDAP_RES_BIND LDAP_RES_COMPARE LDAP_RES_DELETE LDAP_RES_EXTENDED LDAP_RES_MODIFY LDAP_RES_MODRDN LDAP_RES_RENAME LDAP_RES_SEARCH_ENTRY LDAP_RES_SEARCH_REFERENCE LDAP_RES_SEARCH_RESULT LDAP_ROOT_DSE LDAP_SASL_BIND_IN_PROGRESS LDAP_SASL_EXTERNAL LDAP_SASL_SIMPLE LDAP_SCOPE_BASE LDAP_SCOPE_ONELEVEL LDAP_SCOPE_SUBTREE LDAP_SECURITY_NONE LDAP_SERVER_DOWN LDAP_SIZELIMIT_EXCEEDED LDAP_SORT_CONTROL_MISSING LDAP_STRONG_AUTH_NOT_SUPPORTED LDAP_STRONG_AUTH_REQUIRED LDAP_SUCCESS LDAP_TIMELIMIT_EXCEEDED LDAP_TIMEOUT LDAP_TYPE_OR_VALUE_EXISTS LDAP_UNAVAILABLE LDAP_UNAVAILABLE_CRITICAL_EXTENSION LDAP_UNDEFINED_TYPE LDAP_UNWILLING_TO_PERFORM LDAP_URL_ERR_BADSCOPE LDAP_URL_ERR_MEM LDAP_URL_ERR_NODN LDAP_URL_ERR_NOTLDAP LDAP_URL_ERR_PARAM LDAP_URL_OPT_SECURE LDAP_USER_CANCELLED LDAP_VERSION LDAP_VERSION1 LDAP_VERSION2 LDAP_VERSION3 LDAP_VERSION_MAX PRLDAP_OPT_IO_MAX_TIMEOUT LDAPSSL_AUTH_WEAK LDAPSSL_AUTH_CERT LDAPSSL_AUTH_CNCHECK )], api => [qw( ldap_abandon ldap_add ldap_add_s ldap_ber_free ldap_build_filter ldap_compare ldap_compare_s ldap_count_entries ldap_create_filter ldap_delete ldap_delete_s ldap_dn2ufn ldap_err2string ldap_explode_dn ldap_explode_rdn ldap_first_attribute ldap_first_entry ldap_free_friendlymap ldap_free_sort_keylist ldap_free_urldesc ldap_friendly_name ldap_get_dn ldap_getfilter_free ldap_getfirstfilter ldap_get_lang_values ldap_get_lang_values_len ldap_get_lderrno ldap_getnextfilter ldap_get_option ldap_get_values ldap_get_values_len ldap_init ldap_init_getfilter ldap_init_getfilter_buf ldap_is_ldap_url ldap_memcache_destroy ldap_memcache_flush ldap_memcache_get ldap_memcache_init ldap_memcache_set ldap_memcache_update ldap_memfree ldap_modify ldap_modify_s ldap_modrdn ldap_modrdn_s ldap_modrdn2 ldap_modrdn2_s ldap_mods_free ldap_msgfree ldap_msgid ldap_msgtype ldap_multisort_entries ldap_next_attribute ldap_next_entry ldap_perror ldap_result ldap_result2error ldap_search ldap_search_s ldap_search_st ldap_set_filter_additions ldap_set_lderrno ldap_set_option ldap_set_rebind_proc ldap_set_default_rebind_proc ldap_simple_bind ldap_simple_bind_s ldap_sort_entries ldap_unbind ldap_unbind_s ldap_url_parse ldap_url_search ldap_url_search_s ldap_url_search_st ldap_version )], apiv3 => [qw( ldap_abandon_ext ldap_add_ext ldap_add_ext_s ldap_compare_ext ldap_compare_ext_s ldap_control_free ldap_controls_count ldap_controls_free ldap_count_messages ldap_count_references ldap_create_persistentsearch_control ldap_create_sort_control ldap_create_sort_keylist ldap_create_virtuallist_control ldap_delete_ext ldap_delete_ext_s ldap_extended_operation ldap_extended_operation_s ldap_first_message ldap_first_reference ldap_get_entry_controls ldap_modify_ext ldap_modify_ext_s ldap_next_message ldap_next_reference ldap_parse_entrychange_control ldap_parse_extended_result ldap_parse_reference ldap_parse_result ldap_parse_sasl_bind_result ldap_parse_sort_control ldap_parse_virtuallist_control ldap_rename ldap_rename_s ldap_sasl_bind ldap_sasl_bind_s ldap_search_ext ldap_search_ext_s )], ssl => [qw( ldap_start_tls_s ldapssl_client_init ldapssl_clientauth_init ldapssl_enable_clientauth ldapssl_err2string ldapssl_init ldapssl_install_routines ldapssl_set_strength )], nspr => [qw( prldap_install_routines prldap_set_session_option )] ); # Add Everything in %EXPORT_TAGS to @EXPORT_OK Exporter::export_ok_tags(keys %EXPORT_TAGS); $VERSION = '1.5'; # The XS 'constant' routine returns an integer. There are all constants # we want to return something else. my (%OVERRIDE_CONST) = ( "LDAP_ALL_USER_ATTRS","*", "LDAP_CONTROL_ENTRYCHANGE","2.16.840.1.113730.3.4.7", "LDAP_CONTROL_MANAGEDSAIT","2.16.840.1.113730.3.4.2", "LDAP_CONTROL_PERSISTENTSEARCH","2.16.840.1.113730.3.4.3", "LDAP_CONTROL_PWEXPIRED","2.16.840.1.113730.3.4.4", "LDAP_CONTROL_PWEXPIRING","2.16.840.1.113730.3.4.5", "LDAP_CONTROL_REFERRALS","1.2.840.113556.1.4.616", "LDAP_CONTROL_SORTREQUEST","1.2.840.113556.1.4.473", "LDAP_CONTROL_SORTRESPONSE","1.2.840.113556.1.4.474", "LDAP_CONTROL_VLVREQUEST","2.16.840.1.113730.3.4.9", "LDAP_CONTROL_VLVRESPONSE","2.16.840.1.113730.3.4.10", "LDAP_NO_ATTRS","1.1", "LDAP_OPT_OFF",0, "LDAP_OPT_ON",1, "LDAP_ROOT_DSE","", "LDAP_SASL_EXTERNAL","EXTERNAL", ); sub AUTOLOAD { my ($constname); my ($val); # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. ($constname = $AUTOLOAD) =~ s/.*:://; if (($val = $OVERRIDE_CONST{$constname})) { eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } $val = constant($constname, @_ ? $_[0] : 0); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined Mozilla::LDAP macro $constname"; } } eval "sub $AUTOLOAD { $val }"; goto &$AUTOLOAD; } bootstrap Mozilla::LDAP::API $VERSION; # Preloaded methods go here. # Autoload methods go after =cut, and are processed by the autosplit program. 1; __END__ =head1 NAME Mozilla::LDAP::API - Perl methods for LDAP C API calls =head1 SYNOPSIS use Mozilla::LDAP::API; or use Mozilla::LDAP::API qw(:api :ssl :constant); or use Mozilla::LDAP::API qw(:api :ssl :apiv3 :constant); or use Mozilla::LDAP::API qw(:api :ssl :apiv3 :nspr :constant); =head1 DESCRIPTION This package offers a direct interface to the LDAP C API calls from Perl. It is used internally by the other Mozilla::LDAP modules. It is highly suggested that you use the object oriented interface in Mozilla::LDAP::Conn and Mozilla::LDAP::Entry unless you need to use asynchronous calls or other functionality not available in the OO interface. =head1 THIS DOCUMENT This document has a number of known errors that will be corrected in the next revision. Since it is not expected that users will need to use this interface frequently, priority was placed on other documents. You can find examples of how to actually use the API calls under the test_api directory. =head1 CREATING AN ADD/MODIFY HASH For the add and modify routines you will need to generate a list of attributes and values. You will do this by creating a HASH table. Each attribute in the hash contains associated values. These values can be one of three things. - SCALAR VALUE (ex. "Clayton Donley") - ARRAY REFERENCE (ex. ["Clayton Donley","Clay Donley"]) - HASH REFERENCE (ex. {"r",["Clayton Donley"]} note: the value inside the HASH REFERENCE must currently be an ARRAY REFERENCE. The key inside the HASH REFERENCE must be one of the following for a modify operation: - "a" for LDAP_MOD_ADD (Add these values to the attribute) - "r" for LDAP_MOD_REPLACE (Replace these values in the attribute) - "d" for LDAP_MOD_DELETE (Delete these values from the attribute) Additionally, in add and modify operations, you may specify "b" if the attributes you are adding are BINARY (ex. "rb" to replace binary). Currently, it is only possible to do one operation per add/modify operation, meaning you can't do something like: {"d",["Clayton"],"a",["Clay"]} <-- WRONG! Using any combination of the above value types, you can do things like: %ldap_modifications = ( "cn", "Clayton Donley", # Replace 'cn' values "givenname", ["Clayton","Clay"], # Replace 'givenname' values "mail", {"a",["donley\@cig.mcel.mot.com"], #Add 'mail' values "jpegphoto", {"rb",[$jpegphotodata]}, # Replace Binary jpegPhoto ); Then remember to call the add or modify operations with a REFERENCE to this HASH. =head1 API Methods The following are the available API methods for Mozilla::LDAP::API. Many of these items have bad examples and OUTPUT information. Other information should be correct. =item B(ld,msgid) DESCRIPTION: Abandon an asynchronous LDAP operation INPUT: ld - LDAP Session Handle msgid - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_abandon($ld,$msgid); =item B(ld,msgid,serverctrls,clientctrls) DESCRIPTION: Abandon an asynchronous LDAP operation w/ Controls INPUT: ld - LDAP Session Handle msgid - Integer serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_abandon_ext($ld,$msgid,$serverctrls,$clientctrls); =item B(ld,dn,attrs) DESCRIPTION: Asynchronously add a LDAP entry INPUT: ld - LDAP Session Handle dn - String attrs - LDAP Add/Modify Hash OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_add($ld,$dn,$attrs); =item B(ld,dn,attrs,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously add a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String attrs - LDAP Add/Modify Hash serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_add_ext($ld,$dn,$attrs,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,attrs,serverctrls,clientctrls) DESCRIPTION: Synchronously add a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String attrs - LDAP Add/Modify Hash serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_add_ext_s($ld,$dn,$attrs,$serverctrls,$clientctrls); =item B(ld,dn,attrs) DESCRIPTION: Synchronously add a LDAP entry INPUT: ld - LDAP Session Handle dn - String attrs - LDAP Add/Modify Hash OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_add_s($ld,$dn,$attrs); =item B(ber,freebuf) DESCRIPTION: Free a BER element pointer INPUT: ber - BER Element Pointer freebuf - Integer OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_ber_free($ber,$freebuf); =item B(ld,dn,passwd,authmethod) DESCRIPTION: Asynchronously bind to the LDAP server INPUT: ld - LDAP Session Handle dn - String passwd - String authmethod - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_bind($ld,$dn,$passwd,$authmethod); =item B(ld,dn,passwd,authmethod) DESCRIPTION: Synchronously bind to a LDAP server INPUT: ld - LDAP Session Handle dn - String passwd - String authmethod - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_bind_s($ld,$dn,$passwd,$authmethod); =item B(ld,dn,attr,value) DESCRIPTION: Asynchronously compare an attribute/value pair and an entry INPUT: ld - LDAP Session Handle dn - String attr - String value - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_compare($ld,$dn,$attr,$value); =item B(ld,dn,attr,bvalue,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously compare an attribute/value pair and an entry w/ Controls INPUT: ld - LDAP Session Handle dn - String attr - String bvalue - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_compare_ext($ld,$dn,$attr,$bvalue,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,attr,bvalue,serverctrls,clientctrls) DESCRIPTION: Synchronously compare an attribute/value pair to an entry w/ Controls INPUT: ld - LDAP Session Handle dn - String attr - String bvalue - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_compare_ext_s($ld,$dn,$attr,$bvalue,$serverctrls,$clientctrls); =item B(ld,dn,attr,value) DESCRIPTION: Synchronously compare an attribute/value pair to an entry INPUT: ld - LDAP Session Handle dn - String attr - String value - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_compare_s($ld,$dn,$attr,$value); =item B(ctrl) DESCRIPTION: Free a LDAP control pointer INPUT: ctrl - LDAP Control Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_control_free($ctrl); =item B(ctrls) DESCRIPTION: Count the number of LDAP controls in a LDAP Control List INPUT: ctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_controls_count($ctrls); =item B(ctrls) DESCRIPTION: Free a list of LDAP controls INPUT: ctrls - LDAP Control List Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_controls_free($ctrls); =item B(ld,result) DESCRIPTION: Count the number of LDAP entries returned INPUT: ld - LDAP Session Handle result - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $count = ldap_count_entries($ld,$result); =item B(ld,result) DESCRIPTION: Count the number of LDAP messages returned INPUT: ld - LDAP Session Handle result - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_count_messages($ld,$result); =item B(ld,result) DESCRIPTION: Count the number of LDAP references returned INPUT: ld - LDAP Session Handle result - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_count_references($ld,$result); =item B(buf,buflen,pattern,prefix,suffix,attr,value,valwords) DESCRIPTION: Create a LDAP search filter INPUT: buf - String buflen - Integer pattern - String prefix - String suffix - String attr - String value - String valwords - List Reference OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_create_filter($buf,$buflen,$pattern,$prefix,$suffix,$attr,$value,$valwords); =item B(ld,changetypes,changesonly,return_echg_ctrls,ctrl_iscritical,ctrlp) DESCRIPTION: Create a persistent search control INPUT: ld - LDAP Session Handle changetypes - Integer changesonly - Integer return_echg_ctrls - Integer ctrl_iscritical - Integer ctrlp - LDAP Control List Pointer OUTPUT: status - Integer ctrlp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_create_persistentsearch_control($ld,$changetypes,$changesonly,$return_echg_ctrls,$ctrl_iscritical,$ctrlp); =item B(ld,sortKeyList,ctrl_iscritical,ctrlp) DESCRIPTION: Create a LDAP sort control INPUT: ld - LDAP Session Handle sortKeyList - Sort Key Pointer ctrl_iscritical - Integer ctrlp - LDAP Control List Pointer OUTPUT: status - Integer ctrlp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_create_sort_control($ld,$sortKeyList,$ctrl_iscritical,$ctrlp); =item B(sortKeyList,string_rep) DESCRIPTION: Create a list of keys to be used by a sort control INPUT: sortKeyList - Sort Key Pointer string_rep - String OUTPUT: status - Integer sortKeyList - Sort Key Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_create_sort_keylist($sortKeyList,$string_rep); =item B(ld,ldvlistp,ctrlp) DESCRIPTION: Create a LDAP virtual list control INPUT: ld - LDAP Session Handle ctrlp - LDAP Control List Pointer OUTPUT: status - Integer ctrlp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_create_virtuallist_control($ld,$ldvlistp,$ctrlp); =item B(ld,dn) DESCRIPTION: Asynchronously delete a LDAP entry INPUT: ld - LDAP Session Handle dn - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_delete($ld,$dn); =item B(ld,dn,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously delete a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_delete_ext($ld,$dn,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,serverctrls,clientctrls) DESCRIPTION: Synchronously delete a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_delete_ext_s($ld,$dn,$serverctrls,$clientctrls); =item B(ld,dn) DESCRIPTION: Synchronously delete a LDAP entry INPUT: ld - LDAP Session Handle dn - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_delete_s($ld,$dn); =item B(dn) DESCRIPTION: Change a DN to a "Friendly" name INPUT: dn - String OUTPUT: status - String AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_dn2ufn($dn); =item B(err) DESCRIPTION: Return the string value of a LDAP error code INPUT: err - Integer OUTPUT: status - String AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_err2string($err); =item B(dn,notypes) DESCRIPTION: Split a given DN into its components. Setting 'notypes' to 1 returns the components without their type names. INPUT: dn - String notypes - Integer OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_explode_dn($dn,$notypes); =item B(dn,notypes) DESCRIPTION: Split a Relative DN into its components INPUT: dn - String notypes - Integer OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_explode_rdn($dn,$notypes); =item B(ld,requestoid,requestdata,serverctrls,clientctrls,msgidp) DESCRIPTION: Perform an asynchronous extended operation INPUT: ld - LDAP Session Handle requestoid - String requestdata - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_extended_operation($ld,$requestoid,$requestdata,$serverctrls,$clientctrls,$msgidp); =item B(ld,requestoid,requestdata,serverctrls,clientctrls,retoidp,retdatap) DESCRIPTION: Perform a synchronous extended operation INPUT: ld - LDAP Session Handle requestoid - String requestdata - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer retoidp - String OUTPUT: status - Integer retoidp - Return OID retdatap - Return Data AVAILABILITY: V3 EXAMPLE: $status = ldap_extended_operation_s($ld,$requestoid,$requestdata,$serverctrls,$clientctrls,$retoidp,$retdatap); =item B(ld,entry,ber) DESCRIPTION: Return the first attribute returned for a LDAP entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer ber - Ber Element Pointer OUTPUT: status - String ber - Ber Element Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_first_attribute($ld,$entry,$ber); =item B(ld,chain) DESCRIPTION: Return the first entry in a LDAP result chain INPUT: ld - LDAP Session Handle chain - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_first_entry($ld,$chain); =item B(ld,res) DESCRIPTION: Return the first message in a LDAP result INPUT: ld - LDAP Session Handle res - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_first_message($ld,$res); =item B(ld,res) DESCRIPTION: Return the first reference in a LDAP result INPUT: ld - LDAP Session Handle res - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_first_reference($ld,$res); =item B(map) DESCRIPTION: Free a LDAP friendly map pointer INPUT: map - Friendly Map Pointer OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_free_friendlymap($map); =item B(sortKeyList) DESCRIPTION: Free a LDAP sort key pointer INPUT: sortKeyList - Sort Key Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_free_sort_keylist($sortKeyList); =item B(ludp) DESCRIPTION: Free a LDAP URL description hash reference INPUT: ludp - URL Description Hash Reference OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_free_urldesc($ludp); =item B(filename,name,map) DESCRIPTION: Create a LDAP friendly name map INPUT: filename - String name - String map - Friendly Map Pointer OUTPUT: status - String AVAILABILITY: V3 EXAMPLE: $status = ldap_friendly_name($filename,$name,$map); =item B(ld,entry) DESCRIPTION: Return the distinguished name for an entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer OUTPUT: status - String AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_get_dn($ld,$entry); =item B(ld,entry,serverctrlsp) DESCRIPTION: Return the controls for a LDAP entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer serverctrlsp - LDAP Control List Pointer OUTPUT: status - Integer serverctrlsp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_get_entry_controls($ld,$entry,$serverctrlsp); =item B(lfdp) DESCRIPTION: Free a LDAP filter INPUT: lfdp - LDAP Filter Description Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_getfilter_free($lfdp); =item B(lfdp,tagpat,value) DESCRIPTION: Get the first generated filter INPUT: lfdp - LDAP Filter Description Pointer tagpat - String OUTPUT: status - LDAP Filter Information Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_getfirstfilter($lfdp,$tagpat,$value); =item B(ld,entry,target,type) DESCRIPTION: Get values for an entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer target - String type - String OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_get_lang_values($ld,$entry,$target,$type); =item B(ld,entry,target,type) DESCRIPTION: Get binary values for an entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer target - String type - String OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_get_lang_values_len($ld,$entry,$target,$type); =item B(ld,m,s) DESCRIPTION: INPUT: ld - LDAP Session Handle m - String Reference (or undef) s - String Reference (or undef) OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_get_lderrno($ld,\$m,\$s); =item B(lfdp) DESCRIPTION: Get the next generated LDAP filter INPUT: lfdp - LDAP Filter Information Pointer OUTPUT: status - LDAP Filter Information Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_getnextfilter($lfdp); =item B(ld,option,optdata) DESCRIPTION: Get an option for a LDAP session INPUT: ld - LDAP Session Handle option - Integer optdata - Integer OUTPUT: status - Integer optdata - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_get_option($ld,$option,$optdata); =item B(ld,entry,target) DESCRIPTION: Get the values for a LDAP entry and attribute INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer target - String OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_get_values($ld,$entry,$target); =item B(ld,entry,target) DESCRIPTION: Get the binary values for a LDAP entry and attribute INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer target - String OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_get_values_len($ld,$entry,$target); =item B(host,port) DESCRIPTION: Initialize a LDAP session INPUT: host - String port - Integer OUTPUT: status - LDAP Session Handle AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_init($host,$port); =item B(fname) DESCRIPTION: Initialize the LDAP filter generation routines to a filename INPUT: fname - Filename String OUTPUT: status - LDAP Filter Description Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_init_getfilter($fname); =item B(buf,buflen) DESCRIPTION: Initialize the LDAP filter generation routines to a buffer INPUT: buf - String buflen - Integer OUTPUT: status - LDAP Filter Description Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_init_getfilter_buf($buf,$buflen); =item B(url) DESCRIPTION: Return 1 if an the argument is a valid LDAP URL INPUT: url - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_is_ldap_url($url); =item B(cache) DESCRIPTION: Destroy a memory cache INPUT: cache - LDAP Memory Cache Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_memcache_destroy($cache); =item B(cache,dn,scope) DESCRIPTION: Flush a specific DN from the memory cache INPUT: cache - LDAP Memory Cache Pointer dn - String scope - Integer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_memcache_flush($cache,$dn,$scope); =item B(ld,cachep) DESCRIPTION: Get the memory cache for a LDAP session INPUT: ld - LDAP Session Handle cachep - LDAP Memory Cache Pointer OUTPUT: status - Integer cachep - LDAP Memory Cache Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_memcache_get($ld,$cachep); =item B(ttl,size,baseDNs,cachep) DESCRIPTION: Initialize a LDAP memory cache INPUT: ttl - Integer size - Integer baseDNs - List Reference cachep - LDAP Memory Cache Pointer OUTPUT: status - Integer cachep - LDAP Memory Cache Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_memcache_init($ttl,$size,$baseDNs,$cachep); =item B(ld,cache) DESCRIPTION: Set the LDAP memory cache for the session INPUT: ld - LDAP Session Handle cache - LDAP Memory Cache Pointer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_memcache_set($ld,$cache); =item B(cache) DESCRIPTION: Update the specified memory cache INPUT: cache - LDAP Memory Cache Pointer OUTPUT: status - NONE AVAILABILITY: V3 EXAMPLE: $status = ldap_memcache_update($cache); =item B(p) DESCRIPTION: Free memory allocated by the LDAP C API INPUT: p - Pointer OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_memfree($p); =item B(ld,dn,mods) DESCRIPTION: Asynchronously modify a LDAP entry INPUT: ld - LDAP Session Handle dn - String mods - LDAP Add/Modify Hash OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modify($ld,$dn,$mods); =item B(ld,dn,mods,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously modify a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String mods - LDAP Add/Modify Hash serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_modify_ext($ld,$dn,$mods,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,mods,serverctrls,clientctrls) DESCRIPTION: Synchronously modify a LDAP entry w/ Controls INPUT: ld - LDAP Session Handle dn - String mods - LDAP Add/Modify Hash serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_modify_ext_s($ld,$dn,$mods,$serverctrls,$clientctrls); =item B(ld,dn,mods) DESCRIPTION: Synchronously modify a LDAP entry INPUT: ld - LDAP Session Handle dn - String mods - LDAP Add/Modify Hash OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modify_s($ld,$dn,$mods); =item B(ld,dn,newrdn) DESCRIPTION: Asynchronously modify the relative distinguished name of an entry INPUT: ld - LDAP Session Handle dn - String newrdn - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modrdn($ld,$dn,$newrdn); =item B(ld,dn,newrdn) DESCRIPTION: Synchronously modify the relative distinguished name of an entry INPUT: ld - LDAP Session Handle dn - String newrdn - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modrdn_s($ld,$dn,$newrdn); =item B(ld,dn,newrdn,deleteoldrdn) DESCRIPTION: Asynchronously modify the relative distinguished name of an entry. INPUT: ld - LDAP Session Handle dn - String newrdn - String deleteoldrdn - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modrdn2($ld,$dn,$newrdn,$deleteoldrdn); =item B(ld,dn,newrdn,deleteoldrdn) DESCRIPTION: Synchronously modify the relative distinguished name of an entry. INPUT: ld - LDAP Session Handle dn - String newrdn - String deleteoldrdn - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_modrdn2_s($ld,$dn,$newrdn,$deleteoldrdn); =item B(lm) DESCRIPTION: Free memory allocated by a LDAP Message INPUT: lm - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_msgfree($lm); =item B(lm) DESCRIPTION: Get the message id number from a LDAP message INPUT: lm - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_msgid($lm); =item B(lm) DESCRIPTION: Get the message type of a LDAP message INPUT: lm - LDAP Message Pointer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_msgtype($lm); =item B(ld,chain,attr) DESCRIPTION: Sort entries by multiple keys INPUT: ld - LDAP Session Handle chain - LDAP Message Pointer attr - List Reference OUTPUT: status - Integer chain - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_multisort_entries($ld,$chain,$attr); =item B(ld,entry,ber) DESCRIPTION: Get the next attribute for a LDAP entry INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer ber - Ber Element Pointer OUTPUT: status - String ber - BER Element Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_next_attribute($ld,$entry,$ber); =item B(ld,entry) DESCRIPTION: Get the next entry in the result chain INPUT: ld - LDAP Session Handle entry - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_next_entry($ld,$entry); =item B(ld,msg) DESCRIPTION: Get the next message in the result chain INPUT: ld - LDAP Session Handle msg - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_next_message($ld,$msg); =item B(ld,ref) DESCRIPTION: Get the next reference in the result chain INPUT: ld - LDAP Session Handle ref - LDAP Message Pointer OUTPUT: status - LDAP Message Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_next_reference($ld,$ref); =item B(ld,ctrls,chgtypep,prevdnp,chgnumpresentp,chgnump) DESCRIPTION: Parse a LDAP entry change control INPUT: ld - LDAP Session Handle ctrls - LDAP Control List Pointer chgtypep - Integer prevdnp - String chgnumpresentp - Integer chgnump - Integer OUTPUT: status - Integer chgtypep - Integer prevdnp - String chgnumpresentp - Integer chgnump - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_entrychange_control($ld,$ctrls,$chgtypep,$prevdnp,$chgnumpresentp,$chgnump); =item B(ld,res,retoidp,retdatap,freeit) DESCRIPTION: Parse a LDAP extended result INPUT: ld - LDAP Session Handle res - LDAP Message Pointer retoidp - String freeit - Integer OUTPUT: status - Integer retoidp - String retdatap - Binary List Reference AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_extended_result($ld,$res,$retoidp,$retdatap,$freeit); =item B(ld,ref,referalsp,serverctrlsp,freeit) DESCRIPTION: Parse a LDAP Reference INPUT: ld - LDAP Session Handle ref - LDAP Message Pointer referalsp - List Reference serverctrlsp - LDAP Control List Pointer freeit - Integer OUTPUT: status - Integer referalsp - List Reference serverctrlsp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_reference($ld,$ref,$referalsp,$serverctrlsp,$freeit); =item B(ld,res,errcodep,matcheddnp,errmsgp,referralsp,serverctrlsp,freeit) DESCRIPTION: Parse a LDAP result INPUT: ld - LDAP Session Handle res - LDAP Message Pointer errcodep - Integer matcheddnp - String errmsgp - String referralsp - List Reference serverctrlsp - LDAP Control List Pointer freeit - Integer OUTPUT: status - Integer errcodep - Integer matcheddnp - String errmsgp - String referralsp - List Reference serverctrlsp - LDAP Control List Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_result($ld,$res,$errcodep,$matcheddnp,$errmsgp,$referralsp,$serverctrlsp,$freeit); =item B(ld,res,servercredp,freeit) DESCRIPTION: Parse the results of an SASL bind operation INPUT: ld - LDAP Session Handle res - LDAP Message Pointer freeit - Integer OUTPUT: status - Integer servercredp - AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_sasl_bind_result($ld,$res,$servercredp,$freeit); =item B(ld,ctrls,result,attribute) DESCRIPTION: Parse a LDAP sort control INPUT: ld - LDAP Session Handle ctrls - LDAP Control List Pointer result - LDAP Message Pointer attribute - String OUTPUT: status - Integer result - LDAP Message Pointer attribute - String AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_sort_control($ld,$ctrls,$result,$attribute); =item B(ld,ctrls,target_posp,list_sizep,errcodep) DESCRIPTION: Parse a LDAP virtual list control INPUT: ld - LDAP Session Handle ctrls - LDAP Control List Pointer target_posp - Integer list_sizep - Integer errcodep - Integer OUTPUT: status - Integer target_posp - Integer list_sizep - Integer errcodep - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_parse_virtuallist_control($ld,$ctrls,$target_posp,$list_sizep,$errcodep); =item B(ld,s) DESCRIPTION: Print a LDAP error message INPUT: ld - LDAP Session Handle s - String OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_perror($ld,$s); =item B(ld,dn,newrdn,newparent,deleteoldrdn,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously rename a LDAP entry INPUT: ld - LDAP Session Handle dn - String newrdn - String newparent - String deleteoldrdn - Integer serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_rename($ld,$dn,$newrdn,$newparent,$deleteoldrdn,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,newrdn,newparent,deleteoldrdn,serverctrls,clientctrls) DESCRIPTION: Synchronously rename a LDAP entry INPUT: ld - LDAP Session Handle dn - String newrdn - String newparent - String deleteoldrdn - Integer serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_rename_s($ld,$dn,$newrdn,$newparent,$deleteoldrdn,$serverctrls,$clientctrls); =item B(ld,msgid,all,timeout,result) DESCRIPTION: Get the result for an asynchronous LDAP operation INPUT: ld - LDAP Session Handle msgid - Integer all - Integer timeout - Time in Seconds result - LDAP Message Pointer OUTPUT: status - Integer result - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_result($ld,$msgid,$all,$timeout,$result); =item B(ld,r,freeit) DESCRIPTION: Get the error number for a given result INPUT: ld - LDAP Session Handle r - LDAP Message Pointer freeit - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_result2error($ld,$r,$freeit); =item B(ld,dn,mechanism,cred,serverctrls,clientctrls,msgidp) DESCRIPTION: Asynchronously bind to the LDAP server using a SASL mechanism INPUT: ld - LDAP Session Handle dn - String mechanism - String cred - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_sasl_bind($ld,$dn,$mechanism,$cred,$serverctrls,$clientctrls,$msgidp); =item B(ld,dn,mechanism,cred,serverctrls,clientctrls,servercredp) DESCRIPTION: Synchronously bind to a LDAP server using a SASL mechanism INPUT: ld - LDAP Session Handle dn - String mechanism - String cred - Binary String serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer OUTPUT: status - Integer servercredp - AVAILABILITY: V3 EXAMPLE: $status = ldap_sasl_bind_s($ld,$dn,$mechanism,$cred,$serverctrls,$clientctrls,$servercredp); =item B(ld,base,scope,filter,attrs,attrsonly) DESCRIPTION: Asynchronously search the LDAP server INPUT: ld - LDAP Session Handle base - String scope - Integer filter - String attrs - List Reference attrsonly - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_search($ld,$base,$scope,$filter,$attrs,$attrsonly); =item B(ld,base,scope,filter,attrs,attrsonly,serverctrls,clientctrls,timeoutp,sizelimit,msgidp) DESCRIPTION: Asynchronously search the LDAP server w/ Controls INPUT: ld - LDAP Session Handle base - String scope - Integer filter - String attrs - List Reference attrsonly - Integer serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer timeoutp - Time in Seconds sizelimit - Integer msgidp - Integer OUTPUT: status - Integer msgidp - Integer AVAILABILITY: V3 EXAMPLE: $status = ldap_search_ext($ld,$base,$scope,$filter,$attrs,$attrsonly,$serverctrls,$clientctrls,$timeoutp,$sizelimit,$msgidp); =item B(ld,base,scope,filter,attrs,attrsonly,serverctrls,clientctrls,timeoutp,sizelimit,res) DESCRIPTION: Synchronously search the LDAP server w/ Controls INPUT: ld - LDAP Session Handle base - String scope - Integer filter - String attrs - List Reference attrsonly - Integer serverctrls - LDAP Control List Pointer clientctrls - LDAP Control List Pointer timeoutp - Time in Seconds sizelimit - Integer res - LDAP Message Pointer OUTPUT: status - Integer res - LDAP Message Pointer AVAILABILITY: V3 EXAMPLE: $status = ldap_search_ext_s($ld,$base,$scope,$filter,$attrs,$attrsonly,$serverctrls,$clientctrls,$timeoutp,$sizelimit,$res); =item B(ld,base,scope,filter,attrs,attrsonly,res) DESCRIPTION: Synchronously search the LDAP server INPUT: ld - LDAP Session Handle base - String scope - Integer filter - String attrs - List Reference attrsonly - Integer res - LDAP Message Pointer OUTPUT: status - Integer res - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_search_s($ld,$base,$scope,$filter,$attrs,$attrsonly,$res); =item B(ld,base,scope,filter,attrs,attrsonly,timeout,res) DESCRIPTION: Synchronously search the LDAP server w/ Timeout INPUT: ld - LDAP Session Handle base - String scope - Integer filter - String attrs - List Reference attrsonly - Integer timeout - Time in Seconds res - LDAP Message Pointer OUTPUT: status - Integer res - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_search_st($ld,$base,$scope,$filter,$attrs,$attrsonly,$timeout,$res); =item B(lfdp,prefix,suffix) DESCRIPTION: Add a prefix and suffix for filter generation INPUT: lfdp - LDAP Filter Description Pointer prefix - String suffix - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_set_filter_additions($lfdp,$prefix,$suffix); =item B(ld,e,m,s) DESCRIPTION: Set the LDAP error structure INPUT: ld - LDAP Session Handle e - Integer m - String s - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_set_lderrno($ld,$e,$m,$s); =item B(ld,option,optdata) DESCRIPTION: Set a LDAP session option INPUT: ld - LDAP Session Handle option - Integer optdata - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_set_option($ld,$option,$optdata); =item B(ld,rebindproc) DESCRIPTION: Set the LDAP rebind process INPUT: ld - LDAP Session Handle OUTPUT: status - NONE AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_set_rebind_proc($ld,$rebindproc); =item B(ld,who,passwd) DESCRIPTION: Asynchronously bind to the LDAP server using simple authentication INPUT: ld - LDAP Session Handle who - String passwd - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_simple_bind($ld,$who,$passwd); =item B(ld,who,passwd) DESCRIPTION: Synchronously bind to the LDAP server using simple authentication INPUT: ld - LDAP Session Handle who - String passwd - String OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_simple_bind_s($ld,$who,$passwd); =item B(ld,chain,attr) DESCRIPTION: Sort the results of a LDAP search INPUT: ld - LDAP Session Handle chain - LDAP Message Pointer attr - String OUTPUT: status - Integer chain - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_sort_entries($ld,$chain,$attr); =item B(ld) DESCRIPTION: Asynchronously unbind from the LDAP server INPUT: ld - LDAP Session Handle OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_unbind($ld); =item B(ld) DESCRIPTION: Synchronously unbind from a LDAP server INPUT: ld - LDAP Session Handle OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_unbind_s($ld); =item B(url) DESCRIPTION: Parse a LDAP URL, returning a HASH of its components INPUT: url - String OUTPUT: status - AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_url_parse($url); =item B(ld,url,attrsonly) DESCRIPTION: Asynchronously search using a LDAP URL INPUT: ld - LDAP Session Handle url - String attrsonly - Integer OUTPUT: status - Integer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_url_search($ld,$url,$attrsonly); =item B(ld,url,attrsonly,res) DESCRIPTION: Synchronously search using a LDAP URL INPUT: ld - LDAP Session Handle url - String attrsonly - Integer res - LDAP Message Pointer OUTPUT: status - Integer res - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_url_search_s($ld,$url,$attrsonly,$res); =item B(ld,url,attrsonly,timeout,res) DESCRIPTION: Synchronously search using a LDAP URL w/ timeout INPUT: ld - LDAP Session Handle url - String attrsonly - Integer timeout - Time in Seconds res - LDAP Message Pointer OUTPUT: status - Integer res - LDAP Message Pointer AVAILABILITY: V2/V3 EXAMPLE: $status = ldap_url_search_st($ld,$url,$attrsonly,$timeout,$res); =item B(ld,shared) DESCRIPTION: Install NSPR I/O, threading, and DNS functions so they can be used by the LDAP connection (ld). If 'ld' is NULL, the functions are installed as the default functions for all new LDAP * handles). INPUT: ld - LDAP Session Handle shared - True if the LDAP * handle is used in an MT context OUTPUT: status - Integer AVAILABILITY: V3 =head1 CREDITS Most of the Perl API module was written by Clayton Donley to interface with C API routines from Netscape Communications Corp., Inc. =head1 BUGS Documentation needs much work. LDAPv3 calls not tested or supported in this version. NT can not use Perl Rebind processes, must use 'ldap_set_default_rebindproc'. Possible memory leak in ldap_search* is being investigated. =head1 SEE ALSO L, L, and L =cut perl-mozldap-1.5.3/Makefile.PL.rpm0000555000076400007640000000642210634204213015341 0ustar richrich############################################################################# # $Id: Makefile.PL.rpm,v 1.1.2.3 2007/06/14 09:21:15 gerv%gerv.net Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # The Makefile "source". # This has been heavily modified to simply use pkg-config # to get the components necessary to build. require 5.005; use ExtUtils::MakeMaker; use ExtUtils::Liblist; use Config; use Carp; # name of package to use for pkg-config $ldappkgname = $ENV{"LDAPPKGNAME"} || "mozldap6"; print "\nPerLDAP - Perl 5 Module for LDAP\n"; print "================================\n"; $cflags = `pkg-config --cflags $ldappkgname`; chomp($cflags); print "Using CFLAGS = $cflags\n"; print "================================\n"; $libs = `pkg-config --libs $ldappkgname`; chomp($libs); print "Using LIBS = $libs\n"; # # Ok, let's do it! # print "\n######### before WriteMakefile #############\n"; WriteMakefile( 'ABSTRACT' => 'Perl methods for LDAP C API calls', 'AUTHOR' => 'Leif Hedstrom ', 'NAME' => 'Mozilla::LDAP::API', 'DISTNAME' => 'PerLDAP', 'VERSION_FROM' => 'API.pm', 'INC' => $cflags, 'LIBS' => [$libs], 'MYEXTLIB' => $my_extlib, 'DEFINE' => "-DUSE_SSL -DPRLDAP", 'XSOPT' => "-nolinenumbers", @extras ); print "\n######### after WriteMakefile #############\n"; # # Generate a "make HTML" target # sub MY::postamble { ' .SUFFIXES: .pm .html .PHONY: html .pm.html: pod2html --netscape $< > $@ html: Entry.html Conn.html Utils.html API.html LDIF.html $(FIRST_MAKEFILE) @rm -f pod2html-itemcache pod2html-dircache ' } perl-mozldap-1.5.3/RELEASE0000444000076400007640000001055011426102657013600 0ustar richrich############################################################################# # # # PerLDAP Release Notes # # # ############################################################################# VERSION 1.5.3 - Aug 2010 ======================== This is an update release with the following goals: - Allow PerLDAP to use the OpenLDAP client libraries behind the scenes. - Avoid using deprecated functions in the underlying LDAP client library. VERSION 1.5.2 - Jul 2007 ======================== Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=389731 PerLDAP crashes when a bad URL is passed VERSION 1.5.1 - May 2007 ======================== This version is the officially tri-licensed version. All code is licensed under the MPL/GPL/LGPL tri-license, as all of the other Mozilla components. All code was either granted permission by the copyright holder, or was rewritten in a clean-room implementation. VERSION 1.5 - Feb 2006 ====================== This is an update release, with a few goals: - Support for latest Mozilla and Sun C-SDK (v5.x) - Now defaults to LDAP v3 protocol, but you can downgrade to v2 easily - Fully support Perl 5.005 and later - Added "hash" style prototypes to all class methods that takes more than one argument Many, many thanks to Rich Megginson for taking charge of the (broken) build and configuration process. New functionality ----------------- Conn.pm: * setVersion() - Set the LDAP protocol version * getVersion() - Get the current LDAP protocol in use * installNSPR() - Make the connection use NSPR I/O etc. * setNSPRTimeout() - Set the connection timeout, in ms API.xs: * Added support for prldap_install_routines(). VERSION 1.4 - AUGUST 18, 1999 ============================= This is primarily a bug fix release, however there are 5 new methods introduced as well. Brief descriptions follow in this document. To get full examples and a larger summary, see the PerLDAP Programmer's Guide. New Methods Added ----------------- Entry.pm: * getValues() - returns the array of values. * move() - move one attribute to another, and delete the original. * copy() - copy one attribute to another. Conn.pm: * browse() - makes it easy to browse an entry. * compare() - compare an attribute value against a DN/entry without having to do the search. Bug Fixes and other changes --------------------------- Entry.pm: * addDNValue() - fixed wrong index for norm. * matchValue() - fixed missing normalization in half of case statement. * setValue() - remove _delete_ flag if set, fix for saving state. * STORE - fixed not ignoring the internal instance variables properly. * Fixed numerous bugs for large attribute sets. * Fixed bug 4368 ("exists vs. EXISTS"). * Fixed several loop bugs. * Removed all _self_obj_ references, it's obsolete in this version. * We support each() and keys() now on the Entry object, to loop through all attribute names (types). Conn.pm: * close() - fixed memory leak. * modifyRDN() - fixed problem where we weren't updating the appropriate DN in the self object. * Fixed bug 3342 (problems adding entries with binary data). * getErrorCode()/getErrorString() - return LDAP_SUCCESS if no LDAP connection handle. * add() - fixed code to handle hash array as docs indicate. * update() - optimization for "replace" vs "add/delete", we try to use whatever LDAPMod is most efficient. LDIF.pm: * Complete rewrite, by John Kristian . API.xs: * Fixed memory allocation problems, replacing all memory management routines. This solves all known issues with ActiveState Perl. * More safety checks around calls to *_free(). Miscellaneous ------------- * Various other optimizations on tests and such. * Fixed most (all?) known memory leaks. * Fixed a lot of problems with Makefile.PL, adding some new targets (like "make html"). Add a skeleton to "make test". * Fixed numerous small bugs, as reported to Mozilla. * We produce less warnings now, and try to "use strict" when appropriate. * We have a new versioning scheme, conforming to standard Perl. We'll change this again when Perl's new versioning system is in place (allowing versions like 1.2.3). perl-mozldap-1.5.3/Conn.pm0000444000076400007640000016234011426075705014040 0ustar richrich############################################################################# # $Id: Conn.pm,v 1.24.2.18 2010/08/03 20:27:49 nkinder%redhat.com Exp $ # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is PerLDAP. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 2001 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Clayton Donley # Leif Hedstrom # Michelle Hedstrom # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** # DESCRIPTION # This is the main object class for connecting to an LDAP server, # and perform searches and updates. It depends on the ::Entry # object class, which is the data type returned from a search # operation for instance. require 5.005; package Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils 1.5 (); use Mozilla::LDAP::API 1.5 qw(/.+/); use Mozilla::LDAP::Entry 1.5 (); use strict; use vars qw($VERSION); $VERSION = "1.5"; ############################################################################# # Creator, create and initialize a new LDAP object ("connection"). We support # either providing all parameters as a hash array, or as individual # arguments. # sub new { my $class = shift; my $self = {}; if (ref $_[$[] eq "HASH") { my $hash = shift; $self->{"host"} = $hash->{"host"} if defined($hash->{"host"}); $self->{"port"} = $hash->{"port"} if defined($hash->{"port"}); $self->{"binddn"} = $hash->{"bind"} if defined($hash->{"bind"}); $self->{"bindpasswd"} = $hash->{"pswd"} if defined($hash->{"pswd"}); $self->{"bindpasswd"} = $hash->{"password"} if defined($hash->{"password"}); $self->{"certdb"} = $hash->{"cert"} if defined($hash->{"cert"}); $self->{"certdb"} = $hash->{"certificate"} if defined($hash->{"certificate"}); $self->{"version"} = $hash->{"vers"} || $hash->{"version"} || LDAP_VERSION3; $self->{"usenspr"} = 1 if (defined($hash->{"nspr"}) && $hash->{"nspr"}); $self->{"callback"} = $hash->{"callback"} if defined($hash->{"callback"}); $self->{"certname"} = $hash->{"certname"} if defined($hash->{"certname"}); $self->{"keypwd"} = $hash->{"keypwd"} if defined($hash->{"keypwd"}); $self->{"starttls"} = $hash->{"starttls"} if defined($hash->{"starttls"}); $self->{"entryclass"} = $hash->{"entryclass"} || 'Mozilla::LDAP::Entry'; if (defined($hash->{"timeout"})) { die "Can only use the timeout option with NSPR enabled connections" unless defined($self->{"usenspr"}); $self->{"timeout"} = $hash->{"timeout"}; } } else { my ($host, $port, $binddn, $bindpasswd, $certdb, $authmeth, $version, $nspr) = @_; $self->{"host"} = $host if defined($host); $self->{"port"} = $port if defined($port); $self->{"binddn"} = $binddn if defined($binddn); $self->{"bindpasswd"} = $bindpasswd if defined($bindpasswd); $self->{"certdb"} = $certdb if defined($certdb); $self->{"version"} = $version || LDAP_VERSION3; $self->{"usenspr"} = 1 if (defined($nspr) && $nspr); $self->{"entryclass"} = "Mozilla::LDAP::Entry"; } # Anonymous bind is the default... $self->{"binddn"} = "" unless defined($self->{"binddn"}); $self->{"bindpasswd"} = "" unless defined($self->{"bindpasswd"}); # Find an appropriate default port number if not specified. if (!defined($self->{"port"}) || ($self->{"port"} eq "")) { if (defined($self->{"certdb"}) && ($self->{"certdb"} ne "")) { $self->{"port"} = LDAPS_PORT; } else { $self->{"port"} = LDAP_PORT; } } bless $self, $class; return unless $self->init(); return $self; } ############################################################################# # Destructor, makes sure we close any open LDAP connections. # sub DESTROY { my $self = shift; return unless defined($self->{"ld"}); $self->close(); } ############################################################################# # Initialize a normal connection. This seems silly, why not just merge # this back into the creator method (new)... # sub init { my $self = shift; my ($ret, $ld); return 0 unless (defined($self->{"host"})); return 0 unless (defined($self->{"port"})); # Set protocol version to 3. ldap_set_option(undef, LDAP_OPT_PROTOCOL_VERSION, LDAP_VERSION3); if (defined($self->{"certdb"}) && ($self->{"certdb"} ne "")) { #use SSL $ret = ldapssl_client_init($self->{"certdb"}, 0); return 0 if ($ret < 0); if ($self->{"starttls"}) { $ld = ldap_init($self->{"host"}, $self->{"port"}); return 0 unless $ld; $ret = prldap_install_routines($ld, 0); return 0 unless ($ret == LDAP_SUCCESS); } else { # regular ssl $ld = ldapssl_init($self->{"host"}, $self->{"port"}, 1); } if ($self->{"certname"}) { # enable clientauth $ret = ldapssl_enable_clientauth($ld, 0, $self->{"keypwd"}, $self->{"certname"}); return 0 unless ($ret == LDAP_SUCCESS); } if ($self->{"starttls"}) { $ret = ldap_start_tls_s($ld, 0, 0); return 0 unless ($ret == LDAP_SUCCESS); } } else { $ld = ldap_init($self->{"host"}, $self->{"port"}); } return 0 unless $ld; $self->{"ld"} = $ld; if (defined($self->{"usenspr"})) { if (!$self->{"starttls"}) { # already did this above for starttls $ret = prldap_install_routines($self->{"ld"}, 0); return 0 unless ($ret == LDAP_SUCCESS); } if (defined($self->{"timeout"})) { $ret = prldap_set_session_option($self->{"ld"}, 0, PRLDAP_OPT_IO_MAX_TIMEOUT, $self->{"timeout"}); return 0 unless ($ret == LDAP_SUCCESS); } } $self->setVersion($self->{"version"}); if ($self->{"certname"}) # client auth - must use sasl bind { my $rc = ldap_sasl_bind_s($ld, "", "EXTERNAL", 0, 0, 0, 0); if ($rc != LDAP_SUCCESS) { my ($dn, $errmsg); $rc = $self->getErrorCode(\$dn, \$errmsg); print "Error: $rc - ", $self->getErrorString(), ": $errmsg for certname ", $self->{"certname"}, "\n"; } return (($rc == LDAP_SUCCESS) ? 1 : 0); } elsif (defined($self->{"callback"})) { my ($result, $ret); my $id = ldap_simple_bind($ld, $self->{"binddn"}, $self->{"bindpasswd"}); $ret = ldap_result($ld, $id, 0, 1, $result); return 0 unless ($ret == LDAP_RES_BIND); # The callback must return 1 or 0 (success or failure on the login). $ret = $self->{"callback"}($self, $result); ldap_msgfree($result); return $ret; } else { $ret = ldap_simple_bind_s($ld, $self->{"binddn"}, $self->{"bindpasswd"}); return (($ret == LDAP_SUCCESS) ? 1 : 0); } } ############################################################################# # Create a new, empty, Entry object, properly tied into the Entry class. # This is mostly for convenience, you could directly do the "tie" yourself # in your code. # sub newEntry { my ($self, $dn) = @_; my $entry; if (ref $self) { $entry = $self->{"entryclass"}->new(); } else { $entry = Mozilla::LDAP::Entry->new(); } $entry->setDN($dn) if (defined($dn) && $dn ne ""); return $entry; } ############################################################################# # Checks if a string is a properly formed LDAP URL. # sub isURL { my ($self, $url) = @_; return ldap_is_ldap_url($url); } ############################################################################# # Return the actual low level LD connection structure, which is needed if # you want to call any of the API functions yourself... # sub getLD { my $self = shift; return $self->{"ld"} if defined($self->{"ld"}); } ############################################################################# # Return the actual the current result message, don't use this unless you # really have to... # sub getRes { my $self = shift; return $self->{"ldres"} if defined($self->{"ldres"}); } ############################################################################# # Return the Error code from the last LDAP api function call. The last two # optional arguments are pointers to strings, and will be set to the # match string and extra error string if appropriate. # sub getErrorCode { my $self = shift; my ($match, $msg); return LDAP_SUCCESS unless defined($self->{"ld"}); if (ref $_[$[] eq "HASH") { my $hash = shift; $match = $hash->{"match"} if defined($hash->{"match"}); $msg = $hash->{"mesg"} if defined($hash->{"mesg"}); } else { ($match, $msg) = @_; } return $self->{"searchres"} if defined($self->{"searchres"}); return ldap_get_lderrno($self->{"ld"}, $match, $msg); } *getError = \*getErrorCode; ############################################################################# # Return the Error string from the last LDAP api function call. # sub getErrorString { my $self = shift; my $err; return LDAP_SUCCESS unless defined($self->{"ld"}); if (defined($self->{"searchres"})) { $err = $self->{"searchres"}; } else { $err = ldap_get_lderrno($self->{"ld"}, undef, undef); } return ldap_err2string($err); } ############################################################################# # Print the last error code... # sub printError { my ($self, $str) = @_; return unless defined($self->{"ld"}); $str = "LDAP error:" unless defined($str); print "$str ", $self->getErrorString(), "\n"; } ############################################################################# # Normal LDAP search. Note that this will actually perform LDAP URL searches # if the filter string looks like a proper URL. # sub search { my $self = shift; my ($basedn, $scope, $filter, $attrsonly, $attrs, $res, $sortattrs, $cmp); if (ref $_[$[] eq "HASH") { my $hash = shift; $basedn = $hash->{"base"} || ""; $scope = Mozilla::LDAP::Utils::str2Scope($hash->{"scope"}); $filter = $hash->{"filter"} || "(objectclass=*)"; $attrsonly = $hash->{"attrsonly"} || undef; $attrs = $hash->{"attrs"} || undef; $sortattrs = $hash->{"sortattrs"} || undef; $cmp = $hash->{"cmp"} || undef; } else { my @rest; ($basedn, $scope, $filter, $attrsonly, @rest) = @_; $scope = Mozilla::LDAP::Utils::str2Scope($scope); if (ref $rest[0] eq "ARRAY") { $attrs = $rest[0]; } elsif (scalar(@rest) > 0) { $attrs = \@rest; } else { $attrs = undef; $sortattrs = undef; $cmp = undef; } } $filter = "(objectclass=*)" if ($filter =~ /^ALL$/i); if (defined($self->{"ldres"})) { ldap_msgfree($self->{"ldres"}); undef $self->{"ldres"}; } $self->{"ldres"} = 0; # This gets rid of the annoying warning if (defined($self->{"searchres"})) { undef $self->{"searchres"}; } if (ldap_is_ldap_url($filter)) { $res = ldap_url_search_s($self->{"ld"}, $filter, $attrsonly, $self->{"ldres"}); if ($res == LDAP_SUCCESS || $res == LDAP_TIMELIMIT_EXCEEDED || $res == LDAP_SIZELIMIT_EXCEEDED ||$res == LDAP_ADMINLIMIT_EXCEEDED) { $self->{"searchres"} = $res unless $res == LDAP_SUCCESS; $self->{"ldfe"} = 1; if (defined($sortattrs)) { if (scalar(@{$sortattrs}) > 1) { ldap_multisort_entries($self->{"ld"}, $self->{"ldres"}, $sortattrs, $cmp); } else { ldap_sort_entries($self->{"ld"}, $self->{"ldres"}, $sortattrs->[0], $cmp); } } return $self->nextEntry(); } } else { $res = ldap_search_s($self->{"ld"}, $basedn, $scope, $filter, defined($attrs) ? $attrs : 0, defined($attrsonly) ? $attrsonly : 0, $self->{"ldres"}); if ($res == LDAP_SUCCESS || $res == LDAP_TIMELIMIT_EXCEEDED || $res == LDAP_SIZELIMIT_EXCEEDED ||$res == LDAP_ADMINLIMIT_EXCEEDED) { $self->{"searchres"} = $res unless $res == LDAP_SUCCESS; $self->{"ldfe"} = 1; if (defined($sortattrs)) { if (scalar(@{$sortattrs}) > 1) { ldap_multisort_entries($self->{"ld"}, $self->{"ldres"}, $sortattrs, $cmp); } else { ldap_sort_entries($self->{"ld"}, $self->{"ldres"}, $sortattrs->[0], $cmp); } } return $self->nextEntry(); } } undef $self->{"ldres"}; return ""; } ############################################################################# # URL search, optimized for LDAP URL searches. # sub searchURL { my $self = shift; my ($url, $attrsonly, $res); if (ref $_[$[] eq "HASH") { my $hash = shift; $url = $hash->{"url"}; $attrsonly = $hash->{"attrsonly"} || 0; } else { ($url, $attrsonly) = @_; } if (defined($self->{"ldres"})) { ldap_msgfree($self->{"ldres"}); undef $self->{"ldres"}; } $self->{"ldres"} = 0; # This avoids the annoying warnings if (defined($self->{"searchres"})) { undef $self->{"searchres"}; } $res = ldap_url_search_s($self->{"ld"}, $url, defined($attrsonly) ? $attrsonly : 0, $self->{"ldres"}); if ($res == LDAP_SUCCESS || $res == LDAP_TIMELIMIT_EXCEEDED || $res == LDAP_SIZELIMIT_EXCEEDED ||$res == LDAP_ADMINLIMIT_EXCEEDED) { $self->{"searchres"} = $res unless $res == LDAP_SUCCESS; $self->{"ldfe"} = 1; return $self->nextEntry(); } undef $self->{"ldres"}; return ""; } ############################################################################# # Browse an LDAP entry, very much like the regular search, except we set # some defaults (like scope=BASE, filter=(objectclass=*) and so on). Note # that this method does not support the attributesOnly flag. # sub browse { my $self = shift; my ($basedn, @attrs, $scope, $attrsonly); if (ref $_[$[] eq "HASH") { my $hash = shift; $basedn = $hash->{"base"} || ""; $attrsonly = $hash->{"attrsonly"} || 0; @attrs = @{$hash->{"attrs"}} if defined($hash->{"attrs"}); } else { ($basedn, @attrs) = @_; $attrsonly = 0; } $scope = Mozilla::LDAP::Utils::str2Scope("BASE"); return $self->search($basedn, $scope, "(objectclass=*)", $attrsonly, @attrs); } ############################################################################# # Compare an attribute value against a DN in the server (without having to # do a search first). # sub compare { my $self = shift; my ($dn, $attr, $value); if (ref $_[$[] eq "HASH") { my $hash = shift; $dn = $hash->{"dn"} if defined($hash->{"dn"}); $attr = $hash->{"attr"} if defined($hash->{"attr"}); $value = $hash->{"value"} if defined($hash->{"value"}); } else { ($dn, $attr, $value) = @_; } return ldap_compare_s($self->{"ld"}, $dn, $attr, $value) == LDAP_COMPARE_TRUE; } ############################################################################# # Get an entry from the search, either the first entry, or the next entry, # depending on the call order. # sub nextEntry { my ($self) = shift; my (%entry, @ocorder, @vals); my ($attr, $lcattr, $obj, $ldentry, $berv, $dn, $count); my $ber = \$berv; # I use the object directly, to avoid setting the "change" flags $obj = tie %entry, $self->{"entryclass"}; $self->{"dn"} = ""; if ($self->{"ldfe"} == 1) { return "" unless defined($self->{"ldres"}); $self->{"ldfe"} = 0; $ldentry = ldap_first_entry($self->{"ld"}, $self->{"ldres"}); $self->{"ldentry"} = $ldentry; } else { return "" unless defined($self->{"ldentry"}); $ldentry = ldap_next_entry($self->{"ld"}, $self->{"ldentry"}); $self->{"ldentry"} = $ldentry; } if (! $ldentry) { if (defined($self->{"ldres"})) { ldap_msgfree($self->{"ldres"}); undef $self->{"ldres"}; } return ""; } $dn = ldap_get_dn($self->{"ld"}, $self->{"ldentry"}); $obj->{"_oc_numattr_"} = 0; $obj->{"_oc_keyidx_"} = 0; $obj->{"dn"} = $dn; $self->{"dn"} = $dn; $attr = ldap_first_attribute($self->{"ld"}, $self->{"ldentry"}, $ber); return (bless \%entry, $self->{"entryclass"}) unless $attr; $lcattr = lc $attr; @vals = ldap_get_values_len($self->{"ld"}, $self->{"ldentry"}, $attr); $obj->{$lcattr} = [@vals]; push(@ocorder, $lcattr); $count = 1; while ($attr = ldap_next_attribute($self->{"ld"}, $self->{"ldentry"}, $ber)) { $lcattr = lc $attr; @vals = ldap_get_values_len($self->{"ld"}, $self->{"ldentry"}, $attr); $obj->{$lcattr} = [@vals]; push(@ocorder, $lcattr); $count++; } $obj->{"_oc_order_"} = \@ocorder; $obj->{"_oc_numattr_"} = $count; ldap_ber_free($ber, 0) if $ber; return bless \%entry, $self->{"entryclass"}; } # This is deprecated... *entry = \*nextEntry; ############################################################################# # Close the connection to the LDAP server. # sub close { my $self = shift; ldap_unbind_s($self->{"ld"}) if defined($self->{"ld"}); if (defined($self->{"ldres"})) { ldap_msgfree($self->{"ldres"}); undef $self->{"ldres"}; } undef $self->{"ld"} if defined($self->{"ld"}); return 1; } ############################################################################# # Delete an object. # sub delete { my ($self, $id) = @_; my $ret = LDAP_SUCCESS; my $dn = $id; if (UNIVERSAL::isa($id, 'Mozilla::LDAP::Entry')) { $dn = $id->getDN(); } else { $dn = $self->{"dn"} unless (defined($dn) && ($dn ne "")); } $dn = Mozilla::LDAP::Utils::normalizeDN($dn); $ret = ldap_delete_s($self->{"ld"}, $dn) if ($dn ne ""); return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # Add an object. # sub add { my ($self, $entry) = @_; my %ent; my ($key, $val); my ($ret, $gotcha) = (1, 0); if (UNIVERSAL::isa($entry, 'Mozilla::LDAP::Entry')) { foreach $key (@{$entry->{"_oc_order_"}}) { next if (($key eq "dn") || ($key =~ /^_.+_$/)); next if $entry->{"_${key}_deleted_"}; $ent{$key} = { "ab" => $entry->{$key} }; $gotcha++; $entry->attrClean($key); } } elsif (ref $entry eq 'HASH') { foreach $key (keys(%{$entry})) { next if (($key eq "dn") || ($key =~ /^_.+_$/)); $ent{$key} = { "ab" => $entry->{$key} }; $gotcha++; } } else { # We can't handle this, so let's just return. return 0; } if ($gotcha > 0 ) { $ret = ldap_add_s($self->{"ld"}, $entry->{"dn"}, \%ent); return (($ret == LDAP_SUCCESS) ? 1 : 0); } return 0; } ############################################################################# # Modify the RDN, and update the entry accordingly. Note that the last # two arguments (DN and "delete") are optional. The last (optional) argument # is a flag, which if set to TRUE (the default), will cause the corresponding # attribute value to be removed from the entry. # sub modifyRDN { my $self = shift; my ($rdn, $dn, $del, @vals); my $ret = LDAP_SUCCESS; if (ref $_[$[] eq "HASH") { my $hash = shift; $rdn = $hash->{"rdn"} if defined($hash->{"rdn"}); $dn = $hash->{"dn"} if defined($hash->{"dn"}); $del = $hash->{"delete"} if defined($hash->{"delete"}); } else { ($rdn, $dn, $del) = @_; } $del = 1 unless (defined($del) && ($del ne "")); $dn = $self->{"dn"} unless (defined($dn) && ($dn ne "")); @vals = ldap_explode_dn($dn, 0); if (lc($vals[$[]) ne lc($rdn)) { $ret = ldap_modrdn2_s($self->{"ld"}, $dn, $rdn, $del); if ($ret == LDAP_SUCCESS) { shift(@vals); unshift(@vals, ($rdn)); $self->{"dn"} = join(@vals); } } return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # Update an object. NOTE: I'd like to clean up my change tracking tags here, # so that we can call update() again with the same entry. # sub update { my ($self, $entry) = @_; my ($vals, @add, @remove, %mod, %new); my ($key, $val); my $ret = LDAP_SUCCESS; local $_; foreach $key (@{$entry->{"_oc_order_"}}) { next if (($key eq "dn") || ($key =~ /^_.+_$/)); $vals = defined($entry->{$key}) ? $entry->{$key} : [ ]; if (defined($entry->{"_${key}_deleted_"})) { $mod{$key} = { "db", [] }; undef @{$entry->{$key}}; } elsif (defined($entry->{"_${key}_modified_"})) { @remove = (); undef %new; grep(($new{$_} = 1), @{$vals}); if (defined($entry->{"_${key}_save_"})) { foreach (@{$entry->{"_${key}_save_"}}) { if (! $new{$_}) { push(@remove, $_); } $new{$_} = 0; } } @add = (); foreach (@{$vals}) { push(@add, $_) if ($new{$_} == 1); } if ((scalar(@remove) + scalar(@add)) < scalar(@{$vals})) { $mod{$key}{"db"} = [ @remove ] if ($#remove >= $[); $mod{$key}{"ab"} = [ @add ] if ($#add >= $[); } else { $mod{$key}{"rb"} = [ @{$vals} ]; } } $entry->attrClean($key); } # This is here for debug purposes only... if ($main::LDAP_DEBUG) { my $op; foreach $key (keys(%mod)) { print "Working on $key\n"; foreach $op (keys %{$mod{$key}}) { print "\tDoing operation: $op\n"; foreach $val (@{$mod{$key}{$op}}) { print "\t\t$val\n"; } } } } $ret = ldap_modify_s($self->{"ld"}, $entry->{"dn"}, \%mod) if %mod; return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # Set the rebind procedure. We also provide a neat default rebind procedure, # which takes three arguments (DN, password, and the auth method). This is an # extension to the LDAP SDK, which I think should be there. It was also # needed to get this to work on Win/NT... # sub setRebindProc { my ($self, $proc) = @_; # Should we try to reinitialize the connection? die "No LDAP connection" unless defined($self->{"ld"}); ldap_set_rebind_proc($self->{"ld"}, $proc); } sub setDefaultRebindProc { my ($self, $dn, $pswd, $auth) = @_; $auth = LDAP_AUTH_SIMPLE unless defined($auth); die "No LDAP connection" unless defined($self->{"ld"}); ldap_set_default_rebind_proc($self->{"ld"}, $dn, $pswd, $auth); } ############################################################################# # Do a simple authentication, so that we can rebind as another user. # sub simpleAuth { my ($self, $dn, $pswd) = @_; my $ret; $ret = ldap_simple_bind_s($self->{"ld"}, $dn, $pswd); return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # Set arbitrary option (this is flaky, can only handle "int" options ...) # sub setOption { my $self = shift; my ($option, $value, $ret); if (ref $_[$[] eq "HASH") { my $hash = shift; $option = $hash->{"option"}; $value = $hash->{"value"}; } else { ($option, $value) = @_; } $ret = ldap_set_option($self->{"ld"}, $option, $value); return (($ret == LDAP_SUCCESS) ? 1 : 0); } sub getOption { my ($self, $option) = @_; my ($ret, $value); $ret = ldap_get_option($self->{"ld"}, $option, $value); return (($ret == LDAP_SUCCESS) ? $value : undef); } ############################################################################# # Set/get LDAP protocol version # sub setVersion { my ($self, $ver) = @_; my $ret = LDAP_SUCCESS; if ($ver eq "1") { $self->{"version"} = LDAP_VERSION1; } elsif ($ver eq "2") { $self->{"version"} = LDAP_VERSION2; } else { $self->{"version"} = LDAP_VERSION3; } if ($self->{"version"} ne LDAP_VERSION2) { $ret = ldap_set_option($self->{"ld"}, LDAP_OPT_PROTOCOL_VERSION, $self->{"version"}); return (($ret == LDAP_SUCCESS) ? 1 : 0); } return 1; } sub getVersion { return $_[0]->{"version"}; } ############################################################################# # Set sizelimit, convenience wrapper. # sub setSizelimit { my ($self, $limit) = @_; my $ret; $ret = $self->setOption(LDAP_OPT_SIZELIMIT, $limit); return (($ret == LDAP_SUCCESS) ? 1 : 0); } sub getSizelimit { my $self = shift; my ($ret, $limit); $ret = ldap_get_option($self->{"ld"}, LDAP_OPT_SIZELIMIT, $limit); return (($ret == LDAP_SUCCESS) ? $limit : undef); } ############################################################################# # Install NSPR I/O, threading, and DNS functions so they will be used by # the LDAP * handle (ld) sub installNSPR { my $arg = shift; my $shared = shift || 0; my $ret; if (ref $arg) { $arg->close(); $arg->{"usenspr"} = 1; $arg->init(); } else { $ret = prldap_install_routines(0, $shared); } return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # Set the NSPR I/O timeout (in milliseconds). This can only be used after # you have installed the NSPR layer (using installNSPR). # sub setNSPRTimeout { my $arg = shift; my $timeout = shift || 0; my $ret; if (ref $arg) { return 0 unless defined($arg->{"usenspr"}); $ret = prldap_set_session_option($arg->{"ld"}, 0, PRLDAP_OPT_IO_MAX_TIMEOUT, $timeout); } else { $ret = prldap_set_session_option(0, 0, PRLDAP_OPT_IO_MAX_TIMEOUT, $timeout); } return (($ret == LDAP_SUCCESS) ? 1 : 0); } ############################################################################# # SearchIter allows PerLDAP to support asynchronous searching - that is, to # support having a Conn doing two or more simultaneous searches. Objects # of the class SearchIter should not be created directly, but should only # be created by calling the Conn->async_search method (see below). The # nextEntry method is used to iterate over the search results and works # just like the Conn method of the same name. If search result # processing is aborted before all of the search results have been # returned, the abandon method should be called to close the connection # to allow the server and client to reclaim resources. # { package SearchIter; import Mozilla::LDAP::API qw(:api :ssl :apiv3 :constant); # Direct access to C API # arguments to new() are the Conn object used to invoke the search # and the msgid returned from the ldap_search* call sub new { my $that = shift; my ($conn, $msgid, $timeout) = @_; my $class = ref($that) || $that; if (!$timeout) { ldap_get_option($conn->getLD(), LDAP_OPT_TIMELIMIT(), \$timeout); if (!$timeout) { $timeout = 30; # 30 seconds } } my $self = { conn => $conn, msgid => $msgid, timeout => $timeout }; bless $self, $class; return $self; } # just returns the error code from the underlying Conn sub getErrorCode { my $self = shift; return $self->{conn}->getErrorCode(); } # this function returns the next Entry sub nextEntry { my $self = shift; my $timeout = shift; my ($rc, $ld, $res); my (%entry, $obj, $berv); my $ber = \$berv; return "" unless $self->{msgid}; if ($timeout) { $self->{timeout} = $timeout; # change timeout } else { $timeout = $self->{timeout}; # use pre configured one } # I use the object directly, to avoid setting the "change" flags $obj = tie %entry, 'Mozilla::LDAP::Entry'; $ld = $self->{conn}->getLD(); $rc = ldap_result($ld, $self->{msgid}, 0, $timeout, $res); if ($rc == -1) { # error print "Error getting ldap result for msgid ", $self->{msgid}, "\n"; undef $self->{msgid}; } elsif ($rc == 0) { # timeout print "Timeout getting ldap result for msgid ", $self->{msgid}, "\n"; } elsif ($rc == LDAP_RES_SEARCH_RESULT()) { # done - get result # print "Search done, got result for msgid ", $self->{msgid}, "\n" if $verbose; undef $self->{msgid}; } elsif ($rc == LDAP_RES_SEARCH_REFERENCE()) { # referral? print "Got a referral as a search result\n"; } else { # regular entry search result my $dn = ldap_get_dn($ld, $res); $self->{dn} = $dn; # keep last DN that was read $self->{res} = $res; # keep last res that was read # print "Got $dn as next entry for msgid ", $self->{msgid}, "\n" if $verbose; $obj->{"_oc_numattr_"} = 0; $obj->{"_oc_keyidx_"} = 0; $obj->{"dn"} = $dn; my $attr = ldap_first_attribute($ld, $res, $ber); return (bless \%entry, 'Mozilla::LDAP::Entry') unless $attr; my $lcattr = lc $attr; my @vals = ldap_get_values_len($ld, $res, $attr); $obj->{$lcattr} = [@vals]; my @ocorder; push(@ocorder, $lcattr); my $count = 1; while ($attr = ldap_next_attribute($ld, $res, $ber)) { $lcattr = lc $attr; @vals = ldap_get_values_len($ld, $res, $attr); $obj->{$lcattr} = [@vals]; push(@ocorder, $lcattr); $count++; } $obj->{"_oc_order_"} = \@ocorder; $obj->{"_oc_numattr_"} = $count; ldap_ber_free($ber, 0) if $ber; ldap_msgfree($res) if $res; return bless \%entry, 'Mozilla::LDAP::Entry'; } ldap_msgfree($res) if $res; return ""; # search failed } # use this method when it is desired to abort search result processing # before all of the results have been returned from the server sub abandon { my $self = shift; ldap_abandon($self->{conn}->getLD(), $self->{msgid}); undef $self->{msgid}; } } ############################################################################# # This starts an asynchronous search. It returns a SearchIter # use the SearchIter->nextEntry method to get the next entry # you can have multiple async searches going at once, so you can do # nested searches, for example # use SearchIter->getErrorCode() to see if the search had errors # sub async_search { my $self = shift; my ($basedn, $scope, $filter, $attrsonly, $attrs, $msgid, $iter); if (ref $_[$[] eq "HASH") { my $hash = shift; $basedn = $hash->{"base"} || ""; $scope = Mozilla::LDAP::Utils::str2Scope($hash->{"scope"}); $filter = $hash->{"filter"} || "(objectclass=*)"; $attrsonly = $hash->{"attrsonly"} || undef; $attrs = $hash->{"attrs"} || undef; } else { my @rest; ($basedn, $scope, $filter, $attrsonly, @rest) = @_; $scope = Mozilla::LDAP::Utils::str2Scope($scope); if (ref($rest[0]) eq "ARRAY") { $attrs = $rest[0]; } elsif (scalar(@rest) > 0) { $attrs = \@rest; } else { $attrs = undef; } } $filter = "(objectclass=*)" if ($filter =~ /^ALL$/i); if (ldap_is_ldap_url($filter)) { $msgid = ldap_url_search($self->{"ld"}, $filter, $attrsonly); } else { $msgid = ldap_search($self->{"ld"}, $basedn, $scope, $filter, defined($attrs) ? $attrs : 0, defined($attrsonly) ? $attrsonly : 0) } $iter = new SearchIter($self, $msgid); return $iter; } ############################################################################# # Mandatory TRUE return value. # 1; ############################################################################# # POD documentation... # __END__ =head1 NAME Mozilla::LDAP::Conn - Object Oriented API for the LDAP SDK. =head1 SYNOPSIS use Mozilla::LDAP::Conn; use Mozilla::LDAP::Utils; =head1 ABSTRACT This package is the main API for using our Perl Object Oriented LDAP module. Even though it's certainly possible, and sometimes even necessary, to call the native LDAP C SDK functions, we strongly recommend you use these object classes. It's not required to use our Mozilla::LDAP::Utils.pm package, but it's convenient and good for portability if you use as much as you can from that package as well. This implies using the LdapConf package as well, even though you usually don't need to use it directly. You should read this document in combination with the Mozilla::LDAP::Entry document. Both modules depend on each other heavily. =head1 DESCRIPTION First, this is not ment to be a crash course in how LDAP works, if you have no experience with LDAP, I suggest you read some of the literature that's available out there. The LDAP Deployment Book from Netscape, or the LDAP C SDK documentation are good starting points. This object class basically tracks and manages the LDAP connection, it's current status, and the current search operation (if any). Every time you call the B method of an object instance, you'll reset it's internal state. It depends heavily on the ::Entry class, which are used to retrieve, modify and update a single entry. The B and B methods returns Mozilla::LDAP::Entry objects, or an appropriately subclass of it. You also have to instantiate (and modify) a new ::Entry object when you want to add new entries to an LDAP server. Alternatively, the add() method will also take a hash array as argument, to make it easy to create new LDAP entries. To assure that changes to an entry are updated properly, we strongly recommend you use the native methods of the ::Entry object class. Even though you can modify certain elements directly, it could cause changes not to be committed to the LDAP server. If there's something missing from the API, please let us know, or even fix it yourself. =head1 SOME PERLDAP/OO BASICS An entry consist of a DN, and a hash array of pointers to attribute values. Each attribute value (except the DN) is an array, but you have to remember the hash array in the entry stores pointers to the array, not the array. So, to access the first CN value of an entry, you'd do $cn = $entry->{cn}[0]; To set the CN attribute to a completely new array of values, you'd do $entry->{cn} = [ "Leif Hedstrom", "The Swede" ]; As long as you remember this, and try to use native Mozilla::LDAP::Entry methods, this package will take care of most the work. Once you master this, working with LDAP in Perl is surprisingly easy. We already mentioned DN, which stands for Distinguished Name. Every entry on an LDAP server must have a DN, and it's always guaranteed to be unique within your database. Some typical DNs are uid=leif,ou=people,o=netscape.com cn=gene-staff,ou=mailGroup,o=netscape.com dc=data,dc=netscape,dc=com There's also a term called RDN, which stands for Relative Distinguished Name. In the above examples, C, C and C are all RDNs. One particular property for a RDN is that they must be unique within it's sub-tree. Hence, there can only be one user with C within the C tree, there can never be a name conflict. =head1 CREATING A NEW OBJECT INSTANCE Before you can do anything with PerLDAP, you'll need to instantiate at least one Mozilla::LDAP::Conn object, and connect it to an LDAP server. As you probably guessed already, this is done with the B method: $conn = Mozilla::LDAP::Conn->new("ldap", "389", $bind, $pswd, $cert, $ver); die "Couldn't connect to LDAP server ldap" unless $conn; The arguments are: Host name, port number, and optionally a bind-DN, it's password, and a certificate. A recent addition is the LDAP protocol version, which is by default LDAP v3. If there is no bind-DN, the connection will be bound as the anonymous user. If the certificate file is specified, the connection will be over SSL, and you should then probably connect to port 636. You have to check that the object was created properly, and take proper actions if you couldn't get a connection. There's one convenient alternative call method to this function. Instead of providing each individual argument, you can provide one hash array (actually, a pointer to a hash). For example: %ld = Mozilla::LDAP::Utils::ldapArgs(); $conn = Mozilla::LDAP::Conn->new(\%ld); The components of the hash are: $ld->{"host"} $ld->{"port"} $ld->{"base"} $ld->{"bind"} $ld->{"pswd"} $ld->{"cert"} $ld->{"vers"} and (not used in the B method) $ld->{"scope"} New for PerLDAP v1.5 and later are the following: $ld->{"nspr"} $ld->{"timeout"} $ld->{"callback"} $ld->{"entryclass"} The B flag (1/0) indicates that we wish to use the NSPR layer for the LDAP connection. This obviously only works if PerLDAP has been compiled with NSPR support and libraries. The default is for NSPR to be disabled. For an NSPR enabled connection, you can also provide an optional timeout parameter, which will be used during the lifetime of the connection. This includes the initial setup and connection to the LDAP server. You can change this parameter later using the B method. During the bind process, you can provide a callback function to be called when the asynchronus bind has completed. The callback should take two arguments, a reference to the ::Conn object ("self") and a result structure as returned by the call to B. Finally, you can optionally specify what class the different methods should use when instantiating B result objects. The default is Mozilla::LDAP::Entry. Once a connection is established, the package will take care of the rest. If for some reason the connection is lost, the object should reconnect on it's own, automatically. [Note: This doesn't work now... ]. You can use the Mozilla::LDAP:Conn object for any number of operations, but since everything is currently done synchronously, you can only have one operation active at any single time. You can of course have multiple Mozilla::LDAP::Conn instanced active at the same time. =head1 PERFORMING LDAP SEARCHES We assume that you are familiar with the LDAP filter syntax already, all searches performed by this object class uses these filters. You should also be familiar with LDAP URLs, and LDAP object classes. There are some of the few things you actually must know about LDAP. Perhaps the simples filter is (uid=leif) This matches all entries with the UID set to "leif". Normally that would only match one entry, but there is no guarantee for that. To find everyone with the name "leif", you'd instead do (cn=*leif*) A more complicated search involves logic operators. To find all mail groups owned by "leif" (or actually his DN), you could do (&(objectclass=mailGroup)(owner=uid=leif,ou=people,o=netscape)) The I attribute is what's called a DN attribute, so to match on it we have to specify the entire DN in the filter above. We could of course also do a sub string "wild card" match, but it's less efficient, and requires indexes to perform reasonably well. Ok, now we are prepared to actually do a real search on the LDAP server: $base = "o=netscape.com"; $conn = Mozilla::LDAP::Conn->new("ldap", "389", "", ""); die "No LDAP connection" unless $conn; $entry = $conn->search($base, "subtree", "(uid=leif)"); if (! $entry) { # handle this event, no entries found, dude! } else { while ($entry) { $entry->printLDIF(); $entry = $conn->nextEntry(); } } This is in fact a poor mans implementation of the I command line utility. The B method returns an Mozilla::LDAP::Entry object (or derived subclass), which holds the first entry from the search, if any. To get the second and subsequent entries you call the B method, until there are no more entries. The B method is a convenient function, requesting the entry to print itself on STDOUT, in LDIF format. The arguments to the B methods are the I, the I of the search ("base", "one" or "sub"), and the actual LDAP I. The entry return contains the DN, and all attribute values. To access a specific attribute value, you just have to use the hash array: $cn = $entry->{cn}[0]; Since many LDAP attributes can have more than one value, value of the hash array is another array (or actually a pointer to an array). In many cases you can just assume the value is in the first slot (indexed by [0]), but for some attributes you have to support multiple values. To find out how many values a specific attribute has, you'd call the B method: $numVals = $entry->size("objectclass"); One caveat: Many LDAP attributes are case insensitive, but the methods in the Mozilla::LDAP::Entry package are not aware of this. Hence, if you compare values with case sensitivity, you can experience weird behavior. If you know an attribute is CIS (Case Insensitive), make sure you do case insensitive string comparisons. Unfortunately some methods in this package can't do this, and by default will do case sensitive comparisons. We are working on this, and in a future release some of the methods will handle this more gracefully. As an extension (for LDAP v3.0) we could also use schema discovery for handling this even better. There is an alternative search method, to use LDAP URLs instead of a filter string. This can be used to easily parse and process URLs, which is a compact way of storing a "link" to some specific LDAP information. To process such a search, you use the B method: $entry->searchURL("ldap:///o=netscape.com??sub?(uid=leif)"); As it turns out, the B method also supports LDAP URL searches. If the search filter looks like a proper URL, we will actually do an URL search instead. This is for backward compatibility, and for ease of use. To achieve better performance and use less memory, you can limit your search to only retrieve certain attributes. With the LDAP URLs you specify this as an optional parameter, and with the B method you add two more options, like $entry = $conn->search($base, "sub", $filter, 0, ("mail", "cn")); The last argument specifies an array of attributes to retrieve, the fewer the attributes, the faster the search will be. The second to last argument is a boolean value indicating if we should retrieve only the attribute names (and no values). In most cases you want this to be FALSE, to retrieve both the attribute names, and all their values. To do this with the B method, add a second argument, which should be 0 or 1. =head1 PERFORMING ASYNCHRONOUS SEARCHES Conn also supports an async_search method that takes the same arguments as the search method but returns an instance of SearchIter instead of Entry. As its name implies, the SearchIter is used to iterate through the search results. The nextEntry method works just like the nextEntry method of Conn. The abandon method should be called if search result processing is aborted before the last result is received, to allow the client and server to release resources. Example: $iter = $conn->async_search($base, $scope, $filter, ...); if ($rc = $iter->getResultCode()) { # process error condition } else { while (my $entry = $iter->nextEntry) { # process entry if (some abort condition) { $iter->abandon; last; } } } =head1 MODIFYING AND CREATING NEW LDAP ENTRIES Once you have an LDAP entry, either from a search, or created directly to get a new empty object, you are ready to modify it. If you are creating a new entry, the first thing to set it it's DN, like $entry = $conn->newEntry(); $entry->setDN("uid=leif,ou=people,o=netscape.com"); alternatively you can still use the B method on the Entry class, like $entry = Mozilla::LDAP::Entry->new(); You should not do this for an existing LDAP entry, changing the RDN (or DN) for such an entry must be done with B. To populate (or modify) some other attributes, we can do $entry->{objectclass} = [ "top", "person", "inetOrgPerson" ]; $entry->{cn} = [ "Leif Hedstrom" ]; $entry->{mail} = [ "leif@netscape.com" ]; Once you are done modifying your LDAP entry, call the B method from the Mozilla::LDAP::Conn object instance: $conn->update($entry); Or, if you are creating an entirely new LDAP entry, you must call the B method: $conn->add($entry); If all comes to worse, and you have to remove an entry again from the LDAP server, just call the B method, like $conn->delete($entry->getDN()); You can't use native Perl functions like push() and splice() on attribute values, since they won't update the ::Entry instance state properly. Instead use one of the methods provided by the Mozilla::LDAP::Entry object class, for instance $entry->addValue("cn", "The Swede"); $entry->removeValue("mailAlternateAddress", "leif@mcom.com"); $entry->remove("seeAlso"); These methods return a TRUE or FALSE value, depending on the outcome of the operation. If there was no value to remove, or a value already exists, we return FALSE, otherwise TRUE. To check if an attribute has a certain value, use the B method, like if ($entry->hasValue("mail", "leif@netscape.com")) { # Do something } There is a similar method, B, which takes a regular expression to match against, instead of the entire string. For more information this and other methods in the Entry class, see below. =head1 OBJECT CLASS METHODS We have already described the fundamentals of this class earlier. This is a summary of all available methods which you can use. Be careful not to use any undocumented features or heaviour, since the internals in this module is likely to change. =head2 Searching and updating entries =over 13 =item B Add a new entry to the LDAP server. Make sure you use the B method for the Mozilla::LDAP::Entry object, to create a proper entry. =item B Searches for an LDAP entry, but sets some default values to begin with, such as scope=BASE, filter=(objectclass=*) and so on. Much like B except for these defaults. Requires a DN value as an argument. An optional second argument is an array of which attributes to return from the entry. Note that this does not support the "attributesOnly" flag. $secondEntry = $conn->browse($entry->getDN()); =item B Close the LDAP connection, and clean up the object. If you don't call this directly, the destructor for the object instance will do the job for you. =item B Compares an attribute and value to a given DN without first doing a search. Requires three arguments: a DN, the attribute name, and the value of the attribute. Returns TRUE if the attribute/value compared ok. print "not" unless $conn->compare($entry->getDN(), "cn", "Big Swede"); print "ok"; =item B This will delete the current entry, or possibly an entry as specified with the optional argument. You can use this function to delete any entry you like, by passing it an explicit DN. If you don't pass it this argument, B defaults to delete the current entry, from the last call to B or B. I'd recommend doing a delete with the explicit DN, like $conn->delete($entry->getDN()); =item B This will rename the specified LDAP entry, by modifying it's RDN. For example, assuming you have a DN of uid=leif, ou=people, dc=netscape, dc=com and you wish to rename to uid=fiel, ou=people, dc=netscape, dc=com you'd do something like $rdn = "uid=fiel"; $conn->modifyRDN($rdn, $entry->getDN()); Note that this can only be done on the RDN, you could not change say C to be C in the example above. To do that, you have to add a new entry (a copy of the old one), and then remove the old entry. The last argument is a boolean (0 or 1), which indicates if the old RDN value should be removed from the entry. The default is TRUE ("1"). =item B This creates and initialized a new LDAP connection and object. The required arguments are host name, port number, bind DN and the bind password. An optional argument is a certificate (public key), which causes the LDAP connection to be established over an SSL channel. Currently we do not support Client Authentication, so you still have to use the simple authentication method (i.e. with a password). A typical usage could be something like %ld = Mozilla::LDAP::Utils::ldapArgs(); $conn = Mozilla::LDAP::Conn->new(\%ld); Also, remember that if you use SSL, the port is (usually) 636. =item B This will create an empty Mozilla::LDAP::Entry object, which is properly tied into the appropriate objectclass. Use this method instead of manually creating new Entry objects, or at least make sure that you use the "tie" function when creating the entry. This function takes no arguments, and returns a pointer to an ::Entry object. For instance $entry = $conn->newEntry(); or $entry = Mozilla::LDAP::Conn->newEntry(); =item B This method will return the next entry from the search result, and can therefore only be called after a succesful search has been initiated. If there are no more entries to retrieve, it returns nothing (empty string). =item B The B method is the main entry point into this module. It requires at least three arguments: The Base DN, the scope, and the search strings. Two more optional arguments can be given, the first specifies if only attribute names should be returned (TRUE or FALSE). The second argument is a list (array) of attributes to return. The last option is very important for performance. If you are only interested in say the "mail" and "mailHost" attributes, specifying this in the search will signficantly reduce the search time. An example of an efficient search is @attr = ("cn", "uid", "mail"); $filter = "(uid=*)"; $entry = $conn->search($base, $scope, $filter, 0, @attr); while ($entry) { # do something $entry = $conn->nextEntry(); } =item B This is almost identical to B, except this function takes only two arguments, an LDAP URL and an optional flag to specify if we only want the attribute names to be returned (and no values). This function isn't very useful, since the B method will actually honor properly formed LDAP URL's, and use it if appropriate. =item B This method will rebind the LDAP connection using new credentials (i.e. a new user-DN and password). To rebind "anonymously", just don't pass a DN and password, and it will default to binding as the unprivleged user. For example: $user = "leif"; $password = "secret"; $conn = Mozilla::LDAP::Conn->new($host, $port); # Anonymous bind die "Could't connect to LDAP server $host" unless $conn; $entry = $conn->search($base, $scope, "(uid=$user)", 0, (uid)); exit (-1) unless $entry; $ret = $conn->simpleAuth($entry->getDN(), $password); exit (-1) unless $ret; $ret = $conn->simpleAuth(); # Bind as anon again. =item B After modifying an Ldap::Entry entry (see below), use the B method to commit changes to the LDAP server. Only attributes that has been changed will be updated, assuming you have used the appropriate methods in the Entry object. For instance, do not use B or B to modify an entry, the B will not recognize such changes. To change the CN value for an entry, you could do $entry->{cn} = ["Leif Hedstrom"]; $conn->update($entry); =back =head2 Other methods =over 13 =item B Return the error code (numeric) from the last LDAP API function call. Remember that this can only be called I the successful creation of a new :Conn object instance. A typical usage could be if (! $opt_n) { $conn->modifyRDN($rdn, $entry->getDN()); $conn->printError() if $conn->getErrorCode(); } Which will report any error message as generated by the call to B. Some LDAP functions return extra error information, which can be retrieved like: $err = getErrorCode(\$matched, \$string); $matched will then contain the portion of the matched DN (if applicable to the error code), and $string will contain any additional error string returned by the LDAP server. =item B Very much like B, but return a string with a human readable error message. This can then be used to print a good error message on the console. =item B Return the (internal) LDAP* connection handle, which you can use (carefully) to call the native LDAP API functions. You shouldn't have to use this in most cases, unless of course our OO layer is seriously flawed. =item B Just like B, except it returns the internal LDAP return message structure. Again, use this very carefully, and be aware that this might break in future releases of PerLDAP. These two methods can be used to call some useful API functions, like $cld = $conn->getLD(); $res = $conn->getRes(); $count = Mozilla::LDAP::API::ldap_count_entries($cld, $res); =item B Returns TRUE or FALSE if the given argument is a properly formed URL. =item B Print the last error message on standard output. =item B Tell the LDAP SDK to call the provided Perl function when it has to follow referrals. The Perl function should return an array of three elements, the new Bind DN, password and authentication method. A typical usage is sub rebindProc { return ("uid=ldapadmin", "secret", LDAP_AUTH_SIMPLE); } $ld->setRebindProc(\&rebindProc); =item B This is very much like the previous function, except instead of specifying the function to use, you give it the DN, password and Auth method. Then we'll use a default rebind procedure (internal in C) to handle the rebind credentials. This was a solution for the Windows/NT problem/bugs we have with rebind procedures written in Perl. =item B Change the LDAP protocol version on the already initialized connection. The default is LDAP v3 (new for PerLDAP v1.5!), but you can downgrade the connection to LDAP v2 if necessary using this function. Example: $conn->setVersion(2); =item B Return the protocol version currently in used by the connection. =item B Set the sizelimit on a connection, to limit the maximum number of entries that we want to retrieve. For example: $conn->setSizelimit(10); =item B Get the current sizelimit on a connection (if any). =item B Set an (integer) LDAP option. =item B Get an (integer) LDAP option. =item B Install NSPR I/O, threading, and DNS functions so they will be used by 'ld'. Pass a non-zero value for the 'shared' parameter if you plan to use this LDAP * handle from more than one thread. This is highly unlikely since PerLDAP is asynchronous. =item B Set the TCP timeout value, in millisecond, for the NSPR enabled connection. It's an error to call this before calling installNSPR(), unless you created the new connection object with the B option. This method can also be invoked as a class method, and it will then apply to all new connections created. Like Mozilla::LDAP::Conn->installNSPR(1); Mozilla::LDAP::Conn->setNSPRTimeout(1000); =back =head1 EXAMPLES There are plenty of examples to look at, in the examples directory. We are adding more examples every day (almost). =head1 INSTALLATION Installing this package is part of the Makefile supplied in the package. See the installation procedures which are part of this package. =head1 AVAILABILITY This package can be retrieved from a number of places, including: http://www.mozilla.org/directory/ Your local CPAN server =head1 CREDITS Most of this code was developed by Leif Hedstrom, Netscape Communications Corporation. =head1 BUGS None. :) =head1 SEE ALSO L, L L and of course L. =cut perl-mozldap-1.5.3/PerLDAP.ppd0000444000076400007640000000056610267227170014477 0ustar richrich PerLDAP Perl methods for LDAP C API calls Leif Hedstrom <leif@ogre.com> perl-mozldap-1.5.3/MPL-1.1.txt0000444000076400007640000007422507005664140014272 0ustar richrich MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is ______________________________________. The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. Contributor(s): ______________________________________. Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the [___] License." [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] ---------------------------------------------------------------------- AMENDMENTS The Netscape Public License Version 1.1 ("NPL") consists of the Mozilla Public License Version 1.1 with the following Amendments, including Exhibit A-Netscape Public License. Files identified with "Exhibit A-Netscape Public License" are governed by the Netscape Public License Version 1.1. Additional Terms applicable to the Netscape Public License. I. Effect. These additional terms described in this Netscape Public License -- Amendments shall apply to the Mozilla Communicator client code and to all Covered Code under this License. II. "Netscape's Branded Code" means Covered Code that Netscape distributes and/or permits others to distribute under one or more trademark(s) which are controlled by Netscape but which are not licensed for use under this License. III. Netscape and logo. This License does not grant any rights to use the trademarks "Netscape", the "Netscape N and horizon" logo or the "Netscape lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript", "Smart Browsing" even if such marks are included in the Original Code or Modifications. IV. Inability to Comply Due to Contractual Obligation. Prior to licensing the Original Code under this License, Netscape has licensed third party code for use in Netscape's Branded Code. To the extent that Netscape is limited contractually from making such third party code available under this License, Netscape may choose to reintegrate such code into Covered Code without being required to distribute such code in Source Code form, even if such code would otherwise be considered "Modifications" under this License. V. Use of Modifications and Covered Code by Initial Developer. V.1. In General. The obligations of Section 3 apply to Netscape, except to the extent specified in this Amendment, Section V.2 and V.3. V.2. Other Products. Netscape may include Covered Code in products other than the Netscape's Branded Code which are released by Netscape during the two (2) years following the release date of the Original Code, without such additional products becoming subject to the terms of this License, and may license such additional products on different terms from those contained in this License. V.3. Alternative Licensing. Netscape may license the Source Code of Netscape's Branded Code, including Modifications incorporated therein, without such Netscape Branded Code becoming subject to the terms of this License, and may license such Netscape Branded Code on different terms from those contained in this License. VI. Litigation. Notwithstanding the limitations of Section 11 above, the provisions regarding litigation in Section 11(a), (b) and (c) of the License shall apply to all disputes relating to this License. EXHIBIT A-Netscape Public License. "The contents of this file are subject to the Netscape Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/NPL/ 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 Mozilla Communicator client code, released March 31, 1998. The Initial Developer of the Original Code is Netscape Communications Corporation. Portions created by Netscape are Copyright (C) 1998-1999 Netscape Communications Corporation. All Rights Reserved. Contributor(s): ______________________________________. Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License and not to allow others to use your version of this file under the NPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the NPL or the [___] License." perl-mozldap-1.5.3/META.yml0000444000076400007640000000044110321531051014027 0ustar richrich# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: PerLDAP version: 1.5 version_from: API.pm installdirs: site requires: distribution_type: module generated_by: ExtUtils::MakeMaker version 6.17 perl-mozldap-1.5.3/perl-Mozilla-LDAP.spec0000444000076400007640000001024711426102657016541 0ustar richrich%define nspr_name nspr %define nss_name nss %define mozldap_name mozldap Summary: LDAP Perl module that wraps the Mozilla C SDK Name: perl-Mozilla-LDAP Version: 1.5.3 Release: 1%{?dist} License: GPL/LGPL/MPL Group: Development/Libraries URL: http://www.mozilla.org/directory/perldap.html BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires: perl >= 2:5.8.0 BuildRequires: perl >= 2:5.8.0 BuildRequires: %{nspr_name}-devel >= 4.6 BuildRequires: %{nss_name}-devel >= 3.11 BuildRequires: %{mozldap_name}-devel >= 6.0 Source0: ftp://ftp.mozilla.org/pub/mozilla.org/directory/perldap/releases/1.5/perl-mozldap-%{version}.tar.gz Source1: ftp://ftp.mozilla.org/pub/mozilla.org/directory/perldap/releases/1.5/Makefile.PL.rpm %description %{summary}. %prep %setup -q -n perl-mozldap-%{version} # Filter unwanted Provides: cat << \EOF > %{name}-prov #!/bin/sh %{__perl_provides} $* |\ sed -e '/perl(Mozilla::LDAP::Entry)$/d' EOF %define __perl_provides %{_builddir}/perl-mozldap-%{version}/%{name}-prov chmod +x %{__perl_provides} # Filter unwanted Requires: cat << \EOF > %{name}-req #!/bin/sh %{__perl_requires} $* |\ sed -e '/perl(Mozilla::LDAP::Entry)/d' EOF %define __perl_requires %{_builddir}/perl-mozldap-%{version}/%{name}-req chmod +x %{__perl_requires} %build LDAPPKGNAME=%{mozldap_name} CFLAGS="$RPM_OPT_FLAGS" perl %{SOURCE1} PREFIX=$RPM_BUILD_ROOT%{_prefix} INSTALLDIRS=vendor < /dev/null make OPTIMIZE="$RPM_OPT_FLAGS" CFLAGS="$RPM_OPT_FLAGS" make test %install rm -rf $RPM_BUILD_ROOT eval `perl '-V:installarchlib'` %makeinstall # remove files we don't want to package rm -f `find $RPM_BUILD_ROOT -type f -name perllocal.pod -o -name .packlist` find $RPM_BUILD_ROOT -name API.bs -a -size 0 -exec rm -f {} \; # make sure shared lib is correct mode find $RPM_BUILD_ROOT -name API.so -exec chmod 755 {} \; # find and run the correct version of brp-compress if [ -x /usr/lib/rpm/brp-compress ] ; then /usr/lib/rpm/brp-compress elif [ -x %{_libdir}/rpm/brp-compress ] ; then %{_libdir}/rpm/brp-compress fi # make sure files refer to %{_prefix} instead of buildroot/%prefix find $RPM_BUILD_ROOT%{_prefix} -type f -print | \ sed "s@^$RPM_BUILD_ROOT@@g" > %{name}-%{version}-%{release}-filelist if [ "$(cat %{name}-%{version}-%{release}-filelist)X" = "X" ] ; then echo "ERROR: EMPTY FILE LIST" exit 1 fi %clean rm -rf $RPM_BUILD_ROOT %files -f %{name}-%{version}-%{release}-filelist %defattr(-,root,root,-) %doc CREDITS ChangeLog README MPL-1.1.txt %changelog * Tue Aug 3 2010 Nathan Kinder - 1.5.3-1 - avoid using deprecated functions in the underlying LDAP library. * Fri Jul 27 2007 Rich Megginson - 1.5.2-1 - Fix bugzilla 389731 - crash when a bad URL is passed * Wed Jun 20 2007 Rich Megginson - 1.5.1-1 - all files have been GPL/LGPL/MPL tri-licensed * Wed Jan 10 2007 Rich Megginson - 1.5-9 - remove only perl(Mozilla::LDAP::Entry) from Provides, leave in - perl(Mozilla::LDAP::Entry) = 1.5 * Wed Jan 10 2007 Rich Megginson - 1.5-8 - add perl_requires filter for the Entry module - add the MPL-1.1.txt file to the DOCs * Wed Jan 10 2007 Rich Megginson - 1.5-7 - Incorporate comments from Fedora Extras review - https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=219869 - Remove all Requires except perl - use autogenerated ones - Remove ExclusiveArch - Remove files that don't need to be packaged - add full URL to sources - set API.so to mode 755 * Tue Oct 17 2006 Rich Megginson - 1.5-6 - look for brp-compress first in /usr/lib then _libdir * Tue Oct 17 2006 Rich Megginson - 1.5-5 - there is no TODO file; use custom Makefile.PL * Mon Oct 16 2006 Rich Megginson - 1.5-4 - use pkg-config --variable=xxx instead of --cflags e.g. * Mon Oct 16 2006 Rich Megginson - 1.5-3 - this is not a noarch package * Mon Oct 16 2006 Rich Megginson - 1.5-2 - Use new mozldap6, dirsec versions of nspr, nss * Tue Feb 7 2006 Rich Megginson - 1.5-1 - Based on the perl-LDAP.spec file perl-mozldap-1.5.3/MANIFEST0000444000076400007640000000114610267227170013727 0ustar richrichChangeLog API.pm API.xs MANIFEST Makefile.PL PerLDAP.ppd constant.h typemap Entry.pm Conn.pm LDIF.pm Utils.pm README INSTALL CREDITS RELEASE MPL-1.1.txt test_api/search.pl test_api/write.pl test_api/api.pl t/conn.pl t/entry.pl t/ChangeLog t/api.t t/conn.t t/entry.t t/ldif.t t/utils.t examples/ChangeLog examples/lfinger.pl examples/qsearch.pl examples/monitor.pl examples/ldappasswd.pl examples/rmentry.pl examples/tabdump.pl examples/modattr.pl examples/rename.pl examples/psoftsync.pl examples/changes2ldif.pl examples/rand_mods.pl META.yml Module meta-data (added by MakeMaker) perl-mozldap-1.5.3/LDIF.pm0000444000076400007640000011555210634204213013650 0ustar richrich############################################################################# # $Id: LDIF.pm,v 1.8.2.4 2007/06/14 09:21:15 gerv%gerv.net Exp $ # # # ***** BEGIN LICENSE BLOCK ***** # Version: MPL 1.1/GPL 2.0/LGPL 2.1 # # The contents of this file are subject to the Mozilla Public License Version # 1.1 (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # http://www.mozilla.org/MPL/ # # Software distributed under the License is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License # for the specific language governing rights and limitations under the # License. # # The Original Code is LDIF.pm, released # March, 1999. # # The Initial Developer of the Original Code is # Netscape Communications Corporation. # Portions created by the Initial Developer are Copyright (C) 1999 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Leif Hedstrom # John M. Kristian # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), # in which case the provisions of the GPL or the LGPL are applicable instead # of those above. If you wish to allow use of your version of this file only # under the terms of either the GPL or the LGPL, and not to allow others to # use your version of this file under the terms of the MPL, indicate your # decision by deleting the provisions above and replace them with the notice # and other provisions required by the GPL or the LGPL. If you do not delete # the provisions above, a recipient may use your version of this file under # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** package Mozilla::LDAP::LDIF; use vars qw($VERSION); $VERSION = "0.09"; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(); @EXPORT_OK = qw(get_LDIF put_LDIF unpack_LDIF pack_LDIF set_Entry references next_attribute sort_attributes sort_entry delist_values enlist_values condense LDIF_get_DN get_DN read_v0 read_file_name read_v1 read_file_URL read_file_URL_or_name); use strict; my $base64message = "Can't use MIME::Base64! Your version of perl does not have the module MIME::Base64. LDIF files may be have base64 encoded values. An attribute followed by two colons (::) instead of a single colon (:) indicates the attribute value is base64 encoded binary. Please install the MIME::Base64 module from CPAN or use the perl CPAN module to install this module. The url is: http://www.perl.com/CPAN/modules/by-module/MIME/ If you have trouble, try simply putting Base64.pm in a subdirectory named MIME, in one of the directories named in @INC (site_perl is a good choice)."; BEGIN { eval 'use MIME::Base64'; if ($@) { my $complaint = $@; if ($^W) { warn $complaint; warn $base64message; } else { warn $complaint; die $base64message; } } } use vars qw($_uselessUseOf); $_uselessUseOf = "Useless use of ".__PACKAGE__."::%s in scalar or void context"; sub _to_LDIF_records # \@_ $funcname $wantarray # Return the parameter, if the array is a single record; # otherwise return a list of references to records, which # are either copied from the given array or the result of # the getLDIFrecords() method of objects in the given array. { my ($argv, $funcname, $wantarray) = @_; return ($argv) if not ref $argv->[$[]; my @records; foreach my $arg (@$argv) { my $type = ref $arg; if ($type) { push @records, (($type eq "ARRAY") ? $arg : $arg->getLDIFrecords()); } } if (defined ($funcname) and @records > 1 and not $wantarray and $^W) { _carpf ($_uselessUseOf, $funcname); } return @records; } sub _continue_lines { my ($sep, $max_line, $from) = @_; # If $from contains $sep bytes, they will be lost; that is, an LDIF # parser will not reconstruct them from the output. But the remaining # characters are preserved, and the output is fairly legible, with an # LDIF continuation line break in place of each $sep in $from. # This is useful for a person trying to read the value. my ($into) = ""; my $qsep = quotemeta $sep; foreach my $line (split /$qsep/, $from, -1) { $line = " $line" if length $into; # continuation of previous line if (defined $max_line) { while ($max_line < length $line) { my $chunk; ($chunk, $line) = unpack ("a${max_line}a*", $line); $into .= "$chunk$sep"; $line = " $line"; } } $into .= "$line$sep"; } return $into; } ############################################################################# # unpack/pack use vars qw($SEP); $SEP = "\015\012|\012"; # LDIF standard ( CR LF | LF ) # Input lines may be separated by $SEP or $/. # The latter is not standard, but useful. # Maintainers note: the order of alternatives is significant; # in particular, "\012|\015\012" would be wrong. sub unpack_LDIF { my ($str, $read_ref, $option) = @_; { # Change $SEP to $/: my $irs = $/; # Input Record Separator if (($irs =~ /^($SEP)$/) or (not $irs =~ /$SEP/)) { $str =~ s/$SEP/$irs/g; } else { # $SEP matches a proper substring of $/ $str =~ s/$irs|$SEP/$irs/g; } $str =~ s/^($SEP)*//; # ignore leading empty lines # This also handles CRLF when $/ eq CR; in that case, # the final LF of each record is read together with # the beginning of the next record. For example, # the input stream "a: i\015\012\015\012a: j" # is handled (in consecutive calls to get_LDIF) as: # unpack_LDIF("a: i\015\012\015"); # unpack_LDIF("\012a: j"); } $str =~ s"$/ ""g; # combine continuation lines $str =~ s"^#.*($/|$)""gm # ignore comments unless ((defined $option) and ("comments" eq lc $option)); my (@record, $attr, $value); local $_; foreach $_ (split $/, $str) { last if ($_ eq ""); # blank line if ($_ =~ /^#/) { # comment ($attr, $value) = ($_, undef); } else { ($attr, $value) = split /:/, $_, 2; if (not defined ($value)) { warn "$0 non-LDIF line: $_\n" if ($^W and $attr ne "-"); } elsif ($value =~ s/^: *//) { $value = decode_base64 ($value); } elsif ($value =~ s/^< *//) { my $temp = $value; $value = \$temp; if (defined $read_ref) { &$read_ref ($value); } } else { $value =~ s/^ *//; } } push @record, ($attr, $value); } return @record; } sub output_separator { return "\015\012" if "\n" =~ /\015/; return "\012"; } use vars qw($_std_encode); $_std_encode = '^[:< ]|[^ -\x7E]'; sub pack_LDIF { my $max_line = shift; my $encode = undef; my $sep = "\n"; if ((ref $max_line) eq "ARRAY") { my @options = @$max_line; $max_line = undef; while (@options) { my ($option, $value) = splice @options, 0, 2; if ("max_line" eq lc $option) { $max_line = $value; } elsif ("sep" eq lc $option) { $sep = $value; } elsif ("encode" eq lc $option) { $encode = ($value eq $_std_encode) ? undef : $value; } } } $max_line = undef unless (defined ($max_line) and $max_line > 1); my $str = ""; foreach my $record (_to_LDIF_records \@_) { my @record = @$record; $str .= $sep if length $str; # blank line between records while (@record) { my ($attr, $val) = splice @record, 0, 2; foreach $val (((ref $val) eq "ARRAY") ? @$val : $val) { if (not defined $val) { $str .= _continue_lines ($sep, $max_line, $attr); } else { my $value; if (ref $val) { $value = "< $$val"; } elsif ($val eq "") { $value = ""; # output "$attr:" } elsif ((defined $encode) ? $val =~ /$encode/ : $val =~ /$_std_encode/o) { $value = ": " . encode_base64 ($val, ""); } else { $value = " $val"; } $str .= _continue_lines ($sep, $max_line, "$attr:$value"); } } } } return $str; } ############################################################################# # get/put sub get_LDIF { my ($fh, $eof, @options) = @_; $fh = *STDIN unless defined $fh; my $empty_line = ($/ =~ /^($SEP)$/) ? "($SEP)($SEP)" : "($/|$SEP)($/|$SEP)"; my (@record, $localEOF); $eof = (@_ > 1) ? \$_[$[+1] : \$localEOF; $$eof = ""; do { my $str = ""; my $line; while (1) { if (not defined ($line = <$fh>)) { $$eof = 1; last; # EOF from a file } $str .= $line; if (not chomp $line) { $$eof = 1; last; # EOF from a terminal } elsif ($str =~ /$empty_line/) { last; # end of record } } @record = unpack_LDIF ($str, @options); } until (@record or $$eof); return @record; } sub put_LDIF { my $fh = shift; my $options = shift; my $sep = "\n"; if ((ref $options) eq "ARRAY") { next_attribute ($options, undef, type => '"sep" eq lc $_', value => sub {$sep = $_; return 0;}); } $fh = select() unless defined $fh; foreach my $record (_to_LDIF_records \@_) { no strict qw(refs); # $fh might be a string print $fh (pack_LDIF ($options, $record), $sep); } } ############################################################################# # object methods sub new { my ($class) = @_; my $self = {}; if (@_ < 2) { $self->{"_fh_"} = *STDIN; $self->{"_rw_"} = "r"; } else { $self->{"_fh_"} = $_[$[+1]; if (@_ == 2) { $self->{"_rw_"} = "rw"; } else { my $p2 = $_[$[+2]; my $p2type = ref $p2; if ($p2type eq "CODE" or (@_ > 3 and not defined $p2)) { $self->{"_rw_"} = "r"; $self->{"options"} = [$p2, $_[$[+3]]; } else { $self->{"_rw_"} = "w"; $self->{"options"} = ($p2type eq "ARRAY") ? [@$p2] : $p2; } } if (not $self->{"_fh_"}) { if ($self->{"_rw_"} eq "w") { $self->{"_fh_"} = select(); # STDOUT, by default. } else { $self->{"_fh_"} = *STDIN; $self->{"_rw_"} = "r"; } } } return bless $self, $class; } ############################################################################# # Destructor, close file descriptors etc. (???) # #sub DESTROY #{ # my $self = shift; #} sub get1 { my ($self) = @_; if ($self->{"_rw_"} ne "r") { return unless ($self->{"_rw_"} eq "rw"); $self->{"_rw_"} = "r"; } my $options = $self->{"options"}; my $eof; my @record = get_LDIF ($self->{"_fh_"}, $eof, defined $options ? @$options : ()); if ($eof) { $self->{"_rw_"} = "eof"; } return @record; } sub get { if (not ref $_[$[]) { # class method shift; return get_LDIF (@_); } use integer; if (@_ <= 1) { return get1 (@_); } my ($self, $num) = @_; my (@records, @record); $num = -1 unless defined $num; while (($num < 0 or $num-- != 0) and (@record = get1 ($self))) { push @records, [ @record ]; } return @records; } sub put { if (not ref $_[$[]) { # class method shift; return put_LDIF (@_); } my $self = shift; if ($self->{"_rw_"} ne "w") { return unless ($self->{"_rw_"} eq "rw"); $self->{"_rw_"} = "w"; } return put_LDIF ($self->{"_fh_"}, $self->{"options"}, @_); } ############################################################################# # Utilities sub next_attribute { my ($record, $offset) = @_; use integer; if (not defined $offset) { $offset = -2; } elsif ($offset % 2) { --$offset; # make it even } my $i = $[ + $offset; ATTRIBUTE: while (($i += 2) < $#$record) { my $value = \${$record}[$i+1]; next unless defined $$value; # ignore comments and "-" lines my $option; OPTION: for ($option = $[ + 2; $option < $#_; $option += 2) { my ($keyword, $expression) = ((lc $_[$option]), $_[$option+1]); my $exprType = ref $expression; my $OK = 0; if ("name" eq $keyword or "type" eq $keyword) { next ATTRIBUTE unless defined $expression; next OPTION if ($exprType and ($exprType ne "CODE")); # unsupported foreach $_ (${$record}[$i]) { last if ($OK = $exprType ? &$expression ($_) : eval $expression); } } elsif ("value" eq $keyword) { next ATTRIBUTE unless defined $expression; next OPTION if ($exprType and ($exprType ne "CODE")); # unsupported foreach $_ (((ref $$value) eq "ARRAY") ? @$$value : $$value) { last if ($OK = $exprType ? &$expression ($_) : eval $expression); } } else { # unsupported keyword last OPTION; } next ATTRIBUTE unless $OK; } return $i - $[; } return undef; } sub references { my @refs; use integer; foreach my $record (_to_LDIF_records \@_) { my $i = undef; while (defined ($i = next_attribute ($record, $i))) { my $vref = \${$record}[$[+$i+1]; my $vtype = ref $$vref; if ($vtype eq "ARRAY") { # a list foreach my $value (@$$vref) { if (ref $value) { push @refs, \$value; } } } elsif ($vtype) { push @refs, $vref; } } } return @refs; } sub _carpf { my $msg = sprintf shift, @_; require Carp; Carp::carp $msg; } sub enlist_values { use integer; my @records = _to_LDIF_records (\@_, "enlist_values", wantarray); my @results; foreach my $record (@records) { my ($i, @result, %first, $isEntry); for ($i = $[+1; $i <= $#$record; $i += 2) { my ($attr, $value) = (${$record}[$i-1], ${$record}[$i]); if (not defined $value) { %first = () # Don't enlist values separated by a "-" line. unless ($attr =~ /^#/); # but comments don't matter. push @result, ($attr, $value); } else { if (not defined $isEntry) { # Decide whether this is an entry: $isEntry = (lc ${$record}[$[]) eq "dn"; if ($isEntry) { $isEntry = (lc ${$record}[$[+2]) ne "changetype"; $isEntry = (lc ${$record}[$[+3]) eq "add" unless $isEntry; } # A single Boolean expression would be better, except it makes # SunOS Perl 5 carp "Useless use of string ne in void context". } my $firstValue = $first{lc $attr}; if (not defined $firstValue) { $firstValue = []; # Enlist non-adjacent values only in an entry. %first = () unless $isEntry; $first{lc $attr} = $firstValue; push @result, ($attr, $firstValue); } push @$firstValue, ((ref $value) eq "ARRAY") ? @$value : $value; } } for ($i = $[+1; $i <= $#result; $i += 2) { next unless defined $result[$i]; my $len = scalar @{$result[$i]}; if ($len == 0) { $result[$i] = undef; # how did this happen? } elsif ($len == 1) { $result[$i] = ${$result[$i]}[$[]; } } foreach my $r (references (\@result)) { # don't return the same reference my $v = $$$r; $$r = \$v; # return a reference to a copy of the scalar } push @results, \@result; } return ((@records == 1) and ($records[$[] eq \@_)) ? @{$results[$[]} : @results; } sub condense { _carpf ("Use ".__PACKAGE__."::enlist_values" ." (instead of obsolescent condense)") if $^W; # Unlike condense, enlist_values does not modify the records # you pass to it; it returns newly created, equivalent records. foreach my $record (@_) { @$record = @{(enlist_values ($record))[$[]}; } } sub delist_values { use integer; my @records = _to_LDIF_records (\@_, "delist_values", wantarray); my @results; foreach my $record (@records) { my ($i, @result); for ($i = $[+1; $i <= $#$record; $i += 2) { my ($attr, $value) = (${$record}[$i-1], ${$record}[$i]); foreach $value (((ref $value) eq "ARRAY") ? @$value : $value) { push @result, ($attr, $value); } } if ($i == $#$record + 1) { # weird. Well, don't lose it: push @result, ${$record}[$i-1]; } foreach my $r (references (\@result)) { # don't return the same reference my $v = $$$r; $$r = \$v; # return a reference to a copy of the scalar } push @results, \@result; } return ((@records == 1) and ($records[$[] eq \@_)) ? @{$results[$[]} : @results; } sub _k { my $val = shift; return (ref $val) ? "<$$val" : " $val"; # references come last } sub _byAttrValue { ((lc $a->[ $[ ]) cmp (lc $b->[ $[ ])) # ignore case in attribute names or ((_k $a->[$[+1]) cmp (_k $b->[$[+1])); } sub _shiftAttr # Given a reference to an LDIF record, remove the first two elements # (usually an attribute type and value) and also any subsequent # non-attributes (comments, "-" lines or non-LDIF lines). # Return a reference to an array containing the removed values. { my ($from) = @_; my $next = next_attribute ($from, 0); return [ splice @$from, 0, $next ] if defined $next; my @into = splice @$from, 0; push @into, (undef) if (@into % 2); return \@into; } sub sort_attributes # Comments, "-" lines and non-LDIF lines are sorted with the attribute that # immediately precedes them. { use integer; my @records = _to_LDIF_records (\@_, "sort_attributes", wantarray); my (@results, @result, @preamble); foreach my $record (@records) { @result = @{(delist_values ($record))[$[]}; @preamble = (); if (@result > 1 and not defined $result[$[+1]) { # initial comments push @preamble, @{_shiftAttr \@result}; } if (@result and ("dn" eq lc $result[$[])) { push @preamble, @{_shiftAttr \@result}; # dn => "cn=etc..." if ("changetype" eq lc $result[$[]) { # this is a change, not an entry. if ("add" eq lc $result[$[+1]) { push @preamble, @{_shiftAttr \@result}; # changetype => "add" } else { # It's possible to sort this, but it doesn't seem useful. next; # So just return it, unmodified. } } } my @pairs = (); while (@result >= 2) { push @pairs, (_shiftAttr \@result); } @pairs = sort _byAttrValue @pairs; my $pair; while ($pair = pop @pairs) { unshift @result, (@{$pair}); } } continue { unshift @result, @preamble; push @results, [@result]; } return ((@records == 1) and ($records[$[] eq \@_)) ? @{$results[$[]} : @results; } *sort_entry = \&sort_attributes; # for compatibility with prior versions. sub get_DN { use integer; my @records = _to_LDIF_records (\@_, "get_DN", wantarray); my @DNs; foreach my $record (@records) { my $i = next_attribute ($record); push @DNs, (((defined $i) and ("dn" eq lc $record->[$[+$i])) ? $record->[$[+$i+1] : undef); } return ((@records == 1) and ($records[$[] eq \@_)) ? $DNs[$[] : @DNs; } *LDIF_get_DN = \&get_DN; sub read_file_name { my $name = ${$_[$[]}; local *FILE; if (open (FILE, "<$name")) { binmode FILE; $_[$[] = ""; while (read (FILE, $_[$[], 1024, length ($_[$[]))) {} close FILE; return 1; } warn "$0 can't open $name: $!\n" if $^W; return ""; # failed } sub read_file_URL { my $URL = ${$_[$[]}; if ($URL =~ s/^file://i) { $URL =~ s'^///'/'; # file:///x == file:/x my $value = \$URL; if (read_file_name ($value)) { $_[$[] = $value; return 1; } } return ""; # failed } *read_v0 = \&read_file_name; *read_v1 = \&read_file_URL; sub read_file_URL_or_name { read_file_URL (@_) or read_file_name (@_); } ############################################################################# # Mozilla::LDAP::Entry support sub set_Entry { my ($entry, $record) = @_; return unless defined $record; ($record) = enlist_values ($record); foreach my $r (references ($record)) { read_file_URL_or_name ($$r); } my $skip; while (defined ($skip = next_attribute ($record))) { if ($skip) { splice @$record, 0, $skip; } my ($attr, $value) = splice @$record, 0, 2; if ("dn" eq lc $attr) { $entry->setDN ($value); } else { $entry->{$attr} = ((ref $value) eq "ARRAY") ? $value : [$value]; } } return $entry; } use vars qw($_used_Entry); $_used_Entry = ""; sub _use_Entry { return if $_used_Entry; $_used_Entry = 1; eval 'use Mozilla::LDAP::Entry()'; if ($@) { warn $@; # But don't die. Perhaps we're using another, compatible class. } elsif (not can Mozilla::LDAP::Entry 'getLDIFrecords') { # 'eval' prevents 'sub' from happening at compile time. eval q{ package Mozilla::LDAP::Entry; sub getLDIFrecords { my ($self) = @_; my @record = (dn => $self->getDN()); # The following depends on private components of LDAP::Entry. # This is bad. But the public interface wasn't sufficient. foreach my $attr (@{$self->{"_oc_order_"}}) { next if ($attr =~ /^_.+_$/); next if $self->{"_${attr}_deleted_"}; push @record, ($attr => $self->{$attr}); # This is dangerous: @record and %$self now both contain # references to the same array. To avoid this, copy it: # push @record, ($attr => [@{$self->{$attr}}]); # But that's not necessary, because the array and its # contents are not modified as a side-effect of getting # other attributes, from this or other LDAP::Entry's. } return \@record; } }; # eval } } ############################################################################# # Read multiple entries, and return an array of objects. # The first parameter is the number to read (default: read the entire file). # sub readEntries { my ($self, $num, $factory) = @_; # This function could be extended, to enable the caller to supply # a factory class name or object reference as the second parameter. my @records = $self->get ($num); require Mozilla::LDAP::Conn if @records; # and not defined $factory my ($record, @entries); while ($record = shift @records) { push @entries, set_Entry ((#(defined $factory) ? $factory->newEntry() : Mozilla::LDAP::Conn->newEntry()), $record); } return @entries; } ############################################################################# # Read the next $entry from an ::LDIF object. # sub readOneEntry { my $self = shift; my ($entry) = $self->readEntries (1, @_); return $entry; } *readEntry = \&readOneEntry; ############################################################################# # Write multiple entries, the argument is the array of Entry objects. # sub writeEntries { _use_Entry(); return put (@_); } ############################################################################# # Print one entry, to the file handle. # sub writeOneEntry { my ($self, $entry) = @_; # ignore other parameters return $self->writeEntries ($entry); } *writeEntry = \&writeOneEntry; ############################################################################# # Mandatory TRUE return value. # 1; ############################################################################# # POD documentation... # __END__ =head1 NAME Mozilla::LDAP::LDIF - read or write LDIF (LDAP Data Interchange Format) =head1 SYNOPSIS use Mozilla::LDAP::LDIF qw(set_Entry get_LDIF put_LDIF unpack_LDIF pack_LDIF sort_attributes references enlist_values delist_values read_v1 read_v0 read_file_URL_or_name); $ldif = Mozilla::LDAP::LDIF->new(*FILEHANDLE, \&read_reference, $comments); @record = get $ldif; @records = get $ldif ($maximum_number); $entry = set_Entry (\entry, \@record); $entry = readOneEntry $ldif; @entries = readEntries $ldif ($maximum_number); $ldif = Mozilla::LDAP::LDIF->new(*FILEHANDLE, $options); $success = put $ldif (@record); $success = put $ldif (\@record, \object ...); $success = writeOneEntry $ldif (\entry); $success = writeEntries $ldif (\entry, \entry ...); @record = get_LDIF (*FILEHANDLE, $eof, \&read_reference, $comments); @record = get_LDIF; # *STDIN $success = put_LDIF (*FILEHANDLE, $options, @record); $success = put_LDIF (*FILEHANDLE, $options, \@record, \object ...); @record = unpack_LDIF ($string, \&read_reference, $comments); $string = pack_LDIF ($options, @record); $string = pack_LDIF ($options, \@record, \object ...); @record = enlist_values (@record); @record = delist_values (@record); @record = sort_attributes (@record); $DN = LDIF_get_DN (@record); # alias get_DN @DNS = LDIF_get_DN (\@record, \object ...); # alias get_DN $offset = next_attribute (\@record, $offset, @options); @references = references (@record); @references = references (\@record, \object ...); $success = read_v1 (\$url); # alias read_file_URL $success = read_v0 (\$name); # alias read_file_name $success = read_file_URL_or_name (\$url_or_name); =head1 REQUIRES MIME::Base64, Exporter, Carp =head1 INSTALLATION Put the LDIF.pm file into a subdirectory named Mozilla/LDAP, in one of the directories named in @INC. site_perl is a good choice. =head1 EXPORTS Nothing (unless you request it). =head1 DESCRIPTION LDIF version 1 is defined by Fdraft-good-ldap-ldif-03E>. An LDIF record like this: DN: cn=Foo Bar, o=ITU cn: Foo Bar Sn: Bar objectClass: person objectClass: organizatio nalPerson jpegPhoto:< file:foobar.jpg # comment corresponds (in this module) to a Perl array like this: (DN => "cn=Foo Bar, o=ITU", cn => "Foo Bar", Sn => "Bar", objectClass => [ "person", "organizationalPerson" ], jpegPhoto => \"file:foobar.jpg", '# comment', undef ) URLs or file names are read by a separate function. This module provides functions to read a file name (LDIF version 0) or a file URL that names a local file (minimal LDIF version 1), or either. You can supply a similar function to read other forms of URL. Most output and utility methods in this module accept a parameter list that is either an LDIF array (the first item is a string, usually "dn"), or a list of references, with each reference pointing to either an LDIF array or an object from which this module can get LDIF arrays by calling the object's B method. This module calls $object->getLDIFrecords(), expecting it to return a list of references to LDIF arrays. getLDIFrecords may return references to the object's own data, although it should not return references to anything that will be modified as a side-effect of another call to getLDIFrecords(), on any object. =head1 METHODS =head2 Input =over 4 =item B Mozilla::LDAP::LDIF (*FILEHANDLE, \&read_reference, $comments) Create and return an object to read LDIF from the given file. If *FILEHANDLE is not defined, return an object to read from *STDIN. If \&read_reference is defined, call it when reading each reference to another data source, with ${$_[$[]} equal to the reference. The function should copy the referent (for example, the contents of the named file) into $_[$[]. Ignore LDIF comment lines, unless $comments eq "comments". =item B $ldif Read an LDIF record from the given file. Combine continuation lines and base64-decode attribute values. Return an array of strings, representing the record. Return a false value if end of file is encountered before an LDIF record. =item B $ldif ($maximum_number) Read LDIF records from the given file, until end of file is encountered or the given $maximum_number of records are read. If $maximum_number is undef (or negative), read until end of file. Return an array of references to arrays, each representing one record. Return a false value if end of file is encountered before an LDIF record, or $maximum_number is zero. =item B $ldif =item B $ldif ($maximum_number) Read Mozilla::LDAP::Entry objects from the given file, and return references to them. Call Mozilla::LDAP::Conn->newEntry() to create each returned object. Return a false value if end of file is encountered before an LDIF record, or $maximum_number is zero. B returns a reference to a single object. B returns an array of references to as many as $maximum_number objects. See B (above) for more information. =item B (\entry, \@record) Set the DN and attributes of the given Mozilla::LDAP::Entry object from the given LDIF record. Return a reference to the entry. =item B (*FILEHANDLE, $eof, \&read_reference, $comments) Read an LDIF record from the given file. Return an array of strings, representing the record. Return a false value if end of file is encountered before an LDIF record. If *FILEHANDLE is not defined, read from *STDIN. If $eof is passed, set it true if the end of the given file was encountered; otherwise set it false. This function may set $eof false and also return a record (if the record was terminated by the end of file). If \&read_reference is defined, call it when reading each reference to another data source, with ${$_[$[]} equal to the reference. The function should copy the referent (for example, the contents of the named file) into $_[$[]. Ignore LDIF comment lines, unless $comments eq "comments". =item B ($string, \&read_reference, $comments) Read one LDIF record from the given string. Return an array of strings, representing the record. Return a false value if the given string doesn't contain an LDIF record. If \&read_reference is defined, call it when reading each reference to another data source, with ${$_[$[]} equal to the reference. The function should copy the referent (for example, the contents of the named file) into $_[$[]. Ignore LDIF comment lines, unless $comments eq "comments". =item B (\$url) =item B (\$url) Change the parameter, from a reference to a URL (string) to a string containing a copy of the contents of the file named by that URL, and return true. Return false if the URL doesn't name a local file, or the file can't be read. This implements LDIF version 1, although it doesn't support URLs that refer to anything but a local file (e.g. HTTP or FTP URLs). =item B (\$name) =item B (\$name) Change the parameter, from a reference to a file name to a string containing a copy of the contents of that file, and return true. Return false if the file can't be read. This implements LDIF version 0. =item B (\$url_or_name) Change the parameter, from a reference to a URL or file name, to a string containing a copy of the contents of the file it names, and return true. Return false if the file can't be read. =back =head2 Output =over 4 =item Mozilla::LDAP::LDIF->B(*FILEHANDLE, $options) Create and return an object used to write LDIF to the given file. $options are described below. =item B $ldif (@record) =item B $ldif (\@record, \object ...) =item B (*FILEHANDLE, $options, @record) =item B (*FILEHANDLE, $options, \@record, \object ...) Write LDIF records to the given file. $options are described below. =item B $ldif (\entry) =item B $ldif (\entry, \entry ...) Write Mozilla::LDAP::Entry objects to the given file. =item B ($options, @record) =item B ($options, \@record, \object ...) Return an LDIF string, representing the given records. =item B<$options> The options parameter (above) may be either C, indicating all default options, or a number, which is equivalent to C<[max_line =E>I< number>C<]>, or a reference to an array that contains a list of options, composed from: =over 4 =item C>I< number> If I > 1, break output into continuation lines, so no line is longer than I bytes (not counting the end-of-line marker). Default: 0 (output is not broken into continuation lines). =item C>I< pattern> Base64 encode output values that match I. Warning: As a rule, your I should match any value that contains an output line separator (see the SEP option, below). If any such value is not Base64 encoded, it will be output in a form that does not represent the separator bytes in LDIF form. That is, if the output is parsed as LDIF, the resulting value will be like the original value, except the separator bytes will be removed. Default: C<"^[:E ]|[^ -\x7E]"> For example: pack_LDIF ([encode=>"^ |[^ -\xFD]"], @record) returns a string in which UTF-8 strings are not encoded (unless they begin with a space or contain control characters) and lines are not continued. Such a string may be easier to view or edit than standard LDIF, although it's more prone to be garbled when sent in email or processed by software designed for ASCII. It can be parsed without loss of information (by unpack_LDIF). =item C>I< string> Output I at the end of each line. Default: C<"\n"> (the usual line separator, for output text). =back =item B () Return the standard LDIF line separator most similar to "\n". The output option C<[sep =E output_separator()]> is recommended, B you want to produce standard LDIF output. =back =head2 Utilities =over 4 =item B (@record) =item B (\@record, \object ...) Return a record equivalent to each parameter, except with the attributes sorted, primarily by attribute name (ignoring case) and secondarily by attribute value (using &cmp). If the parameter list is a single record, return a single record; otherwise return a list of references to records. =item B (@record) =item B (\@record, \object ...) Return a record equivalent to the parameter, except with values of the same attribute type combined into a nested array. For example, enlist_values (givenName => "Joe", givenname => "Joey", GivenName => "Joseph") returns (givenName => ["Joe", "Joey", "Joseph"]) If the parameter list is a single record, return a single record; otherwise return a list of references to records. =item B (@record) =item B (\@record, \object ...) Return a record equivalent to the parameter, except with all values contained directly (not in a nested array). For example, delist_values (givenName => ["Joe", "Joey", "Joseph"]) returns (givenName => "Joe", givenName => "Joey", givenName => "Joseph") If the parameter list is a single record, return a single record; otherwise return a list of references to records. =item B (@record) =item B (\@record, \object ...) In list context, return a list of references to each of the references to external data sources, in the given records. In scalar context, return the length of that list; that is, the total number of references to external data sources. =item LDIF_get_DN (@record) =item get_DN (@record) Return the DN of the given record. Return undef if the first attribute of the record isn't a DN. =item LDIF_get_DN (\@record, \object ...) =item get_DN (\@record, \object ...) Return the DN of each of the given records, as an array with one element for each parameter. If a given record's first attribute isn't a DN, the corresponding element of the returned array is undef. =item next_attribute (\@record, $offset, @options) Return the offset of an attribute type in the given record. Search forward, starting at $offset + 1, or 0 if $offset is not defined. Return undef if no attribute is found. The @options list is composed of zero or more of the following: =over 4 =item C >I =item C >I Don't return an offset unless the given I evaluates to TRUE, with $_ aliased to the attribute type name. =item C >I Don't return an offset unless the given I evaluates to TRUE, with $_ aliased to one of the attribute values. =back In either case, the I may be a string, which is simply evaluated (using B), or a reference to a subroutine, which is called with $_ as its only parameter. The value returned by B or the subroutine is taken as the result of evaluation. If no options are given, the offset of the next attribute is returned. Option expressions can modify the record, since they are passed an alias to an element of the record. An option can selectively prevent the evaluation of subsequent options: options are evaluated in the order they appear in the @options list, and if an option evaluates to FALSE, subsequent options are not evaluated. =back =head1 DIAGNOSTICS =over 4 =item $0 can't open %s: $! (W) Mozilla::LDAP::LDIF::read_file_* failed to open a file, probably named in an LDIF attrval-spec. =item $0 non-LDIF line: %s (D) The input contains a line that can't be parsed as LDIF. It is carried along in place of an attribute name, with an undefined value. For example, B("abc") outputs this warning, and returns ("abc", undef). =item Can't use MIME::Base64 (F) The MIME::Base64 module isn't installed. To rectify this, get a copy of MIME::Base64 from http://www.perl.com/CPAN/modules/by-module/MIME/ and install it. If you have trouble, try simply putting Base64.pm in a subdirectory named MIME, in one of the directories named in @INC (site_perl is a good choice). You'll get a correct, but relatively slow implementation. =item Useless use of %s in scalar or void context (W) The function returns multiple records, of which all but the last will be ignored by the caller. Time and space were wasted to create them. It would probably be better to call the function in list context, or to pass it only a single record. =back =head1 EXAMPLES use Mozilla::LDAP::LDIF qw(read_file_URL_or_name); $in = Mozilla::LDAP::LDIF->new(*STDIN, \&read_file_URL_or_name); $out = Mozilla::LDAP::LDIF->new(*STDOUT, 78); @records = get $in (undef); # read to end of file (^D) put $out (@records); use Mozilla::LDAP::Conn(); $conn = Mozilla::LDAP::Conn->new(...); while ($entry = readOneEntry $in) { add $conn ($entry); } use Mozilla::LDAP::LDIF qw(get_LDIF put_LDIF references read_v1 next_attribute sort_attributes); while (@record = get_LDIF (*STDIN, $eof)) { # Resolve all the file URLs: foreach my $r (references (@record)) { read_v1 ($$r); } # Capitalize all the attribute names: for ($r = undef; defined ($r = next_attribute (\@record, $r)); ) { $record[$r] = ucfirst $record[$r]; } # Capitalize all the title values: next_attribute (\@record, undef, type => '"title" eq lc $_', value => '$_ = ucfirst; 0'); # Sort the attributes and output the record, 78 characters per line: put_LDIF (*STDOUT, 78, sort_attributes (@record)); last if $eof; } =head1 BUGS =over 4 =item Output Line Separator Output lines are separated by "\n", by default. Although this works well in many cases, it is not standard LDIF unless "\n" is "\012" or "\015\012". It is not, on some platforms (Macintosh, for example). To get standard output, use the output option C<[sep =E Mozilla::LDAP::LDIF::output_separator()]>. =item Input Line Separator This package may fail to read standard LDIF correctly, if the input record separator is not LF. To avoid this bug, set $/ = "\012". Other values of $/ work less well: CR ($/ eq "\015") handles input separated by CR or CR LF, but not LF alone; and CR LF ($/ eq "\015\012") handles input separated by CR LF, but not LF alone. This bug arises when handling standard LDIF received 'raw' via the Internet (via HTTP, for example). There's no problem with an input file that has been converted (as generic text) from standard Internet line separators to $/ (that is, the usual line separator for the local platform). =back =head1 AUTHOR John Kristian Thanks to Leif Hedstrom, from whose code I took ideas; and to the users who took the trouble to correct my mistakes. But I accept all blame. =head1 SEE ALSO L, L, and of course L. =cut