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   43962 use strict;
  26         61  
  26         694  
4 26     26   123 use warnings;
  26         41  
  26         898  
5              
6             # ABSTRACT: Data store to support Net::LDAP::SimpleServer
7              
8             our $VERSION = '0.0.21'; # VERSION
9              
10 26     26   344 use 5.010;
  26         86  
11 26     26   104 use Carp qw/carp croak/;
  26         47  
  26         1064  
12 26     26   5513 use UNIVERSAL::isa;
  26         19106  
  26         84  
13 26     26   704 use Scalar::Util qw(blessed reftype);
  26         50  
  26         1106  
14              
15 26     26   6970 use Net::LDAP::LDIF;
  26         430248  
  26         827  
16 26     26   57084 use Net::LDAP::Util qw/canonical_dn/;
  26         1434  
  26         1589  
17              
18 26     26   7599 use Net::LDAP::SimpleServer::Constant;
  26         78  
  26         26551  
19              
20             sub new {
21 16     16 1 954 my ( $class, $param ) = @_;
22 16 50       117 croak 'Must pass parameter!' unless defined($param);
23              
24             # empty defaults
25 16         186 my $data = {
26             ldif_object => undef,
27             tree => {},
28             };
29              
30 16         106 my $self = bless( $data, $class );
31 16         126 $self->load($param);
32 14         156 return $self;
33             }
34              
35             sub load {
36 16     16 1 78 my ( $self, $param ) = @_;
37              
38 16 100       266 croak 'Must pass parameter!' unless $param;
39              
40 15 50 33     259 if ( blessed($param) && $param->isa('Net::LDAP::LDIF') ) {
41 0         0 $self->{ldif_object} = $param;
42             }
43             else {
44 15         155 $self->_open_ldif($param);
45             }
46 14         2496 $self->_load_ldif();
47 14         413 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   73 my $self = shift;
60 15   50     95 my $param = shift // '';
61              
62 15   50     262 my $reftype = reftype($param) // '';
63 15 50       95 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       311 croak q{Cannot read file "} . $param . q{"} unless -r $param;
81              
82 14         359 $self->{ldif_object} = Net::LDAP::LDIF->new($param);
83             }
84              
85             sub _make_entry_path {
86 22     22   64 my $dn = shift;
87              
88 22 100       383 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
89              
90 22         1433 return [ reverse( split( ',', canonical_dn($dn) ) ) ];
91             }
92              
93             sub _make_entry {
94 42     42   214 my ( $entry, $tree, $current_dn, @path ) = @_;
95              
96 42 50       207 $tree = {} unless defined($tree);
97 42 100       130 if ( scalar(@path) == 0 ) {
98 14         52 $tree->{_object} = $entry;
99             }
100             else {
101 28         92 my $next = $path[0];
102             $tree->{_object} = Net::LDAP::Entry->new($current_dn)
103 28 50       166 unless exists $tree->{_object};
104             $tree->{$next} = _make_entry(
105 28         890 $entry, $tree->{$next},
106             join( q{,}, $next, $current_dn ),
107             @path[ 1 .. $#path ]
108             );
109             }
110              
111 42         207 return $tree;
112             }
113              
114             sub _add {
115 14     14   70 my ( $self, $entry ) = @_;
116              
117 14         38 my @path = @{ _make_entry_path($entry) };
  14         67  
118 14         6922 my $tree = $self->{tree};
119 14         45 my $next = $path[0];
120 14         139 $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   49 my $self = shift;
131 14         57 my $ldif = $self->{ldif_object};
132              
133 14         200 while ( not $ldif->eof() ) {
134 14         291 my $entry = $ldif->read_entry();
135 14 50       16447 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         175 $self->_add($entry);
142             }
143 14         262 $ldif->done();
144             }
145              
146             sub _find_subtree {
147 21     21   1158 my ( $tree, $rdn, @path ) = @_;
148              
149 21 50       43 return unless exists $tree->{$rdn};
150 21 100       52 return $tree->{$rdn} if scalar(@path) == 0;
151 13         27 return _find_subtree( $tree->{$rdn}, @path );
152             }
153              
154             sub find_tree {
155 8     8 1 1130 my $self = shift;
156 8         10 my $dn = shift;
157 8 50       31 $dn = $dn->dn() if $dn->isa('Net::LDAP::Entry');
158              
159 8         211 return _find_subtree( $self->{tree}, @{ _make_entry_path($dn) } );
  8         15  
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 961 my ( $self, $dn ) = @_;
171              
172 3         6 my $tree = $self->find_tree($dn);
173 3 50       8 return $tree->{_object} if defined($tree);
174 0         0 return;
175             }
176              
177             sub _list {
178 6     6   8 my $tree = shift;
179              
180             my @children_trees =
181 6         8 map { $tree->{$_} } ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         6  
  9         20  
  6         12  
182              
183 6         17 return ( $tree->{_object}, ( map { ( _list($_) ) } @children_trees ) );
  3         7  
184             }
185              
186             sub list {
187 1     1 1 369 my $self = shift;
188 1   33     5 my $tree = shift // $self->{tree}->{ ( keys( %{ $self->{tree} } ) )[0] };
  1         5  
189              
190 1         3 return [ _list($tree) ];
191             }
192              
193             sub _list_baseobj {
194 2     2   4 my $self = shift;
195 2         3 my $dn = shift;
196 2         4 my $entry = $self->find_entry($dn);
197              
198 2 50       6 return unless defined($entry);
199              
200 2         6 return [$entry];
201             }
202              
203             sub _list_onelevel {
204 2     2   4 my $self = shift;
205 2         4 my $dn = shift;
206 2         4 my $tree = $self->find_tree($dn);
207              
208 2 50       7 return unless defined($tree);
209             my @children =
210 1         3 map { $tree->{$_}->{_object} }
211 2         3 ( grep { $_ ne '_object' } keys( %{$tree} ) );
  3         8  
  2         4  
212              
213 2         7 return [ $tree->{_object}, @children ];
214             }
215              
216             sub _list_subtree {
217 2     2   4 my $self = shift;
218 2         3 my $dn = shift;
219 2         5 my $tree = $self->find_tree($dn);
220              
221 2 50       6 return unless defined($tree);
222 2         5 return [ _list($tree) ];
223             }
224              
225             sub list_with_dn_scope {
226 6     6 1 12313 my ( $self, $dn, $scope ) = @_;
227              
228 6         15 my @funcs = ( \&_list_baseobj, \&_list_onelevel, \&_list_subtree );
229 6         13 return $funcs[$scope]->( $self, $dn );
230             }
231              
232             1; # Magic true value required at end of module
233              
234             __END__