File Coverage

blib/lib/App/Info/HTTPD/Apache.pm
Criterion Covered Total %
statement 169 186 90.9
branch 76 142 53.5
condition 5 17 29.4
subroutine 39 45 86.7
pod 31 31 100.0
total 320 421 76.0


line stmt bran cond sub pod time code
1             package App::Info::HTTPD::Apache;
2              
3             # $Id: Apache.pm 3154 2006-09-16 00:01:20Z theory $
4              
5             =head1 NAME
6            
7             App::Info::HTTPD::Apache - Information about Apache web server
8            
9             =head1 SYNOPSIS
10            
11             use App::Info::HTTPD::Apache;
12            
13             my $apache = App::Info::HTTPD::Apache->new;
14            
15             if ($apache->installed) {
16             print "App name: ", $apache->name, "\n";
17             print "Version: ", $apache->version, "\n";
18             print "Bin dir: ", $apache->bin_dir, "\n";
19             } else {
20             print "Apache is not installed. :-(\n";
21             }
22            
23             =head1 DESCRIPTION
24            
25             App::Info::HTTPD::Apache supplies information about the Apache web server
26             installed on the local system. It implements all of the methods defined by
27             App::Info::HTTPD. Methods that trigger events will trigger them only the first
28             time they're called (See L<App::Info|App::Info> for documentation on handling
29             events). To start over (after, say, someone has installed Apache) construct a
30             new App::Info::HTTPD::Apache object to aggregate new metadata.
31            
32             Some of the methods trigger the same events. This is due to cross-calling of
33             methods or of functions common to methods. However, any one event should be
34             triggered no more than once. For example, although the info event "Executing
35             `httpd -v`" is documented for the methods C<name()>, C<version()>,
36             C<major_version()>, C<minor_version()>, and C<patch_version()>, rest assured
37             that it will only be triggered once, by whichever of those four methods is
38             called first.
39            
40             =cut
41              
42 2     2   54 use strict;
  2         18  
  2         78  
43 2     2   55 use App::Info::HTTPD;
  2         20  
  2         41  
44 2     2   68 use App::Info::Util;
  2         21  
  2         118  
45 2     2   37 use vars qw(@ISA $VERSION);
  2         19  
  2         33  
46             @ISA = qw(App::Info::HTTPD);
47             $VERSION = '0.51';
48 2     2   81 use constant WIN32 => $^O eq 'MSWin32';
  2         19  
  2         37  
