File Coverage

lib/HTTPD/GroupAdmin/Text.pm
Criterion Covered Total %
statement 68 74 91.8
branch 18 28 64.2
condition n/a
subroutine 12 12 100.0
pod 3 3 100.0
total 101 117 86.3


line stmt bran cond sub pod time code
1             # $Id: Text.pm,v 1.2 2003/01/16 19:41:31 lstein Exp $
2             package HTTPD::GroupAdmin::Text;
3 2     2   12 use Carp ();
  2         3  
  2         37  
4 2     2   9 use strict;
  2         4  
  2         61  
5 2     2   15 use vars qw(@ISA $DLM $VERSION $LineMax);
  2         4  
  2         2309  
6             @ISA = qw(HTTPD::GroupAdmin);
7             $VERSION = (qw$Revision: 1.2 $)[1];
8             $DLM = ": ";
9              
10             # Maximum size of each line in the group file. Anytime we have more
11             # group data than this we split it up into multiple lines. At least
12             # Apache 1.3.4 this limitation on lines in the group file.
13             $LineMax = 8 * 1024;
14              
15             my %Default = (PATH => ".",
16             DB => ".htgroup",
17             FLAGS => "rwc",
18             );
19              
20             sub new {
21 4     4 1 9 my($class) = shift;
22 4         35 my $self = bless { %Default, @_ } => $class;
23             #load the DBM methods
24 4         24 $self->load("HTTPD::GroupAdmin::DBM");
25 4         45 $self->db($self->{DB});
26 4         59 return $self;
27             }
28              
29             sub _tie {
30 4     4   7 my($self) = @_;
31 4         13 my($fh,$db) = ($self->gensym(), $self->{DB});
32 4         40 my($key,$val);
33 4 50       33 printf STDERR "%s->_tie($db)\n", $self->class if $self->debug;
34              
35 4 50       25 $db =~ /^([^<>;|]+)$/ or Carp::croak("Bad file name '$db'"); $db = $1; #untaint
  4         10  
36 4 100       115 open($fh, $db) or return; #must be new
37              
38 3         71 while(<$fh>) {
39 3         14 ($key,$val) = $self->_parseline($fh, $_);
40 3 50       12 next unless $key =~ /\S/;
41 3 50       22 $self->{'_HASH'}{$key} = (exists $self->{'_HASH'}{$key} ?
42             join(" ", $self->{'_HASH'}{$key}, $val) :
43             $val);
44             }
45 3         36 CORE::close $fh;
46             }
47              
48             sub _untie {
49 2     2   3 my($self) = @_;
50 2 100       7 return unless exists $self->{'_HASH'};
51 1         4 $self->commit;
52 1         3 delete $self->{'_HASH'};
53             }
54              
55             DESTROY {
56 2     2   18 $_[0]->_untie('_HASH');
57 2         14 $_[0]->unlock;
58             }
59              
60             sub commit {
61 6     6 1 8 my($self) = @_;
62 6 100       21 return if $self->readonly;
63 5         16 my($fh,$db) = ($self->gensym(), $self->{DB});
64 5         55 my($key,$val);
65              
66 5 50       25 $db =~ /^([^<>;|]+)$/ or return (0, "Bad file name '$db'"); $db = $1;
  5         22  
67             #untaint
68 5         23 my $tmp_db = "$db.$$"; # Use temp file until write is complete.
69 5 50       356 open($fh, ">$tmp_db") or return (0, "open: '$tmp_db' $!");
70              
71 5         10 while(($key,$val) = each %{$self->{'_HASH'}}) {
  14         57  
72 9 50       32 print $fh $self->_formatline($key,$val)
73             or return (0, "print: '$tmp_db' failed: $!");
74             }
75 5 50       154 CORE::close $fh
76             or return (0, "close: '$tmp_db' failed: $!");
77 5         58 my $mode = (stat $db)[2];
78 5 100       85 chmod $mode, $tmp_db if $mode;
79 5 50       291 rename( $tmp_db,$db )
80             or return (0, "rename '$tmp_db' to '$db' failed: $!");
81 5         27 1;
82             }
83             sub _parseline {
84 3     3   4 my($self,$fh) = (shift,shift);
85 3         5 local $_ = shift;
86 3         4 chomp; s/^\s+//; s/\s+$//;
  3         7  
  3         8  
87 3         14 my($key, $val) = split(/:\s*/, $_, 2);
88 3         13 $val =~ s/\s* \s*/ /g;
89 3         11 return ($key,$val);
90             }
91              
92             sub _formatline {
93 9     9   16 my($self,$key,$val) = @_;
94 9         17 my( $FieldMax ) = $LineMax - length( $key );
95 9         10 my( @fields );
96 9         45 $val =~ s/(\w) /$1 /g;
97 9         26 while( length( $val ) > $FieldMax ) {
98 0         0 my( $tail, $field );
99 0         0 $field = substr( $val, 0, $FieldMax );
100 0         0 $val = substr( $val, $FieldMax );
101 0         0 ( $field, $tail ) = ( $field =~ m/^(.+) (\S+ ?)$/ );
102 0         0 $val = $tail . $val;
103 0         0 push( @fields, $field );
104             }
105 9         86 map( join($DLM, $key,$_) . "\n", @fields, $val );
106             }
107              
108             sub add {
109 6     6 1 8 my $self = shift;
110 6 50       14 return(0, $self->db . " is read-only!") if $self->readonly;
111 6         31 $self->HTTPD::GroupAdmin::DBM::add(@_);
112             }
113              
114             package HTTPD::GroupAdmin::Text::_generic;
115 2     2   13 use vars qw(@ISA);
  2         4  
  2         147  
116             @ISA = qw(HTTPD::GroupAdmin::Text
117             HTTPD::GroupAdmin::DBM);
118              
119             1;
120              
121             __END__