зеркало из https://github.com/mozilla/pjs.git
873 строки
27 KiB
Perl
873 строки
27 KiB
Perl
#############################################################################
|
|
# $Id: Entry.pm,v 1.5 1998-08-03 06:58:21 leif Exp $
|
|
#
|
|
# The contents of this file are subject to the Mozilla Public License
|
|
# Version 1.0 (the "License"); you may not use this file except in
|
|
# compliance with the License. You may obtain a copy of the License at
|
|
# http://www.mozilla.org/MPL/
|
|
#
|
|
# Software distributed under the License is distributed on an "AS IS"
|
|
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing rights and limitations
|
|
# under the License.
|
|
#
|
|
# The Original Code is PerlDAP. The Initial Developer of the Original
|
|
# Code is Netscape Communications Corp. and Clayton Donley. Portions
|
|
# created by Netscape are Copyright (C) Netscape Communications
|
|
# Corp., portions created by Clayton Donley are Copyright (C) Clayton
|
|
# Donley. All Rights Reserved.
|
|
#
|
|
# Contributor(s):
|
|
#
|
|
# 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.
|
|
#
|
|
#############################################################################
|
|
|
|
package Mozilla::LDAP::Entry;
|
|
|
|
require Tie::Hash;
|
|
@ISA = (Tie::StdHash);
|
|
|
|
|
|
#############################################################################
|
|
# 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, does nothing really...
|
|
#
|
|
#sub DESTROY
|
|
#{
|
|
#}
|
|
|
|
|
|
#############################################################################
|
|
# Store method, to keep track of changes.
|
|
#
|
|
sub STORE
|
|
{
|
|
my ($self, $attr, $val) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2]);
|
|
|
|
return if (($val eq "") || ($attr eq ""));
|
|
|
|
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
|
|
unless $self->{"_${attr}_save_"};
|
|
$self->{$attr} = $val;
|
|
$self->{"_${attr}_modified_"} = 1;
|
|
|
|
# Potentially add the attribute to the OC order list.
|
|
if (($attr ne "dn") && !grep(/^$attr$/, @{$self->{_oc_order_}}))
|
|
{
|
|
push(@{$self->{_oc_order_}}, $attr);
|
|
}
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Fetch method, this is case insensitive (since LDAP is...).
|
|
#
|
|
sub FETCH
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
|
|
return unless defined($self->{$attr});
|
|
|
|
return $self->{$attr};
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Delete method, to keep track of changes.
|
|
#
|
|
sub DELETE
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
|
|
return if ($attr eq "");
|
|
return unless defined($self->{$attr});
|
|
|
|
$self->{"_${attr}_deleted_"} = 1;
|
|
undef $self->{$attr};
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Mark an attribute as changed.
|
|
#
|
|
sub attrModified
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
|
|
return 0 if ($attr eq "");
|
|
return 0 unless defined($self->{$attr});
|
|
|
|
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
|
|
unless $self->{"_${attr}_save_"};
|
|
$self->{_self_obj_}->{"_${attr}_modified_"} = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Remove an attribute from the entry, basically the same as the DELETE
|
|
# method. We also make an alias for "delete" here, just in case.
|
|
#
|
|
sub remove
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
|
|
return 0 if ($attr eq "");
|
|
return 0 unless defined($self->{$attr});
|
|
|
|
$self->{_self_obj_}->{"_${attr}_deleted_"} = 1;
|
|
undef $self->{_self_obj_}->{$attr};
|
|
|
|
return 1;
|
|
}
|
|
*delete = \*remove;
|
|
|
|
|
|
#############################################################################
|
|
# 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, $attr, $val) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2]);
|
|
my $i = 0;
|
|
local $_;
|
|
|
|
return 0 if (($val eq "") || ($attr eq ""));
|
|
return 0 unless defined($self->{$attr});
|
|
|
|
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
|
|
unless $self->{"_${attr}_save_"};
|
|
foreach (@{$self->{$attr}})
|
|
{
|
|
if ($_ eq $val)
|
|
{
|
|
splice(@{$self->{$attr}}, $i, 1);
|
|
$action = ($self->size($attr) > 0 ? "modified" : "deleted");
|
|
$self->{_self_obj_}->{"_${attr}_${action}_"} = 1;
|
|
|
|
return 1;
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# 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) = (lc $_[$[], $_[$[ + 1], $_[$[ + 2]);
|
|
local $_;
|
|
|
|
return 0 if (($val eq "") || ($attr eq ""));
|
|
if (!$force)
|
|
{
|
|
foreach (@{$self->{$attr}})
|
|
{
|
|
return 0 if ($_ eq $val);
|
|
}
|
|
}
|
|
|
|
@{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
|
|
unless $self->{"_${attr}_save_"};
|
|
|
|
$self->{_self_obj_}->{"_${attr}_modified_"} = 1;
|
|
push(@{$self->{$attr}}, $val);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Return TRUE or FALSE, if the attribute has the specified value. The
|
|
# optional third argument says we should do case insensitive search.
|
|
#
|
|
sub hasValue
|
|
{
|
|
my($self, $attr, $val, $nocase) = @_;
|
|
|
|
return 0 if (($val eq "") || ($attr eq ""));
|
|
return 0 unless defined($self->{$attr});
|
|
return grep(/^\Q$val\E$/i, @{$self->{$attr}}) if $nocase;
|
|
return grep(/^\Q$val\E$/, @{$self->{$attr}});
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Return TRUE or FALSE, if the attribute matches the specified regexp. The
|
|
# optional third argument says we should do case insensitive search.
|
|
#
|
|
sub matchValue
|
|
{
|
|
my($self, $attr, $reg, $nocase) = @_;
|
|
|
|
return 0 if (($reg eq "") || ($attr eq ""));
|
|
return 0 unless defined($self->{$attr});
|
|
return grep(/$reg/i, @{$self->{$attr}}) if $nocase;
|
|
return grep(/$reg/, @{$self->{$attr}});
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Set the DN of this entry.
|
|
#
|
|
sub setDN
|
|
{
|
|
my ($self, $val) = @_;
|
|
|
|
return 0 if ($val eq "");
|
|
|
|
$self->{dn} = $val;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# Get the DN of this entry.
|
|
#
|
|
sub getDN
|
|
{
|
|
my ($self) = @_;
|
|
|
|
return "$self->{dn}";
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
#
|
|
# Return the number of elements in an attribute.
|
|
#
|
|
sub size
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
my @val;
|
|
|
|
return 0 if ($attr eq "");
|
|
return 0 unless defined($self->{$attr});
|
|
|
|
@val = @{$self->{$attr}};
|
|
return $#val + 1;
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
#
|
|
# Return TRUE if the attribute name is in the LDAP entry.
|
|
#
|
|
sub exists
|
|
{
|
|
my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
|
|
|
|
return 0 if ($attr eq "");
|
|
return defined($self->{$attr});
|
|
}
|
|
|
|
|
|
#############################################################################
|
|
# 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
|
|
|
|
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 LdapUtils.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.
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
First, this is not ment to be a course in how LDAP works, if you have no
|
|
experience with LDAP, I suggest you read some of the literature out
|
|
there. The LDAP Deployment Book, or the LDAP C SDK documentation are good
|
|
starting points.
|
|
|
|
There are two main object classes in this package, the primary class is to
|
|
establish and use an LDAP connection. This class tracks the LDAP
|
|
connection, it's current status, and the current search (if any). Every
|
|
time you call the B<search> method of an Ldapp object, you'll reset it's
|
|
state.
|
|
|
|
The second class is for retrieving, modifying and updating a single entry
|
|
from the LDAP server. The B<search> and B<entry> methods from the
|
|
Ldapp class returns Ldapp::Entry objects. You also have to instantiate
|
|
(and modify) a new Entry object when you want to add new entries to an
|
|
LDAP server.
|
|
|
|
To assure that changes to an entry are updated properly, we strongly
|
|
recommend you use the native methods of this object class. Even though you
|
|
can modify certain elements directly, it could cause changes not to be
|
|
committed to the LDAP server.
|
|
|
|
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 Ldapp::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
|
|
in LDAP must have a DN, and it's always guaranteed to be unique within
|
|
your LDAP 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<uid=leif>, C<cn=gene-staff> and C<dc=data>
|
|
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<uid=leif> within the ou=people tree.
|
|
|
|
=head1 CREATING A NEW LDAPP OBJECT
|
|
|
|
Before you can do anything with LDAP, you'll need to instantiate at least
|
|
one Ldapp object, and connect it to an LDAP server. As you probably
|
|
guessed already, this is done with the B<new> method:
|
|
|
|
$ldap = new Ldapp("ldap", "389", $bind, $pswd, $cert);
|
|
die "Couldn't connect to LDAP server ldap" unless $ldap;
|
|
|
|
The arguments are: Host name, port number, and optionally a bind-DN, it's
|
|
password, and a certificate. 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.
|
|
|
|
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 LDAP object for any number of operations, but
|
|
since everything is currently done synchronously, you can only have one
|
|
operation active at any single time. This is a major drag, and it's
|
|
something we'll fix later (see the BUGS section).
|
|
|
|
=head1 PERFORMING LDAP SEARCHES
|
|
|
|
We assume that you are familiar with the LDAP filter syntax already, all
|
|
searches in the Ldapp object 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<owner> 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";
|
|
$ldap = new Ldapp("ldap", "389", "", "");
|
|
die "No LDAP connection" unless $ldap;
|
|
|
|
$entry = $ldap->search($base, "sub", "(uid=leif)");
|
|
if (! $entry) {
|
|
# handle this event, no entries found
|
|
} else {
|
|
while ($entry) {
|
|
$ldap->printentry($entry);
|
|
$entry = $ldap->entry();
|
|
}
|
|
}
|
|
|
|
This is actually a poor mans implementation of the I<ldapsearch> command
|
|
line utility. The B<search> method returns an Ldapp::Entry object, which
|
|
holds the first entry from the search, if any. To get the second and
|
|
subsequent entries you call the B<entry> method, until there are no more
|
|
entries. The B<printentry> method is a convenient function, printing the
|
|
entry in the LDIF format on the standard output.
|
|
|
|
The arguments to the B<search> methods are the I<LDAP Base-DN>, the
|
|
I<scope> of the search ("base", "one" or "sub"), and the actual LDAP
|
|
I<filter>. 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<size> method:
|
|
|
|
$numVals = $entry->size("objectclass");
|
|
|
|
One caveat: Many LDAP attributes are case insensitive, but the methods in
|
|
the Ldapp package are not aware of this. Hence, if you compare values with
|
|
case sensitivity, you can experience weird problems. 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<searchURL> method:
|
|
|
|
$entry->searchURL("ldap:///o=netscape.com??sub?(uid=leif");
|
|
|
|
As it turns out, the B<search> method also supports LDAP URL searches. If
|
|
the search filter is a proper URL, we'll 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<search> method you add two
|
|
more options, like
|
|
|
|
$entry = $ldap->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<searchURL> method, add a second argument, which should be 0 or 1.
|
|
|
|
=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:
|
|
|
|
$entry->setDN("uid=leif,ou=people,o=netscape.com");
|
|
|
|
You should not do this for an existing LDAP entry, changing the RDN (or
|
|
DN) for such an entry is currently not supported. It is however something
|
|
we'll be adding in a future release. 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<update> method
|
|
from the Ldapp object:
|
|
|
|
$ldap->update($entry);
|
|
|
|
Or, if you are creating an entirely new object, you must call the B<add>
|
|
method:
|
|
|
|
$ldap->add($entry);
|
|
|
|
If all comes to worse, and you have to remove an entire entry from the
|
|
LDAP server, just call the B<delete> method, like
|
|
|
|
$ldap->delete($entry);
|
|
|
|
You can't use native Perl functions like push() and splice() on attribute
|
|
values, since they won't update the Ldap::Entry class state properly.
|
|
Instead use one of the methods provided in this class, for instance
|
|
|
|
$ldap->addValue("cn", "The Swede");
|
|
$ldap->removeValue("mailAlternateAddress", "leif@mcom.com");
|
|
$ldap->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<hasValue> method, like
|
|
|
|
if ($ldap->hasValue("mail", "leif@netscape.com")) {
|
|
# Do something
|
|
}
|
|
|
|
There is a similar method, B<matchValue>, 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 Ldapp::
|
|
|
|
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<new>
|
|
|
|
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 password.
|
|
|
|
Remember that if you use SSL, the port is (usually) 636.
|
|
|
|
=item B<search>
|
|
|
|
The B<search> method is the main entry point into the Ldapp 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.
|
|
|
|
=item B<searchURL>
|
|
|
|
This is almost identical to B<search>, 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<search> method will actually honor properly formed
|
|
LDAP URL's, and use it if appropriate.
|
|
|
|
=item B<entry>
|
|
|
|
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<update>
|
|
|
|
After modifying an Ldap::Entry entry (see below), use the B<update>
|
|
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<push> or B<splice> to
|
|
modify an entry, the B<update> will not recognize such changes.
|
|
|
|
=item B<delete>
|
|
|
|
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<delete> defaults to delete the current entry, from the last call to
|
|
B<search> or B<entry> .
|
|
|
|
=item B<add>
|
|
|
|
Add a new entry to the LDAP server. Make sure you use the B<new> method
|
|
for the Ldapp::Entry object, to create a proper entry.
|
|
|
|
=item B<close>
|
|
|
|
Close the LDAP connection, and clean up the object. If you don't call this
|
|
directly, the destructor for the Ldapp:: object will do the job for you.
|
|
|
|
=back
|
|
|
|
=head2 MISCELLANEOUS METHODS
|
|
|
|
=over 13
|
|
|
|
=item B<printEntry>
|
|
|
|
Print an entry on the standard output, in a format similar to LDIF. This
|
|
is mostly useful for debugging.
|
|
|
|
=item B<isURL>
|
|
|
|
Returns TRUE or FALSE if the given argument is a properly formed URL.
|
|
|
|
=item B<getError>
|
|
|
|
Return the error code (numeric) from the last LDAP API function
|
|
call. Remember that this can only be called I<after> the successful
|
|
creation of a new Ldapp:: object.
|
|
|
|
=item B<getErrorString>
|
|
|
|
Very much like B<getError>, but return a string with a human readable
|
|
error message.
|
|
|
|
=item B<printError>
|
|
|
|
Print the last error message on standard output.
|
|
|
|
=item B<setRebindProc>
|
|
|
|
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<setDefaultRebindProc>
|
|
|
|
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<normalizeDN>
|
|
|
|
This function will remove all extraneous white spaces in the DN, and also
|
|
change all upper case characters to lower case. By default we'll normalize
|
|
the current DN (from the last search), but you can also provide an
|
|
arbitrary DN as the optional argument. We do not modify the DN in this
|
|
method, we only return a new string that is the normalized version of the
|
|
DN.
|
|
|
|
This method is useful if you need to do string comparisons on DNs, for
|
|
instance during a synchronization process.
|
|
|
|
=back
|
|
|
|
=head1 OBJECT CLASS Ldapp::Entry
|
|
|
|
This is perhaps the most important class, and you'll do most of your
|
|
interaction with this class. You are already familiar with the basics for
|
|
this object class, so this section will describe details for all methods.
|
|
|
|
=head2 CREATING A NEW ENTRY
|
|
|
|
To create a complete new entry, use the B<new> method, for instance
|
|
|
|
$entry = new Ldapp::Entry()
|
|
$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);
|
|
$ldap->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 also adding the
|
|
I<person> and I<inetOrgPerson> classes, we also must provide some more
|
|
attributes, like I<CN> and I<SN>. This is because the object classes have
|
|
these attributes marked as required, and we'd get a schema violation
|
|
without them.
|
|
|
|
=head2 ADDING AND REMOVING ATTRIBUTES AND VALUES
|
|
|
|
Most of these methods are already introduces, so we'll give a brief
|
|
summary.
|
|
|
|
=over 13
|
|
|
|
=item B<remove>
|
|
|
|
This will remove the entire attribute, including all it's values, from the
|
|
entry. Let's say you want to nuke all I<mailAlternateAddress> values:
|
|
|
|
$entry->remove("mailAlternateAddress");
|
|
|
|
=item B<removeValue>
|
|
|
|
Remove a value from an attribute. If we found the attribute, and we
|
|
removed it, we'll return TRUE (1), otherwise FALSE (0).
|
|
|
|
=item B<addValue>
|
|
|
|
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 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 have duplicates.
|
|
|
|
=item B<hasValue>
|
|
|
|
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.
|
|
|
|
=item B<matchValue>
|
|
|
|
This is very similar to B<hasValue>, except it does a regular expression
|
|
match against a full string match. It takes the same arguments, including
|
|
the optional third argument to specify case insensitive matching.
|
|
|
|
=item B<setDN>
|
|
|
|
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. In the future,
|
|
you'll be able to use the B<modifyRDN> method.
|
|
|
|
=item B<getDN>
|
|
|
|
Return the DN for the entry.
|
|
|
|
=item B<modifyRDN>
|
|
|
|
This is currently not implemented. In my copious spare time...
|
|
|
|
=item B<size>
|
|
|
|
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).
|
|
|
|
=item B<exists>
|
|
|
|
Return TRUE if the specified attribute is defined in the LDAP entry.
|
|
|
|
=back
|
|
|
|
=head1 EXAMPLES
|
|
|
|
There are plenty of examples to look at, in the is-ldap/perl directory. If
|
|
you don't have these files, get the distribution from one of the sites below.
|
|
|
|
=head1 INSTALLATION
|
|
|
|
Installing this package is part of the Makefile supplied in the
|
|
package. To install and use this module, you'll first need to download and
|
|
install the LDAP SDK (e.g. from http://developer.netscape.com). To build
|
|
the Perl modules, just do
|
|
|
|
perl5 Makefile.PL
|
|
make
|
|
make install
|
|
|
|
You'll get some questions during the first step, asking you to specify
|
|
where your LDAP SDK installed, and how to configure the package.
|
|
|
|
=head1 AVAILABILITY
|
|
|
|
The latest version of this script, and other related packages, are
|
|
available from
|
|
|
|
http://data/software/
|
|
ftp://ftp.ogre.com/pub/LDAP/ (external)
|
|
|
|
=head1 AUTHOR INFORMATION
|
|
|
|
Address bug reports and comments to:
|
|
leif@netscape.com
|
|
|
|
=head1 CREDITS
|
|
|
|
|
|
|
|
=head1 BUGS
|
|
|
|
None :). But there are lots of things to be added or changed:
|
|
|
|
=over 4
|
|
|
|
=item *
|
|
|
|
Memory usage, it's just a pig.
|
|
|
|
=item *
|
|
|
|
Add support for LDAP v3, including persistanc searches.
|
|
|
|
=item *
|
|
|
|
Clean up the hole call schema for the C SDK API. This is a mess...
|
|
|
|
=item *
|
|
|
|
Add support for modifyRDN.
|
|
|
|
=item *
|
|
|
|
We must support automatica reconnect, and timeouts.
|
|
|
|
=item *
|
|
|
|
Go through all return values, for all functions.
|
|
|
|
=item *
|
|
|
|
Use asynchronous LDAP, and support more than one concurrent LDAP
|
|
operation. This is a tough one...
|
|
|
|
=item *
|
|
|
|
Several minor bugs and issues, on the ToDo list.
|
|
|
|
=back
|
|
|
|
=head1 SEE ALSO
|
|
|
|
L<Ldapc>, L<LdapUtils> and L<Perl>
|
|
|
|
=cut
|