File Coverage

blib/lib/Wizard/SaveAble/LDAP.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             # Wizard - A Perl package for implementing system administration
4             # applications in the style of Windows wizards.
5             #
6             #
7             # This module is
8             #
9             # Copyright (C) 1999 Jochen Wiedmann
10             # Am Eisteich 9
11             # 72555 Metzingen
12             # Germany
13             #
14             # Email: joe@ispsoft.de
15             # Phone: +49 7123 14887
16             #
17             # and Amarendran R. Subramanian
18             # Grundstr. 32
19             # 72810 Gomaringen
20             # Germany
21             #
22             # Email: amar@ispsoft.de
23             # Phone: +49 7072 920696
24             #
25             # All Rights Reserved.
26             #
27             # You may distribute under the terms of either the GNU General Public
28             # License or the Artistic License, as specified in the Perl README file.
29             #
30             # $Id$
31             #
32              
33 1     1   890 use strict;
  1         3  
  1         388  
34              
35 1     1   6 use Socket ();
  1         2  
  1         30  
36 1     1   5 use Net::LDAP ();
  1         2  
  1         22  
37 1     1   477 use Wizard;
  0            
  0            
38             use Wizard::SaveAble ();
39              
40             package Wizard::SaveAble::LDAP;
41              
42             @Wizard::SaveAble::LDAP::ISA = qw(Wizard::SaveAble);
43             $Wizard::SaveAble::LDAP::VERSION = '0.1001';
44              
45             =pod
46              
47             =head1 NAME
48              
49             Wizard::SaveAble::LDAP - A package for automatically saved objects,
50             that are stored in a LDAP server's directory structure.
51              
52             =head1 SYNOPSIS
53              
54             =head1 DESCRIPTION
55              
56             =cut
57              
58             #'
59             sub _load {
60             my $proto = shift; my $self = shift; my $dn = shift;
61             die "Cannot load object without a valid dn" unless($dn);
62             my $prefix = $self->{'prefix'};
63              
64             my $ldap = LDAPBind($self);
65             my $mesg = $ldap->search(base => $dn,
66             filter => 'objectClass=*',
67             scope => 0) || die "Could not search for $dn: $@";
68             die "Following error occured while searching: code=" . $mesg->code
69             . ", error=" . $mesg->error if $mesg->code;
70             die "Could not find entry $dn " unless $mesg->count;
71             my $entry = $mesg->entry(0); my ($value, $val); my @vals;
72             $self = bless({%$self, map { @vals = $entry->get($_);
73             ($#vals == 0) ? ($prefix . $_ => $vals[0])
74             : ($prefix . $_ => [ @vals ]);
75             } $entry->attributes}, $proto);
76             LDAPUnbind($self);
77             $self;
78             }
79              
80              
81             sub AttrRef2Scalar($$) {
82             my $self = shift; my @keys = @_;
83             my $key; my $prefix = $self->{'prefix'};
84             my ($val, $vals);
85             foreach $key (@keys) {
86             $key = $prefix . $key unless $key =~ /^$prefix/;
87             next unless ref($self->{$key});
88             $vals = $self->{$key};
89             $self->{$key} = shift @$vals;
90             foreach $val (@$vals) {
91             $self->{$key} .= ", $val";
92             }
93             }
94             }
95              
96             sub AttrScalar2Ref($$) {
97             my $self = shift; my @keys = @_;
98             my $key; my $prefix = $self->{'prefix'};
99             foreach $key (@keys) {
100             $key = $prefix . $key unless $key =~ /^$prefix/;
101             next if (ref($self->{$key}) || !($self->{$key}));
102             $self->{$key} = [ split(/\,\s*/, $self->{$key})];
103             }
104             }
105              
106             sub LDAPBind {
107             my $self=shift;
108             my $serverport = $self->{'serverport'};
109             my $ldap = new Net::LDAP($self->{'serverip'},
110             $serverport > 0 ? (port => $serverport)
111             : ());
112             die "Could not initialize LDAP object, probable cause: $!" unless(ref($ldap));
113             $self->{'_wizard_saveable_ldap'} = $ldap;
114             my $dn = $self->{'adminDN'};
115             my $password = $self->{'adminPassword'};
116             $ldap->bind(dn => $self->{'adminDN'},
117             password => $self->{'adminPassword'}
118             ) or die "Cannot bind to LDAP server $@";
119             $ldap->sync;
120             $ldap;
121             }
122              
123             sub LDAPUnbind {
124             my $self=shift;
125             my $ldap = (delete $self->{'_wizard_saveable_ldap'}) || return;
126             $ldap->unbind;
127             }
128              
129             sub new {
130             my $proto = shift;
131             my $self = { @_ };
132             $self->{'serverport'} ||= 0;
133             $self->{'adminPassword'} ||= '';
134             $self->{'prefix'} ||= '';
135             my $serverport = $self->{'serverport'};
136             die "Missing server ip or invalid server ip"
137             unless (($self->{'serverip'} ne '') && (Socket::inet_aton($self->{'serverip'})));
138             die "Missing server port" unless $serverport =~ /^[\d]+$/;
139             die "Missing admin dn" unless $self->{'adminDN'};
140              
141             my $dn = delete $self->{'dn'} if (exists($self->{'dn'}));
142             if (exists($self->{'load'}) and delete $self->{'load'}) {
143             return $proto->_load($self, $dn) if $dn;
144             }
145             bless($self, (ref($proto) || $proto));
146             $self->Modified(1);
147             $self->DN($dn);
148             $self->CreateMe($dn);
149             $self;
150             }
151              
152             sub DN {
153             my $self = shift;
154             if (@_) {
155             $self->{'_wizard_saveable_olddn'} = $self->{'_wizard_saveable_dn'};
156             $self->{'_wizard_saveable_dn'} = shift;
157             }
158             wantarray ? return ($self->{'_wizard_saveable_dn'},
159             $self->{'_wizard_saveable_olddn'})
160             : return $self->{'_wizard_saveable_dn'};
161             }
162              
163             sub Store {
164             my $self = shift;
165              
166             # Create a copy of the object to work with it.
167             my $copy = { %$self };
168             bless($copy, ref($self));
169              
170             return unless delete $copy->{'_wizard_saveable_modified'};
171              
172             my $cme = delete $copy->{'_wizard_saveable_createme'};
173             my $dn = delete $copy->{'_wizard_saveable_dn'}
174             or die "Cannot store object without a valid DN";
175             my $old_dn = delete $copy->{'_wizard_saveable_olddn'} || $dn;
176             my $prefix = delete $copy->{'prefix'};
177             my $ldap = $self->LDAPBind();
178             my $mesg; my @vals;
179             my $attr =[ map {(/^$prefix(.+)$/ && ($copy->{$_} ne ''))
180             ? ($1 => $copy->{$_})
181             : ()
182             } (keys %$copy)];
183             if(!$cme) {
184             if($old_dn ne $dn) {
185             $mesg = $ldap->delete(dn => $old_dn);
186             die "Error deleting old entry '$old_dn', code=" . $mesg->code
187             . " error=" . $mesg->error . "." if $mesg->code;
188             $self->LDAPUnbind();
189             $ldap = $self->LDAPBind();
190             $mesg = $ldap->add(dn => $dn, attr => $attr)
191             or die "Error while adding $dn: $@";
192             } else {
193             $mesg = $ldap->modify(dn => $dn, replace => { @$attr });
194             }
195             } else {
196             $mesg = $ldap->add(dn => $dn, attr => $attr)
197             or die "Error while adding $dn: $@";
198             }
199             die "Object '$dn' already exists: code=" . $mesg->code . ", error="
200             . $mesg->error if($mesg->code == Net::LDAP::Constant::LDAP_ALREADY_EXISTS());
201             die "Following error occured while adding/modifying '$dn': code=" . $mesg->code
202             . ", error=" . $mesg->error if $mesg->code;
203            
204             $self->LDAPUnbind();
205             $self->CreateMe(0);
206             $self->Modified(0);
207             }
208              
209             sub Delete {
210             my $self = shift;
211             my $dn = $self->DN() || die "Missing dn";
212             my $ldap = $self->LDAPBind();
213             my $mesg = $ldap->delete(dn => $dn);
214             die "Following error occured while deleting '$dn': code=" . $mesg->code
215             . ", error=" . $mesg->error if $mesg->code;
216              
217             $self->LDAPUnbind();
218             }
219              
220              
221             1;
222              
223             =pod
224              
225             =head1 AUTHORS AND COPYRIGHT
226              
227             This module is
228              
229             Copyright (C) 1999 Jochen Wiedmann
230             Am Eisteich 9
231             72555 Metzingen
232             Germany
233              
234             Email: joe@ispsoft.de
235             Phone: +49 7123 14887
236              
237             and Amarendran R. Subramanian
238             Grundstr. 32
239             72810 Gomaringen
240             Germany
241              
242             Email: amar@ispsoft.de
243             Phone: +49 7072 920696
244              
245             All Rights Reserved.
246              
247             You may distribute under the terms of either the GNU General Public
248             License or the Artistic License, as specified in the Perl README file.
249              
250              
251             =head1 SEE ALSO
252              
253             L, L, L
254              
255             =cut