File Coverage

blib/lib/Template/Plugin/LDAP.pm
Criterion Covered Total %
statement 27 118 22.8
branch 0 30 0.0
condition 0 17 0.0
subroutine 9 25 36.0
pod 3 4 75.0
total 39 194 20.1


line stmt bran cond sub pod time code
1             # Copyright (c) 2001 Dominic Mitchell.
2             # Portions Copyright (c) 2007-2009 Gavin Henry - ,
3             # Suretec Systems Ltd.
4             #
5             # Redistribution and use in source and binary forms, with or without
6             # modification, are permitted provided that the following conditions
7             # are met:
8             # 1. Redistributions of source code must retain the above copyright
9             # notice, this list of conditions and the following disclaimer.
10             # 2. Redistributions in binary form must reproduce the above copyright
11             # notice, this list of conditions and the following disclaimer in the
12             # documentation and/or other materials provided with the distribution.
13             #
14             # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15             # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16             # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17             # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18             # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19             # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20             # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21             # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22             # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23             # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24             # SUCH DAMAGE.
25             #
26             # @(#) $Id: LDAP.pm 1318 2007-03-29 12:05:03Z dom $
27             #
28              
29             package Template::Plugin::LDAP;
30              
31 1     1   1062 use strict;
  1         2  
  1         40  
32 1     1   5 use vars qw( $VERSION );
  1         2  
  1         51  
33 1     1   15 use base qw( Template::Plugin );
  1         2  
  1         886  
34              
35 1     1   18500 use Template::Exception;
  1         1119  
  1         31  
36 1     1   4426 use Net::LDAP;
  1         350059  
  1         13  
37              
38             $VERSION = ( qw( $Revision: 1318 $ ) )[1];
39              
40             sub new {
41 0     0 1   my $class = shift;
42 0           my $context = shift;
43 0           my $self = {};
44 0           bless $self, $class;
45 0           $self->_context( $context );
46 0 0         $self->connect( @_ ) if @_;
47 0           return $self;
48             }
49              
50             sub _context {
51 0     0     my $self = shift;
52 0 0         $self->{ _context } = $_[0] if @_;
53 0           return $self->{ _context };
54             }
55              
56             sub _ldap {
57 0     0     my $self = shift;
58 0 0         $self->{ _ldap } = $_[0] if @_;
59 0           return $self->{ _ldap };
60             }
61              
62             # connect(host[:port], user, password);
63             sub connect {
64 0     0 1   my $self = shift;
65 0 0         my $params = ref $_[-1] eq 'HASH' ? pop( @_ ) : {};
66 0           my ( $host, $port, $user, $pass );
67              
68             $host = shift
69             || $params->{ host }
70 0   0       || $self->throw( "no ldap host specified" );
71             $port = ( $host =~ m/:(\d+)$/ )[0]
72             || $params->{ port }
73 0   0       || getservbyname( "ldap", "tcp" )
74             || 389;
75 0   0       $user = shift || $params->{ user };
76 0   0       $pass = shift || $params->{ pass };
77              
78 0 0         my $ldap = Net::LDAP->new( $host, port => $port )
79             or return $self->throw( "ldap connect: $@" );
80 0 0 0       if ( $user || $pass ) {
81 0           $ldap->bind( $user, password => $pass );
82             }
83             else {
84 0           $ldap->bind; # Anonymous bind.
85             }
86 0           $self->_ldap( $ldap );
87              
88 0           return '';
89             }
90              
91             # search takes the same arguments as Net::LDAP->search().
92             sub search {
93 0     0 1   my $self = shift;
94 0 0         my $params = ref $_[-1] eq 'HASH' ? pop( @_ ) : { @_ };
95              
96 0           my $mesg = $self->_ldap->search( %$params );
97 0 0         $self->throw( $mesg->error )
98             if $mesg->code;
99              
100 0           return Template::Plugin::LDAP::Iterator->new( $mesg );
101             }
102              
103             sub throw {
104 0     0 0   die Template::Exception->new( 'ldap', join('', @_) );
105             }
106              
107             package Template::Plugin::LDAP::Iterator;
108              
109 1     1   662 use strict;
  1         2  
  1         45  
