6 use Carp (qw(cluck confess));
7 use Encode (qw(encode decode is_utf8));
9 use LiCoM::Config (qw(get_config));
10 use LiCoM::Connection (qw($Ldap));
13 use Net::LDAP::Filter;
17 Person - High level interface for address books using an LDAP-backend.
24 facsimileTelephoneNumber => 1,
29 homePostalAddress => 1,
38 officephone => 'telephoneNumber',
39 fax => 'facsimileTelephoneNumber',
42 firstname => 'givenName',
43 homephone => 'homePhone',
44 address => 'homePostalAddress',
47 cellphone => 'mobile',
48 password => 'userPassword'
59 $obj->{'dn'} = $entry->dn ();
60 $obj->{'ldap'} = $entry;
62 for (keys %ValidFields)
65 my $val = $entry->get_value ($key, asref => $ValidFields{$key});
69 $obj->{$key} = [map { decode ('UTF-8', $_) } (@$val)];
73 $obj->{$key} = decode ('UTF-8', $val);
77 return (bless ($obj, $pkg));
80 =head1 STATIC FUNCTIONS
84 =item LiCoM::Person-E<gt>B<load> (I<$cn>)
86 Loads the given CN and returns the B<Person>-object.
95 my ($retval) = search ($pkg, [[cn => $cn]]);
99 cluck ("CN '$cn' could not be found");
106 =item LiCoM::Person-E<gt>B<create> (B<lastname> =E<gt> I<$lastname>, B<firstname> =E<gt> I<$firstname>, ...)
108 Create a new I<Net::LDAP::Entry>-object and return it's corresponding
118 my $entry = Net::LDAP::Entry->new ();
122 $entry->add (objectClass => [qw(person organizationalPerson inetOrgPerson)]);
127 my $val = $hash{$key};
128 my $field = defined ($ExternalNames{$key}) ? $ExternalNames{$key} : $key;
130 if (!defined ($ValidFields{$field}))
132 warn ("Invalid field $field");
136 if ($ValidFields{$field})
138 if (ref ($val) eq 'ARRAY')
140 $entry->add ($field => [map { encode ('UTF-8', $_) } (@$val)]) if (@$val);
144 $entry->add ($field => [encode ('UTF-8', $val)]) if ($val);
148 warn ("You cannot pass ref-type " . ref ($val));
154 if (ref ($val) eq 'ARRAY')
156 $temp = encode ('UTF-8', $val->[0]);
160 $temp = encode ('UTF-8', $val);
164 warn ("You cannot pass ref-type " . ref ($val));
167 $entry->add ($field => $temp) if (defined ($temp) and $temp);
171 # $sn and $gn are UTF-8
172 my $sn = $entry->get_value ('sn');
173 my $gn = $entry->get_value ('givenName');
175 if (!defined ($sn) or !defined ($gn))
177 warn ("sn or givenName not given");
181 $ou = encode ('UTF-8', 'Person');
182 $dn = "cn=$sn $gn,ou=$ou," . encode ('UTF-8', get_config ('base_dn'));
184 $entry->add (cn => "$sn $gn", ou => $ou);
187 $entry->changetype ('add');
188 my $mesg = $entry->update ($Ldap);
190 if ($mesg->is_error ())
192 my $tmp = decode ('UTF-8', $dn);
193 warn ("Error while creating entry '$tmp' on LDAP server: " . $mesg->error_text ());
197 return (new ($pkg, $entry));
200 =item LiCoM::Person-E<gt>B<search> (B<firstname> =E<gt> I<"Flor*">)
202 Search for the given patterns. Returns a list of I<Person>-objects.
207 [field => value], # OR
236 $field = $ExternalNames{$field} if (defined ($ExternalNames{$field}));
237 if (!defined ($ValidFields{$field}))
239 warn ("Not a valid field: $field");
243 $value =~ s/([\(\)\\])/\\$1/g;
245 confess ("Value is not UTF-8 encoded: `$value'") if (!is_utf8 ($value));
247 push (@disjunc, "($field=$value)");
253 if (scalar (@disjunc) == 1)
259 $tmp = join ('', '(|', @disjunc, ')');
261 push (@konjunct, $tmp);
267 $filter = join ('', '(&(objectclass=inetOrgPerson)', @konjunct, ')');
271 $filter = '(objectclass=inetOrgPerson)';
274 $mesg = $Ldap->search
276 base => 'ou=Person,' . get_config ('base_dn'),
277 filter => encode ('UTF-8', $filter)
280 if ($mesg->is_error ())
282 warn ("Error while querying LDAP server: " . $mesg->error_text ());
286 for ($mesg->entries ())
289 my $obj = new ($pkg, $entry);
291 push (@retval, $obj);
297 =item LiCoM::Person-E<gt>B<get_user> (I<$dn>)
299 Returns the cn and, if defined, the user-id of this dn.
307 my ($search) = $dn =~ m/cn\s*=\s*([^,]+)/i;
309 return unless ($search);
314 my $mesg = $Ldap->search
316 base => 'ou=Person,' . get_config ('base_dn'),
317 filter => "(cn=$search)"
320 if ($mesg->is_error ())
322 cluck ("Error while querying LDAP server: " . $mesg->error_text ());
326 for ($mesg->entries ())
329 my ($t_cn) = $e->get_value ('cn', asref => 0);
330 my ($t_id) = $e->get_value ('uid', asref => 0);
348 =item I<$obj>-E<gt>B<delete> ()
357 my $entry = $obj->{'ldap'};
359 $entry->changetype ('delete');
361 $entry->update ($Ldap);
366 =item I<$obj>-E<gt>B<lastname> ([I<$lastname>])
368 Get or set the lastname.
374 confess ("Wrong number of arguments") if (@_ != 3);
383 my $entry = $obj->{'ldap'};
385 if (($sn eq $obj->{'sn'}) && ($gn eq $obj->{'givenName'}))
390 $hash_new{$_} = $obj->{$_} for (keys %ValidFields);
391 $hash_new{'sn'} = $sn;
392 $hash_new{'givenName'} = $gn;
393 delete ($hash_new{'cn'});
395 $obj_new = LiCoM::Person->create (%hash_new)
396 or confess ("Cannot duplicate LDAP entry");
402 return ($obj->{'dn'});
411 _update_dn ($obj, shift, $obj->{'givenName'});
414 return ($obj->{'sn'});
417 =item I<$obj>-E<gt>B<firstname> ([I<$firstname>])
419 Get or set the firstname.
429 _update_dn ($obj, $obj->{'sn'}, shift);
432 return ($obj->{'givenName'});
435 =item I<$obj>-E<gt>B<name> ()
444 return ($obj->{'cn'});
447 =item I<$obj>-E<gt>B<address> ([I<@address>])
449 =item I<$obj>-E<gt>B<homephone> ([I<@homephone>])
451 =item I<$obj>-E<gt>B<cellphone> ([I<@cellphone>])
453 =item I<$obj>-E<gt>B<officephone> ([I<@officephone>])
455 =item I<$obj>-E<gt>B<fax> ([I<@fax>])
457 =item I<$obj>-E<gt>B<mail> ([I<@mail>])
459 =item I<$obj>-E<gt>B<uri> ([I<@uri>])
461 Get or set the attribute. This is the same as calling S<I<$obj>-E<gt>B<set>
462 (I<$field>, I<\@values>)> or S<I<$obj>-E<gt>B<get> (I<$field>)>.
470 my $field = $Person::AUTOLOAD;
472 return (undef) unless ($field);
476 return (set ($obj, $field, @values ? [@values] : undef))
479 =item I<$obj>-E<gt>B<get> (I<$field>)
481 Returs the value(s) of field I<$field>.
492 return (set ($obj, $field, undef));
496 return (scalar (set ($obj, $field, undef)));
500 =item I<$obj>-E<gt>B<set> (I<$field>, I<\@values>)
502 Sets the field I<$field> to the value(s) I<\@valued>. Pass an empty array-ref
511 my $value = @_ ? shift : undef;
512 my $entry = $obj->{'ldap'};
514 if (defined ($ExternalNames{$field}))
516 $field = $ExternalNames{$field};
518 if (!defined ($ValidFields{$field}))
523 if (defined ($value))
525 $_ = encode ('UTF-8', $_) for (@$value);
527 $entry->changetype ('modify');
529 if ($ValidFields{$field})
531 $entry->replace ($field, [@$value]);
532 $obj->{$field} = $value;
536 splice (@$value, 1) if (scalar (@$value) > 1);
537 $entry->replace ($field, $value);
538 $obj->{$field} = $value->[0];
541 $entry->update ($Ldap);
544 if (!defined ($obj->{$field}) and $ValidFields{$field})
549 if (wantarray () and $ValidFields{$field})
551 return (@{$obj->{$field}});
555 return ($obj->{$field});
563 Florian octo Forster E<lt>octo at verplant.orgE<gt>