File Coverage

blib/lib/Tie/LDAP.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             # -*- mode: perl -*-
2             #
3             # $Id: LDAP.pm,v 1.3 2000/03/28 13:15:56 tai Exp $
4             #
5              
6             package Tie::LDAP;
7              
8             =head1 NAME
9              
10             Tie::LDAP - Tie LDAP database to Perl hash.
11              
12             =head1 SYNOPSIS
13              
14             use Tie::LDAP;
15              
16             tie %LDAP, 'Tie::LDAP', {
17             host => $host, # LDAP hostname (defaults to 127.0.0.1)
18             port => $port, # Port number (defaults to 389)
19             user => $user, # Full DN used to access LDAP database
20             pass => $pass, # Password used with above DN
21             base => $base, # Base DN used for each/keys/values operation
22             };
23              
24             =head1 DESCRIPTION
25              
26             This library allows you to tie LDAP database to Perl hash.
27             Once tied, all hash operation will cause corresponding LDAP
28             operation, as you would (probably) expect.
29              
30             Referencing tied hash will return hash reference to named
31             LDAP entry that holds lowercased attribute as hash key, and
32             reference to ARRAY containing data as hash value.
33              
34             Storing data is as easy as fetching: just push hash reference
35             - with the same structure as fetched hash - back in.
36              
37             Also, fetching/storing data into fetched hash reference will
38             work as expected - it will manipulate corresponding field in
39             fetched LDAP entry.
40              
41             =head1 EXAMPLE
42              
43             Here's a brief example of how you can use this module:
44              
45             use Tie::LDAP;
46              
47             ## connect
48             tie %LDAP, 'Tie::LDAP', { base => 'o=IMASY, c=JP' };
49              
50             ## lookup entry for [dn: cn=tai, o=IMASY, c=JP]
51             $info = $LDAP{q{cn=tai, o=IMASY, c=JP}};
52              
53             ## lookup each attributes
54             $user = $info->{username}->[0];
55             $mail = @{$info->{mailaddr}};
56              
57             ## update each attributes
58             $info->{username} = ['newname'];
59             $info->{mailaddr} = ['tai@imasy.or.jp', 'tyamada@tk.elec.waseda.ac.jp'];
60              
61             ## update entry
62             $LDAP{q{cn=tai, o=IMASY, c=JP}} = {
63             username => ['newname'],
64             mailaddr => ['tai@imasy.or.jp', 'tyamada@tk.elec.waseda.ac.jp'],
65             };
66              
67             ## dump database (under base DN of [o=IMASY, c=JP]) in LDIF style
68             while (my($dn, $hash) = each %LDAP) {
69             print "dn: $dn\n";
70             while (my($name, $list) = each %{$hash}) {
71             foreach (@{$list}) {
72             print "$name: $_\n";
73             }
74             }
75             print "\n";
76             }
77              
78             ## disconnect
79             untie %LDAP;
80              
81             =cut
82              
83 1     1   6313 use strict;
  1         2  
  1         41  
84             #use diagnostics;
85              
86 1     1   6 use Carp;
  1         1  
  1         69  
87 1     1   1450 use Net::LDAPapi;
  0            
  0            