110              
111 1     1   7 use base qw( Template::Iterator );
  1         3  
  1         1006  
112              
113             sub new {
114 0     0     my ( $class, $mesg, $params ) = @_;
115 0           my $self = bless {}, $class;
116 0           $self->_mesg( $mesg );
117 0           return $self;
118             }
119              
120             {
121             my @accessors = qw( _mesg _started PREV NEXT ITEM FIRST LAST COUNT INDEX );
122             foreach my $a ( @accessors ) {
123 1     1   1635 no strict 'refs';
  1         4  
  1         570  
124             *{ $a } = sub {
125 0     0     my $self = shift;
126 0 0         $self->{ $a } = $_[0] if @_;
127 0           return $self->{ $a };
128             }
129             }
130             }
131              
132             sub get_first {
133 0     0     my $self = shift;
134 0           $self->_started( 1 );
135              
136 0           $self->PREV( undef );
137 0           $self->ITEM( undef );
138 0           $self->FIRST( 2 ); # ???
139 0           $self->LAST( 0 );
140 0           $self->COUNT( 0 );
141 0           $self->INDEX( -1 );
142              
143 0           $self->_fetchentry;
144              
145 0           return $self->get_next;
146             }
147              
148             sub get_next {
149 0     0     my $self = shift;
150 0           my $data;
151              
152 0           $self->INDEX( $self->INDEX + 1 );
153 0           $self->COUNT( $self->COUNT + 1 );
154              
155 0 0         $self->FIRST( $self->FIRST - 1 )
156             if $self->FIRST;
157              
158 0 0         return ( undef, Template::Constants::STATUS_DONE )
159             unless $data = $self->NEXT;
160              
161 0           $self->PREV( $self->ITEM );
162              
163 0           $self->_fetchentry;
164              
165 0           $self->ITEM( $data );
166 0           return ( $data, Template::Constants::STATUS_OK );
167             }
168              
169             sub get {
170 0     0     my $self = shift;
171 0 0         my ( $data, $error ) = $self->STARTED ? $self->get_next : $self->get_first;
172 0           return $data;
173             }
174              
175             sub get_all {
176 0     0     my $self = shift;
177 0           my $mesg = $self->_mesg;
178 0           my $error;
179              
180 0           my $data =
181 0           [ map { Template::Plugin::LDAP::Entry->new( $_ ) } $mesg->entries ];
182 0 0         unshift @$data, $self->NEXT # XXX Is this needed?
183             if $self->NEXT;
184 0           $self->LAST( 1 );
185 0           $self->NEXT( undef );
186              
187 0           return $data;
188             }
189              
190             sub _fetchentry {
191 0     0     my $self = shift;
192 0           my $mesg = $self->_mesg;
193              
194             # XXX We should probably use our own wrapper object here.
195 0   0       my $data = $mesg->shift_entry || do {
196             $self->LAST( 1 );
197             $self->NEXT( undef );
198             return;
199             };
200 0           $data = Template::Plugin::LDAP::Entry->new( $data );
201 0           $self->NEXT( $data );
202 0           return;
203             }
204              
205             package Template::Plugin::LDAP::Entry;
206              
207             sub new {
208 0     0     my ( $class, $entry ) = @_;
209 0           my $self = { _entry => $entry };
210 0           foreach my $attrib ( $entry->attributes(nooptions => 1)) {
211 1     1   7 no strict 'refs';
  1         3  
  1         211  
212 0 0         next if defined &{"$class\::\L$attrib"};
  0            
213 0           *{"$class\::\L$attrib"} = sub {
214 0 0   0     if ( $_[0]->{ _entry }->exists( $attrib ) ) {
215 0           return $_[0]->{ _entry }->get_value( $attrib );
216             } else {
217 0           return "";
218             }
219             }
220 0           }
221 0           bless $self, $class;
222 0           return $self;
223             }
224              
225             sub dn {
226 0     0     my $self = shift;
227 0           return $self->{ _entry }->dn;
228             }
229              
230             1;
231             __END__