File Coverage

blib/lib/Apache/Htgroup.pm
Criterion Covered Total %
statement 54 64 84.3
branch 11 20 55.0
condition 1 3 33.3
subroutine 9 11 81.8
pod 9 9 100.0
total 84 107 78.5


line stmt bran cond sub pod time code
1             package Apache::Htgroup;
2              
3             =head1 NAME
4              
5             Apache::Htgroup - Manage Apache authentication group files
6              
7             =head1 SYNOPSIS
8              
9             use Apache::Htgroup;
10             $htgroup = Apache::Htgroup->load($path_to_groupfile);
11             &do_something if $htgroup->ismember($user, $group);
12             $htgroup->adduser($user, $group);
13             $htgroup->deleteuser($user, $group);
14             $htgroup->deletegroup( $group );
15             $htgroup->save;
16              
17             =head1 DESCRIPTION
18              
19             Manage Apache htgroup files
20              
21             Please note that this is I a mod_perl module. Please also note
22             that there is another module that does similar things
23             (HTTPD::UserManage) and that this is a more simplistic module,
24             not doing all the things that one does.
25              
26             =head2 METHODS
27              
28             The following methods are provided by this module.
29              
30             =cut
31              
32 4     4   39210 use strict;
  4         8  
  4         161  
33 4     4   21 use vars qw($VERSION);
  4         10  
  4         4086  
