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 19     19   113054 use strict;
  19         55  
  19         440  
4 19     19   78 use warnings;
  19         29  
  19         658  
5              
6             # ABSTRACT: Data store to support Net::LDAP::SimpleServer
7              
8             our $VERSION = '0.0.19'; # VERSION
9              
10 19     19   261 use 5.010;
  19         47  
11 19     19   157 use Carp qw/carp croak/;
  19         52  
  19         995  
12 19     19   4700 use UNIVERSAL::isa;
  19         14705  
  19         70  
13 19     19   583 use Scalar::Util qw(blessed reftype);
  19         41  
  19         1014  
14              
15 19     19   5728 use Net::LDAP::LDIF;
  19         380995  
  19         623  
16 19     19   43388 use Net::LDAP::Util qw/canonical_dn/;
  19         1104  
  19         1356  
17              
18 19     19   5874 use Net::LDAP::SimpleServer::Constant;
  19         56  
  19         19834  
19              
20             sub new {
21 11     11 1 1045 my ( $class, $param ) = @_;
22 11 50       78 croak 'Must pass parameter!' unless defined($param);
23              
24             # empty defaults
25 11         117 my $data = {
26             ldif_object => undef,
27             tree => {},
28             };
29              
30 11         49 my $self = bless( $data, $class );
31 11         72 $self->load($param);
32 9         89 return $self;
33             }
34              
35             sub load {
36 11     11 1 61 my ( $self, $param ) = @_;
37              
38 11 100       210 croak 'Must pass parameter!' unless $param;
39              
40 10 50 33     120 if ( blessed($param) && $param->isa('Net::LDAP::LDIF') ) {
41 0         0 $self->{ldif_object} = $param;
42             }
43             else {
44 10         97 $self->_open_ldif($param);
45             }
46 9         1668 $self->_load_ldif();
47 9         258 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 10     10   41 my $self = shift;
60 10   50     58 my $param = shift // '';
61              
62 10   50     168 my $reftype = reftype($param) // '';
63 10 50       77 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 10 100       285 croak q{Cannot read file "} . $param . q{"} unless -r $param;
81              
82 9         239 $self->{ldif_object} = Net::LDAP::LDIF->new($param);
83             }
84              
85             sub _make_entry_path {
86 17     17   35 my $dn = shift;
87              
88 17 100       259 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
89              
90 17         1060 return [ reverse( split( ',', canonical_dn($dn) ) ) ];
91             }
92              
93             sub _make_entry {
94 27     27   115 my ( $entry, $tree, $current_dn, @path ) = @_;
95              
96 27 50       96 $tree = {} unless defined($tree);
97 27 100       84 if ( scalar(@path) == 0 ) {
98 9         26 $tree->{_object} = $entry;
99             }
100             else {
101 18         42 my $next = $path[0];
102             $tree->{_object} = Net::LDAP::Entry->new($current_dn)
103 18 50       98 unless exists $tree->{_object};
104             $tree->{$next} = _make_entry(
105 18         456 $entry, $tree->{$next},
106             join( q{,}, $next, $current_dn ),
107             @path[ 1 .. $#path ]
108             );
109             }
110              
111 27         114 return $tree;
112             }
113              
114             sub _add {
115 9     9   42 my ( $self, $entry ) = @_;
116              
117 9         24 my @path = @{ _make_entry_path($entry) };
  9         37  
118 9         4204 my $tree = $self->{tree};
119 9         27 my $next = $path[0];
120 9         104 $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 9     9   27 my $self = shift;
131 9         43 my $ldif = $self->{ldif_object};
132              
133 9         118 while ( not $ldif->eof() ) {
134 9         187 my $entry = $ldif->read_entry();
135 9 50       9667 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 9         118 $self->_add($entry);
142             }
143 9         158 $ldif->done();
144             }
145              
146             sub _find_subtree {
147 21     21   1292 my ( $tree, $rdn, @path ) = @_;
148              
149 21 50       50 return unless exists $tree->{$rdn};
150 21 100       61 return $tree->{$rdn} if scalar(@path) == 0;
151 13         31 return _find_subtree( $tree->{$rdn}, @path );
152             }
153              
154             sub find_tree {
155 8     8 1 1265 my $self = shift;
156 8         16 my $dn = shift;
157 8 50       36 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
158              
159 8         235 return _find_subtree( $self->{tree}, @{ _make_entry_path($dn) } );
  8         20  
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 708 my ( $self, $dn ) = @_;
171              
172 3         9 my $tree = $self->find_tree($dn);
173 3 50       11 return $tree->{_object} if defined($tree);
174 0         0 return;
175             }
176              
177             sub _list {
178 6     6   13 my $tree = shift;
179              
180             my @children_trees =
181 6         10 map { $tree->{$_} } ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         9  
  9         21  
  6         14  
182              
183 6         20 return ( $tree->{_object}, ( map { ( _list($_) ) } @children_trees ) );
  3         10  
184             }
185              
186             sub list {
187 1     1 1 417 my $self = shift;
188 1   33     6 my $tree = shift // $self->{tree}->{ ( keys( %{ $self->{tree} } ) )[0] };
  1         5  
189              
190 1         4 return [ _list($tree) ];
191             }
192              
193             sub _list_baseobj {
194 2     2   4 my $self = shift;
195 2         4 my $dn = shift;
196 2         6 my $entry = $self->find_entry($dn);
197              
198 2 50       7 return unless defined($entry);
199              
200 2         7 return [$entry];
201             }
202              
203             sub _list_onelevel {
204 2     2   5 my $self = shift;
205 2         4 my $dn = shift;
206 2         5 my $tree = $self->find_tree($dn);
207              
208 2 50       8 return unless defined($tree);
209             my @children =
210 1         5 map { $tree->{$_}->{_object} }
211 2         5 ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         7  
  2         7  
212              
213 2         10 return [ $tree->{_object}, @children ];
214             }
215              
216             sub _list_subtree {
217 2     2   6 my $self = shift;
218 2         4 my $dn = shift;
219 2         8 my $tree = $self->find_tree($dn);
220              
221 2 50       9 return unless defined($tree);
222 2         7 return [ _list($tree) ];
223             }
224              
225             sub list_with_dn_scope {
226 6     6 1 13936 my ( $self, $dn, $scope ) = @_;
227              
228 6         23 my @funcs = ( \&_list_baseobj, \&_list_onelevel, \&_list_subtree );
229 6         19 return $funcs[$scope]->( $self, $dn );
230             }
231              
232             1; # Magic true value required at end of module
233              
234             __END__