File Coverage

lib/Net/LDAP/SimpleServer/LDIFStore.pm
Criterion Covered Total %
statement 113 127 88.9
branch 22 38 57.8
condition 4 10 40.0
subroutine 25 27 92.5
pod 8 8 100.0
total 172 210 81.9


line stmt bran cond sub pod time code
1             package Net::LDAP::SimpleServer::LDIFStore;
2              
3 26     26   63436 use strict;
  26         79  
  26         808  
4 26     26   156 use warnings;
  26         58  
  26         1175  
5              
6             # ABSTRACT: Data store to support Net::LDAP::SimpleServer
7              
8             our $VERSION = '0.0.20'; # VERSION
9              
10 26     26   453 use 5.010;
  26         105  
11 26     26   151 use Carp qw/carp croak/;
  26         63  
  26         1349  
12 26     26   7549 use UNIVERSAL::isa;
  26         25180  
  26         131  
13 26     26   900 use Scalar::Util qw(blessed reftype);
  26         69  
  26         1824  
14              
15 26     26   9407 use Net::LDAP::LDIF;
  26         376179  
  26         1075  
16 26     26   72223 use Net::LDAP::Util qw/canonical_dn/;
  26         1934  
  26         2300  
17              
18 26     26   9060 use Net::LDAP::SimpleServer::Constant;
  26         89  
  26         35945  