34             $VERSION = (qw($Revision: 1.23 $))[1];
35              
36             # sub new, load {{{
37              
38             =head2 load
39              
40             $htgroup = Apache::Htgroup->load($path_to_groupfile);
41              
42             Returns an Apache::Htgroup object.
43              
44             =head2 new
45              
46             $htgroup = Apache::Htgroup->new();
47             $htgroup = Apache::Htgroup->new( $path_to_groupfile );
48              
49             Creates a new, empty group file. If the specified file already exists,
50             loads the contents of that file. If no filename is specified, you can
51             create a group file in memory, and save it later.
52              
53             =cut
54              
55 2     2 1 28 sub new { return load(@_) }
56              
57             sub load {
58 3     3 1 20 my ( $class, $file ) = @_;
59 3         14 my $self = bless {
60             groupfile => $file,
61             }, $class;
62 3         15 $self->groups;
63              
64 3         9 return $self;
65             }
66              
67             #}}}
68              
69             # sub adduser {{{
70              
71             =head2 adduser
72              
73             $htgroup->adduser( $username, $group );
74              
75             Adds the specified user to the specified group.
76              
77             =cut
78              
79             sub adduser {
80 2     2 1 828 my $self = shift;
81 2         5 my ( $user, $group ) = @_;
82              
83 2 50       8 return (1) if $self->ismember( $user, $group );
84 2         7 $self->{groups}->{$group}->{$user} = 1;
85              
86 2         5 return (1);
87             }
88              
89             #}}}
90              
91             # sub deleteuser {{{
92              
93             =head2 deleteuser
94              
95             $htgroup->deleteuser($user, $group);
96              
97             Removes the specified user from the group.
98              
99             =cut
100              
101             sub deleteuser {
102 0     0 1 0 my $self = shift;
103 0         0 my ( $user, $group ) = @_;
104              
105 0         0 delete $self->{groups}->{$group}->{$user};
106 0         0 return (1);
107             } # }}}
108              
109             # sub groups {{{
110              
111             =head2 groups
112              
113             $groups = $htgroup->groups;
114              
115             Returns a (reference to a) hash of the groups. The key is the name
116             of the group. Each value is a hashref, the keys of which are the
117             group members. I suppose there may be some variety of members
118             method in the future, if anyone thinks that would be useful.
119              
120             It is expected that this method will not be called directly, and
121             it is provided as a convenience only.
122              
123             Please see the section below about internals for an example
124             of the data structure.
125              
126             =cut
127              
128             sub groups {
129 3     3 1 7 my $self = shift;
130              
131 3 50       23 return $self->{groups} if defined $self->{groups};
132              
133 3         12 $self->reload;
134              
135 3         6 return $self->{groups};
136             } # }}}
137              
138             # sub reload {{{
139              
140             =head2 reload
141              
142             $self->reload;
143              
144             If you have not already called save(), you can call reload()
145             and get back to the state of the object as it was loaded from
146             the original file.
147              
148             =cut
149              
150             sub reload {
151 4     4 1 8 my $self = shift;
152              
153 4 100       14 if ( $self->{groupfile} ) {
154              
155 1 50       48 open( FILE, $self->{groupfile} )
156             || die ("Was unable to open group file $self->{groupfile}: $!");
157 1         31 while ( my $line = ) {
158 3         6 chomp $line;
159              
160             #
161             # Allow for multiple spaces after the colon.
162             # Allow for groups with no users.
163 3         16 $line =~ /^([^:]+):(\s+)?(.*)?/;
164 3         8 my $group = $1;
165 3         8 my $members = $3;
166              
167             #
168             # Make sure we keep empty groups
169 3 50       12 if(!defined($self->{groups}->{$group}))
170             {
171 3         10 $self->{groups}->{$group} = { };
172             }
173 3         12 foreach my $user( split /\s+/, $members ) {
174 10         46 $self->{groups}->{$group}->{$user} = 1;
175             }
176             }
177 1         12 close FILE;
178              
179             } else {
180 3         8 $self->{groups} = {};
181             }
182             } # }}}
183              
184             # sub deletegroup {{{
185              
186             =head2 deletegroup
187              
188             $self->deletegroup( 'GroupName' );
189              
190             Removes a group from the htgroup file. You will need to call save
191             afterward to commit this change back to the file.
192              
193             =cut
194              
195             sub deletegroup {
196 0     0 1 0 my $self = shift;
197 0         0 my ( $group ) = @_;
198 0 0       0 if ( exists $self->{groups}->{$group} ) {
199 0         0 delete $self->{groups}->{$group};
200             }
201 0         0 return (1);
202             } # }}}
203              
204             # sub save {{{
205              
206             =head2 save
207              
208             $htgroup->save;
209             $htgroup->save($file);
210              
211             Writes the current contents of the htgroup object back to the
212             file. If you provide a $file argument, C will attempt to
213             write to that location.
214              
215             =cut
216              
217             sub save {
218 1     1 1 169 my $self = shift;
219 1   33     6 my $file = shift || $self->{groupfile};
220 1         1 my $out;
221             my @members;
222              
223 1 50       123 open( FILE, ">$file" ) || die ("Was unable to open $file for writing: $!");
224              
225 1         2 foreach my $group( keys %{ $self->{groups} } ) {
  1         4  
226              
227             # Work around the fact that Apache can't handle lines
228             # over 8K.
229 1         2 @members = keys %{ $self->{groups}->{$group} };
  1         3  
230 1 50       3 if(!@members) {
231 0         0 print FILE "${group}: \n";
232             }
233 1         4 while (@members) {
234 1         2 $out = "$group:";
235 1         3 while (@members) {
236 1         2 $out .= " " . shift (@members);
237 1 50       4 last if 7500 < length($out);
238             }
239 1         17 print FILE $out, "\n";
240             }
241             }
242 1         64 close FILE;
243              
244 1         3 return (1);
245             } # }}}
246              
247             # sub ismember {{{
248              
249             =head2 ismember
250              
251             $foo = $htgroup->ismember($user, $group);
252              
253             Returns true if the username is in the group, false otherwise
254              
255             =cut
256             sub ismember {
257 7     7 1 106 my $self = shift;
258 7         9 my ( $user, $group ) = @_;
259              
260 7 100       48 return ( $self->{groups}->{$group}->{$user} ) ? 1 : 0;
261             } # }}}
262              
263             1;
264              
265             # Documentation {{{
266              
267             =head1 Internals
268              
269             Although this was not the case in earlier versions, the internal
270             data structure of the object looks something like the following:
271              
272             $obj = { groupfile => '/path/to/groupfile',
273             groups => { group1 => { 'user1' => 1,
274             'user2' => 1,
275             'user3' => 1
276             },
277             group2 => { 'usera' => 1,
278             'userb' => 1,
279             'userc' => 1
280             },
281             }
282             };
283              
284             Note that this data structure is subject to change in the future,
285             and is provided mostly so that I can remember what the heck I was
286             thinking when I next have to look at this code.
287              
288             =head1 Adding groups
289              
290             A number of folks have asked for a method to add a new group. This
291             is unnecessary. To add a new group, just start adding users to
292             a new group, and the new group will magically spring into existance.
293              
294             =head1 AUTHOR
295              
296             Rich Bowen, rbowen@rcbowen.com
297              
298             =head1 COPYRIGHT
299              
300             Copyright (c) 2001 Rich Bowen. All rights reserved.
301             This program is free software; you can redistribute
302             it and/or modify it under the same terms as Perl itself.
303              
304             The full text of the license can be found in the
305             LICENSE file included with this module.
306              
307             =cut
308              
309             # }}}
310