49              
50             my $u = App::Info::Util->new;
51             my @EXES = qw(ab apachectl apxs htdigest htpasswd logresolve rotatelogs);
52              
53             =head1 INTERFACE
54            
55             =head2 Constructor
56            
57             =head3 new
58            
59             my $apache = App::Info::HTTPD::Apache->new(@params);
60            
61             Returns an App::Info::HTTPD::Apache object. See L<App::Info|App::Info> for a
62             complete description of argument parameters.
63            
64             When called, C<new()> searches the the directories returned by
65             C<search_bin_dirs()> for an executable with a name returned by
66             C<search_exe_names()>. If found, the executable (hereafer referred to as
67             F<httpd>, regardless of how it was actually found to be named) will be called
68             by the object methods below to gather the data necessary for each. If F<httpd>
69             cannot be found, then Apache is assumed not to be installed, and each of the
70             object methods will return C<undef>.
71            
72             In addition to the parameters supported by the parent classes,
73             L<App::Info|App::Info> and L<App::Info::HTTPD|App::Info::HTTPD>,
74             this class' C<new()> method also supports:
75            
76             =over 4
77            
78             =item search_conf_names
79            
80             An array reference of possible names for Apache configuration files. These
81             will be returned by the C<search_conf_names()> method before the default
82             names, and may be used by C<conf_file()> to search for the configuration file.
83            
84             =item search_conf_dirs
85            
86             An array reference of possible directories in which to search for Apache
87             configuration files. These will be returned by the C<search_conf_dirs()>
88             method before the default directories, and may be used by C<conf_file()> to
89             search for the configuration file.
90            
91             =back
92            
93             As well as these parameters to specify alternate names for Apache executables
94             (other than F<httpd>, which you specify via the C<search_exe_names> parameter):
95            
96             =over
97            
98             =item search_ab_names
99            
100             =item search_apachectl_names
101            
102             =item search_apxs_names
103            
104             =item search_htdigest_names
105            
106             =item search_htpasswd_names
107            
108             =item search_logresolve_names
109            
110             =item search_rotatelogs_names
111            
112             =back
113            
114             B<Events:>
115            
116             =over 4
117            
118             =item info
119            
120             Looking for Apache executable
121            
122             =item confirm
123            
124             Path to your httpd executable?
125            
126             =item unknown
127            
128             Path to your httpd executable?
129            
130             =back
131            
132             =cut
133              
134             sub new {
135             # Construct the object.
136 2     2 1 75     my $self = shift->SUPER::new(@_);
137              
138 2         23     for my $exe (qw(search_conf_dirs search_conf_names),
  14         146  
139                              map { "search_$_\_names" } @EXES
140                 ) {
141 18 100       177         if (exists $self->{$exe}) {
142 4 50       92             $self->{$exe} = [$self->{$exe}] unless ref $self->{$exe} eq 'ARRAY';
143                     } else {
144 14         230             $self->{$exe} = [];
145                     }
146                 }
147              
148             # Find Apache executable.
149 2         45     $self->info("Looking for Apache executable");
150              
151 2         53     my @paths = $self->search_bin_dirs;
152 2         223     my @exes = $self->search_exe_names;
153              
154 2 50       36     if (my $exe = $u->first_cat_exe(\@exes, @paths)) {
155             # We found httpd. Confirm.
156                     $self->{executable} = $self->confirm(
157                         key => 'path to httpd',
158                         prompt => 'Path to your httpd executable?',
159                         value => $exe,
160 0     0   0             callback => sub { -x },
161 2         45             error => 'Not an executable',
162                     );
163                 } else {
164             # Handle an unknown value.
165                     $self->{executable} = $self->unknown(
166                         key => 'path to httpd',
167                         prompt => 'Path to your httpd executable?',
168 0     0   0             callback => sub { -x },
169 0         0             error => 'Not an executable',
170                     );
171                 }
172 2         45     return $self;
173             };
174              
175             ##############################################################################
176              
177             =head2 Class Method
178            
179             =head3 key_name
180            
181             my $key_name = App::Info::HTTPD::Apache->key_name;
182            
183             Returns the unique key name that describes this class. The value returned is
184             the string "Apache".
185            
186             =cut
187              
188 2     2 1 32 sub key_name { 'Apache' }
189              
190             ##############################################################################
191              
192             =head2 Object Methods
193            
194             =head3 installed
195            
196             print "apache is ", ($apache->installed ? '' : 'not '),
197             "installed.\n";
198            
199             Returns true if Apache is installed, and false if it is not.
200             App::Info::HTTPD::Apache determines whether Apache is installed based on the
201             presence or absence of the F<httpd> application on the file system, as found
202             when C<new()> constructed the object. If Apache does not appear to be
203             installed, then all of the other object methods will return empty values.
204            
205             =cut
206              
207 2 50   2 1 34 sub installed { return $_[0]->{executable} ? 1 : undef }
208              
209             ##############################################################################
210              
211             =head3 name
212            
213             my $name = $apache->name;
214            
215             Returns the name of the application. App::Info::HTTPD::Apache parses the name
216             from the system call C<`httpd -v`>.
217            
218             B<Events:>
219            
220             =over 4
221            
222             =item info
223            
224             Executing `httpd -v`
225            
226             =item error
227            
228             Failed to find Apache version data with `httpd -v`
229            
230             Failed to parse Apache name and version from string
231            
232             =item unknown
233            
234             Enter a valid Apache name
235            
236             =back
237            
238             =cut
239              
240             my $get_version = sub {
241                 my $self = shift;
242                 $self->{-v} = 1;
243                 $self->info(qq{Executing `"$self->{executable}" -v`});
244                 my $version = `"$self->{executable}" -v`;
245                 unless ($version) {
246                     $self->error("Failed to find Apache version data with ",
247                                  qq{`"$self->{executable}" -v`});
248                     return;
249                 }
250              
251                 chomp $version;
252                 my ($n, $x, $y, $z) = $version =~
253                   /Server\s+version:\s+([^\/]*)\/(\d+)\.(\d+).(\d+)/;
254                 unless ($n and $x and defined $y and defined $z) {
255                     $self->error("Failed to parse Apache name and ",
256                                      "version from string '$version'");
257                     return;
258                 }
259              
260                 @{$self}{qw(name version major minor patch)} =
261                   ($n, "$x.$y.$z", $x, $y, $z);
262             };
263              
264             sub name {
265 2     2 1 23     my $self = shift;
266 2 50       27     return unless $self->{executable};
267              
268             # Load data.
269 2 50       37     $get_version->($self) unless exists $self->{-v};
270              
271             # Handle an unknown name.
272 2   50     86     $self->{name} ||= $self->unknown( key => 'apache name' );
273              
274             # Return the name.
275 2         424     return $self->{name};
276             }
277              
278             ##############################################################################
279              
280             =head3 version
281            
282             my $version = $apache->version;
283            
284             Returns the apache version number. App::Info::HTTPD::Apache parses the version
285             number from the system call C<`httpd -v`>.
286            
287             B<Events:>
288            
289             =over 4
290            
291             =item info
292            
293             Executing `httpd -v`
294            
295             =item error
296            
297             Failed to find Apache version data with `httpd -v`
298            
299             Failed to parse Apache name and version from string
300            
301             =item unknown
302            
303             Enter a valid Apache version number
304            
305             =back
306            
307             =cut
308              
309             sub version {
310 2     2 1 883     my $self = shift;
311 2 50       76     return unless $self->{executable};
312              
313             # Load data.
314 2 50       86     $get_version->($self) unless exists $self->{-v};
315              
316             # Handle an unknown value.
317 2 50       45     unless ($self->{version}) {
318             # Create a validation code reference.
319                     my $chk_version = sub {
320             # Try to get the version number parts.
321 0     0   0             my ($x, $y, $z) = /^(\d+)\.(\d+).(\d+)$/;
322             # Return false if we didn't get all three.
323 0 0 0     0             return unless $x and defined $y and defined $z;
      0        
324             # Save all three parts.
325 0         0             @{$self}{qw(major minor patch)} = ($x, $y, $z);
  0         0  
326             # Return true.
327 0         0             return 1;
328 0         0         };
329 0         0         $self->{version} = $self->unknown( key => 'apache version number',
330                                                        callback => $chk_version);
331                 }
332              
333             # Return the version number.
334 2         52     return $self->{version};
335             }
336              
337             ##############################################################################
338              
339             =head3 major_version
340            
341             my $major_version = $apache->major_version;
342            
343             Returns the Apache major version number. App::Info::HTTPD::Apache parses the
344             version number from the system call C<`httpd --v`>. For example, if
345             C<version()> returns "1.3.24", then this method returns "1".
346            
347             B<Events:>
348            
349             =over 4
350            
351             =item info
352            
353             Executing `httpd -v`
354            
355             =item error
356            
357             Failed to find Apache version data with `httpd -v`
358            
359             Failed to parse Apache name and version from string
360            
361             =item unknown
362            
363             Enter a valid Apache major version number
364            
365             =back
366            
367             =cut
368              
369             # This code reference is used by major_version(), minor_version(), and
370             # patch_version() to validate a version number entered by a user.
371             my $is_int = sub { /^\d+$/ };
372              
373             sub major_version {
374 2     2 1 21     my $self = shift;
375 2 50       26     return unless $self->{executable};
376             # Load data.
377 2 50       28     $get_version->($self) unless exists $self->{-v};
378             # Handle an unknown value.
379 2 50       26     $self->{major} = $self->unknown( key => 'apache major version number',
380                                                  callback => $is_int)
381                   unless $self->{major};
382 2         71     return $self->{major};
383             }
384              
385             ##############################################################################
386              
387             =head3 minor_version
388            
389             my $minor_version = $apache->minor_version;
390            
391             Returns the Apache minor version number. App::Info::HTTPD::Apache parses the
392             version number from the system call C<`httpd --v`>. For example, if
393             C<version()> returns "1.3.24", then this method returns "3". See the
394             L<version|"version"> method for a list of possible errors.
395            
396             B<Events:>
397            
398             =over 4
399            
400             =item info
401            
402             Executing `httpd -v`
403            
404             =item error
405     <