88             use Tie::LDAP::Entry;
89              
90             use vars qw($DEBUG $VERSION);
91              
92             $DEBUG = 0;
93             $VERSION = '0.06';
94              
95             sub TIEHASH {
96             my $name = shift;
97             my $opts = shift;
98             my $port = $opts->{port} || 389;
99             my $host = $opts->{host} || '127.0.0.1';
100             my $conn = new Net::LDAPapi($opts->{host}, $opts->{port}) || croak($@);
101             my $mesg;
102              
103             print STDERR "[$name] TIEHASH\n" if $DEBUG;
104              
105             $conn->set_option(LDAP_OPT_SIZELIMIT, $opts->{maxsize} || 5000);
106             $conn->set_option(LDAP_OPT_TIMELIMIT, $opts->{maxwait} || 5000);
107              
108             unless ($conn->bind_s($opts->{user}, $opts->{pass}) == LDAP_SUCCESS) {
109             croak($conn->errstring);
110             }
111             bless { conn => $conn, base => $opts->{base} }, $name;
112             }
113              
114             sub FETCH {
115             my $self = shift;
116             my $path = shift;
117             my $conn = $self->{conn};
118             my $mesg = $conn->search($path, LDAP_SCOPE_BASE, '(!( = ))', [], 0);
119             my $data = {};
120              
121             print STDERR "[$self] FETCH\n" if $DEBUG;
122             print STDERR "[$self] FETCH - path: $path\n" if $DEBUG;
123              
124             return undef unless $mesg >= 0;
125             return undef unless $conn->result($mesg, 0, -1) != -1;
126             return undef unless $conn->first_entry;
127              
128             ##
129             for (my $s = $conn->first_attribute; $s ; $s = $conn->next_attribute) {
130             $data->{$s} = [$conn->get_values_len($s)];
131             }
132             $conn->msgfree;
133             $conn->abandon($mesg);
134              
135             ##
136             tie %{$data}, 'Tie::LDAP::Entry', {
137             path => $path,
138             data => { %{$data} },
139             conn => $self->{conn},
140             };
141             return $data;
142             }
143              
144             sub STORE {
145             my $self = shift;
146             my $path = shift;
147             my $data = shift;
148              
149             print STDERR "[$self] STORE\n" if $DEBUG;
150              
151             $self->{conn}->delete_s($path);
152             $self->{conn}->add_s($path, $data);
153             }
154              
155             sub DELETE {
156             my $self = shift;
157             my $path = shift;
158              
159             print STDERR "[$self] DELETE\n" if $DEBUG;
160             print STDERR "[$self] DELETE - path: $path\n" if $DEBUG;
161              
162             $self->{conn}->delete_s($path);
163             }
164              
165             sub CLEAR {
166             my $self = shift;
167             my $path;
168              
169             print STDERR "[$self] CLEAR\n" if $DEBUG;
170              
171             $path = $self->FIRSTKEY || return;
172             do {
173             $self->DELETE($path);
174             } while ($path = $self->NEXTKEY);
175             }
176              
177             sub EXISTS {
178             my $self = shift;
179             my $path = shift;
180              
181             print STDERR "[$self] EXISTS\n" if $DEBUG;
182              
183             $self->FETCH($path);
184             }
185              
186             sub FIRSTKEY {
187             my $self = shift;
188             my $conn = $self->{conn};
189             my $path;
190              
191             print STDERR "[$self] FIRSTKEY\n" if $DEBUG;
192              
193             return undef unless $self->{base};
194              
195             $self->{mesg} = $conn->search($self->{base},
196             LDAP_SCOPE_ONELEVEL, '(!(dn=))', [], 0);
197              
198             return undef if $self->{mesg} < 0;
199              
200             $self->NEXTKEY;
201             }
202              
203             sub NEXTKEY {
204             my $self = shift;
205             my $last = shift;
206             my $conn = $self->{conn};
207             my $path;
208              
209             print STDERR "[$self] NEXTKEY\n" if $DEBUG;
210              
211             return undef unless $conn->result($self->{mesg}, 0, -1) != -1;
212             return undef unless $conn->first_entry;
213              
214             $path = $conn->get_dn;
215              
216             print STDERR "[$self] NEXTKEY - path: $path\n" if $DEBUG;
217              
218             $conn->msgfree;
219             $path;
220             }
221              
222             sub DESTROY {
223             my $self = shift;
224              
225             print STDERR "[$self] DESTROY\n" if $DEBUG;
226              
227             $self->{conn}->unbind;
228             }
229              
230             =head1 BUGS
231              
232             Doing each/keys/values operation to tied hash works (as shown in
233             example), but could be _very_ slow, depending on the size of the
234             database. This is because all operation is done synchronously.
235              
236             Also, though this is not a bug, substituting empty array
237             to tied hash will cause whole database to be cleared out.
238              
239             =head1 COPYRIGHT
240              
241             Copyright 1998-2000, T. Yamada .
242             All rights reserved.
243              
244             This program is free software; you can redistribute it
245             and/or modify it under the same terms as Perl itself.
246              
247             =head1 SEE ALSO
248              
249             L
250              
251             =cut
252              
253             1;