19              
20             sub new {
21 16     16 1 1494 my ( $class, $param ) = @_;
22 16 50       175 croak 'Must pass parameter!' unless defined($param);
23              
24             # empty defaults
25 16         487 my $data = {
26             ldif_object => undef,
27             tree => {},
28             };
29              
30 16         150 my $self = bless( $data, $class );
31 16         259 $self->load($param);
32 14         271 return $self;
33             }
34              
35             sub load {
36 16     16 1 93 my ( $self, $param ) = @_;
37              
38 16 100       338 croak 'Must pass parameter!' unless $param;
39              
40 15 50 33     240 if ( blessed($param) && $param->isa('Net::LDAP::LDIF') ) {
41 0         0 $self->{ldif_object} = $param;
42             }
43             else {
44 15         243 $self->_open_ldif($param);
45             }
46 14         3995 $self->_load_ldif();
47 14         509 return;
48             }
49              
50             sub ldif {
51 0     0 1 0 my $self = shift;
52 0         0 return $self->{ldif_object};
53             }
54              
55             #
56             # opens a filename, a file-handle, or a Net::LDAP::LDIF object
57             #
58             sub _open_ldif {
59 15     15   61 my $self = shift;
60 15   50     104 my $param = shift // '';
61              
62 15   50     370 my $reftype = reftype($param) // '';
63 15 50       106 if ( $reftype eq 'HASH' ) {
64             croak q{Hash parameter must contain a "ldif" parameter}
65 0 0       0 unless exists $param->{ldif};
66              
67             $self->{ldif_object} = Net::LDAP::LDIF->new(
68             $param->{ldif},
69             'r',
70             (
71             exists $param->{ldif_options}
72 0 0       0 ? %{ $param->{ldif_options} }
  0         0  
73             : undef
74             )
75             );
76 0         0 return;
77             }
78              
79             # Then, it must be a filename
80 15 100       425 croak q{Cannot read file "} . $param . q{"} unless -r $param;
81              
82 14         493 $self->{ldif_object} = Net::LDAP::LDIF->new($param);
83             }
84              
85             sub _make_entry_path {
86 22     22   93 my $dn = shift;
87              
88 22 100       445 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
89              
90 22         2277 return [ reverse( split( ',', canonical_dn($dn) ) ) ];
91             }
92              
93             sub _make_entry {
94 42     42   253 my ( $entry, $tree, $current_dn, @path ) = @_;
95              
96 42 50       193 $tree = {} unless defined($tree);
97 42 100       176 if ( scalar(@path) == 0 ) {
98 14         51 $tree->{_object} = $entry;
99             }
100             else {
101 28         90 my $next = $path[0];
102             $tree->{_object} = Net::LDAP::Entry->new($current_dn)
103 28 50       228 unless exists $tree->{_object};
104             $tree->{$next} = _make_entry(
105 28         1014 $entry, $tree->{$next},
106             join( q{,}, $next, $current_dn ),
107             @path[ 1 .. $#path ]
108             );
109             }
110              
111 42         340 return $tree;
112             }
113              
114             sub _add {
115 14     14   73 my ( $self, $entry ) = @_;
116              
117 14         124 my @path = @{ _make_entry_path($entry) };
  14         152  
118 14         10311 my $tree = $self->{tree};
119 14         68 my $next = $path[0];
120 14         220 $tree->{$next} = _make_entry( $entry, $tree->{$next}, @path );
121              
122             # line above is equivalent to
123             # _make_entry( $entry, $tree->{$next}, $next, @path[ 1 .. $#path ] );
124             }
125              
126             #
127             # loads a LDIF file
128             #
129             sub _load_ldif {
130 14     14   101 my $self = shift;
131 14         65 my $ldif = $self->{ldif_object};
132              
133 14         217 while ( not $ldif->eof() ) {
134 14         350 my $entry = $ldif->read_entry();
135 14 50       24017 if ( $ldif->error() ) {
136 0         0 print STDERR "Error msg: ", $ldif->error(), "\n";
137 0         0 print STDERR "Error lines:\n", $ldif->error_lines(), "\n";
138 0         0 next;
139             }
140              
141 14         229 $self->_add($entry);
142             }
143 14         322 $ldif->done();
144             }
145              
146             sub _find_subtree {
147 21     21   2160 my ( $tree, $rdn, @path ) = @_;
148              
149 21 50       81 return unless exists $tree->{$rdn};
150 21 100       96 return $tree->{$rdn} if scalar(@path) == 0;
151 13         57 return _find_subtree( $tree->{$rdn}, @path );
152             }
153              
154             sub find_tree {
155 8     8 1 1987 my $self = shift;
156 8         22 my $dn = shift;
157 8 50       57 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
158              
159 8         404 return _find_subtree( $self->{tree}, @{ _make_entry_path($dn) } );
  8         35  
160             }
161              
162             sub exists_dn {
163 0     0 1 0 my ( $self, $dn ) = @_;
164              
165 0         0 my $tree = $self->find_tree($dn);
166 0         0 return defined($tree);
167             }
168              
169             sub find_entry {
170 3     3 1 1164 my ( $self, $dn ) = @_;
171              
172 3         14 my $tree = $self->find_tree($dn);
173 3 50       18 return $tree->{_object} if defined($tree);
174 0         0 return;
175             }
176              
177             sub _list {
178 6     6   15 my $tree = shift;
179              
180             my @children_trees =
181 6         15 map { $tree->{$_} } ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         16  
  9         35  
  6         24  
182              
183 6         33 return ( $tree->{_object}, ( map { ( _list($_) ) } @children_trees ) );
  3         12  
184             }
185              
186             sub list {
187 1     1 1 720 my $self = shift;
188 1   33     10 my $tree = shift // $self->{tree}->{ ( keys( %{ $self->{tree} } ) )[0] };
  1         7  
189              
190 1         7 return [ _list($tree) ];
191             }
192              
193             sub _list_baseobj {
194 2     2   6 my $self = shift;
195 2         7 my $dn = shift;
196 2         10 my $entry = $self->find_entry($dn);
197              
198 2 50       9 return unless defined($entry);
199              
200 2         12 return [$entry];
201             }
202              
203             sub _list_onelevel {
204 2     2   5 my $self = shift;
205 2         6 my $dn = shift;
206 2         10 my $tree = $self->find_tree($dn);
207              
208 2 50       11 return unless defined($tree);
209             my @children =
210 1         6 map { $tree->{$_}->{_object} }
211 2         6 ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         16  
  2         8  
212              
213 2         12 return [ $tree->{_object}, @children ];
214             }
215              
216             sub _list_subtree {
217 2     2   9 my $self = shift;
218 2         7 my $dn = shift;
219 2         10 my $tree = $self->find_tree($dn);
220              
221 2 50       9 return unless defined($tree);
222 2         11 return [ _list($tree) ];
223             }
224              
225             sub list_with_dn_scope {
226 6     6 1 21900 my ( $self, $dn, $scope ) = @_;
227              
228 6         30 my @funcs = ( \&_list_baseobj, \&_list_onelevel, \&_list_subtree );
229 6         29 return $funcs[$scope]->( $self, $dn );
230             }
231              
232             1; # Magic true value required at end of module
233              
234             __END__