Front page | perl.ldap |
Postings from April 2003
Subclass proposal: Net::LDAP::Simple
Thread Next
From:
Marco Marongiu
Date:
April 28, 2003 03:54
Subject:
Subclass proposal: Net::LDAP::Simple
Message ID:
3EAD0843.2070308@crs4.it
Hello there, my name is Marco Marongiu. I am brand new on this list so
if I am violating any rule or convention here I apologize. I am writing
here after exchanging a couple of e-mails with Graham Barr.
A couple of weeks I asked some opinions on the perlmonks.org site about
the idea of subclassing Net::LDAP to get a simplified interface. I am
sorry I didn't think about posting *here* the same RFC, but here we go...
What do I mean "simplified"? I'll try to show it by means of two examples.
Example 1: you have to retrieve a number of entries in a subtree based
on the contents of certain attributes, say cn, uid, loginName. The
attributes remain the same, but you change the search string. You'll use
a filter like (|(cn~=marco)(|(uid~=marco)(loginName~=marco)); then
you'll pass the filter to the search method, along with the base (the
same for all searches) and all the other parameters you need. After
that, you need to check the returned Search object for errors and, in
case of success, extract the entries to do the job; then start over with
another similar filter and so on.
I'd like to have a method to which I pass a "query string" and it does
all the job for me, returning a reference to an array of entries for
success or undef on failure -and, of course, I'd like to have a chance
of seeing what actually made my search go wrong.
Example 2: You have to read a bunch of entries from a directory server,
modifying some attributes and then update them on another server -to fix
the ideas you can think of reading entries from an iPlanet DS with NIS
gateway and putting them into some Windows Active Directory server. The
algorithm is about the same as above: search, check return message,
extract entries, modify them, push them one by one on the other server,
check the return message each time.
I'd like to have a method that allows me to add an array of entries, and
that returns a reference to an array containing the entries that made it
in the directory server; in case of problems (input array has different
length than the output) I'd like to have a chance to see what happened.
In short: I don't want to go and check the return code if I don't have
to, and I'd be happy if I had "array operations" on entries.
I thought that it could be a good idea to create a subclass that offered
such a simplified interface, and that Net::LDAP::Simple could be a name
that fit. Then I read the (excellent) Sam Tregar's book "Writing Perl
modules for CPAN" and he warned to ask for namespace owner's consensus
before publishing anything. That's why I am here.
I wouldn't post the module to CPAN if I won't have enough consensus or
if you'll send me reasonable objections. But, in that case, I beg you to
suggest a different, appropriate namespace.
Enough talking. Below is the content of the manpage. If it is allowed on
the list, I'll post the gzipped tarball too, it's less than 9kB. Just
let me know.
Thanks in advance for any suggestions and sorry for not contacting you
before.
Marco
__END__
NAME
Net::LDAP::Simple - Simplified interface for Net::LDAP
SYNOPSIS
use Net::LDAP::Simple;
# connect and bind to a directory server
# bindDN and bindpw are optional, if you don't specify them an
# anonymous bind is performed
# base is the base subtree for searches, it is an optional parameter
# searchattrs are the attributes that are used by the simplesearch()
# method.
eval {
my $ldap =
Net::LDAP::Simple->new(host => 'localhost',
bindDN => 'cn=admin,ou=People,dc=me',
bindpw => 'secret',
base => 'ou=People,dc=me',
searchattrs => [qw(cn uid loginname)],
%parms) ; # params for Net::LDAP::new
} ;
if ($@) {
die "Can't connect to ldap server: $@" ;
}
my $filter = '(|(loginname=~bronto)(|(cn=~bronto)(uid=~bronto)))' ;
my $entries ;
# These all return the same array of Net::LDAP::Entry objects
$entries = $ldap->search(filter => $filter) ; # uses new()'s base
$entries = $ldap->search(base => 'ou=People,dc=me',
filter => $filter) ;
$entries = $ldap->simplesearch('bronto') ; # uses new()'s searchattrs
# Now elaborate results:
foreach my $entry (@$entries) {
modify_something_in_this($entry) ;
}
# You often want to update a set of entries
foreach my $entry (@$entries) {
die "Error updating entry" unless defined $ldap->update($entry) ;
}
# but you can also do this:
my $result = $ldap->update(@$entries) ;
unless (@$result == @$entries) {
print "Error updating entries: ",$ldap->error,
"; code ",$ldap->errcode,".\n\n" ;
}
# Add an entry, or an array of them, works as above:
die $ldap->error unless $ldap->add($entry) ;
# rename an entry: sometimes you simply want to change a name
# and nothing else...
$ldap->rename($entry,$newrdn) ;
DESCRIPTION
Net::LDAP::Simple is a simplified interface to the fantastic Graham
Barr's Net::LDAP. Net::LDAP is a great module for working with
directory servers, but it's a bit overkill when you want to do
simple short scripts or have big programs that always do the same
job again and again, say: open an authenticated connection to a
directory server, search entries against the same attributes each
time and in the same way (e.g.: approx search against the three
attributes cn, uid and loginname). With Net::LDAP this would mean:
* connect to the directory server using new();
* authenticate with bind() ;
* compose a search filter, and pass it to search(), along with the
base subtree;
* perform the search getting a Net::LDAP::Search object;
* verify that the search was successful using the code() or
is_error() method on the search object;
* if the search was successful, extract the entries from the
Search object, for example with entries or shift_entry.
With Net::LDAP::Simple this is done with:
* connect, authenticate, define default search subtree and
simple-search attributes with the new() method;
* pass the simplesearch method a search string to be matched
against the attributes defined with searchattrs in new() and
check the return value: if it was successful you have a
reference to an array of Net::LDAP::Entry objects, if it was
unsuccessful you get undef, and you can check what the error was
with the error() method (or the error code with errcode) ;
CONSTRUCTOR
new(%parms)
Creates a Net::LDAP::Simple object. Accepts all the parameters
that are legal to Net::LDAP::new but the directory server
name/address is specified via the "host" parameter. Specific
Net::LDAP::Simple parameters are therefore:
host
the name or IP address of the directory server we are
connecting to. Mandatory.
bindDN
bind DN in case of authenticated bind
bindpw
bind password in case of authenticated bind
base
base subtree for searches. ***(Mandatory or optional?)
searchattrs
attributes to use for simple searches (see the simplesearch
method);
searchbool
boolean operator in case that more than one attribute is
specified with searchattrs; default is '|' (boolean or);
allowed boolean operators are | and &.
searchmatch
By default, an 'approx' search is performed by
simplesearch(); for those directory servers that doesn't
support the ~= operator it is possible to request a
substring search specifying the value 'substr' for the
searchmatch parameter.
searchextras
A list of attributes that should be returned in addition of
the default ones.
REDEFINED METHODS
All Net::LDAP methods are supported via inheritance. Method specific
in Net::LDAP::Simple or that override inherited methods are
documented below.
add If you pass it a scalar DN as first parameter, it will proxy the
method call to Net::LDAP::add and it will behave the sane way
returning a Net::LDAP::Message object. Or you can pass it one or
more Net::LDAP::Entry objects, and it will return a reference to
an array of Net::LDAP::Entry objects that successfully made it
on the directory server. You can check if every entry has been
added by comparing the length of the input list against the
length of the output list. Use the error and/or errorcode
methods to see what went wrong.
delete
Works the same way as "add", but it deletes entries instead :-)
search
search works exactly as Net::LDAP::search() does, however it
takes advantage of the defaults set with new(): uses new()'s
base parameter if you don't specify another base, and adds
searchextras to default attributes unless you specify an "attrs"
parameter.
Another change in the search() interface is the return value:
now search() returns a reference to an array of entries for
success, or undef on error.
Passing a plain string to "search" just proxyies the call to the
method "simplesearch".
NOTE: Actually, I am undecided if this is a good thing. I am
pondering if search should simply be inherited by the
superclass... I'd like to have some feedback about that.
NEW METHODS
rename($entry,$newrdn)
Renames an entry; $entry can be a Net::LDAP::Entry or a DN,
$newrdn is a new value for the RDN. Returns $entry for success,
undef on failure.
update(@entries)
update takes a list of Net::LDAP::Entry objects as arguments and
commits changes on the directory server. Returns a reference to
an array of updated entries.
simplesearch($searchstring)
Searches entries using the new()'s search* and base parameters.
Takes a search string as argument. Returns a list of entries on
success, undef on error.
error
Returns last error's name
errcode
Returns last error's code
AUTHOR
Marco Marongiu, <bronto@crs4.it>
SEE ALSO
Net::LDAP.
--
Marco Marongiu Email: bronto@crs4.it
CRS4 Research Center Phone: +39 070 2796 336
NCS Division Fax: +39 070 2796 216
NSM Group WWW: http://bugs.unica.it:4444/
Thread Next
-
Subclass proposal: Net::LDAP::Simple
by Marco Marongiu