File Coverage

lib/Provision/Unix/Web/Apache.pm
Criterion Covered Total %
statement 73 287 25.4
branch 18 174 10.3
condition 2 37 5.4
subroutine 12 19 63.1
pod 8 12 66.6
total 113 529 21.3


line stmt bran cond sub pod time code
1             package Provision::Unix::Web::Apache;
2             # ABSTRACT: provision web hosting accounts on Apache
3              
4 1     1   6 use strict;
  1         3  
  1         55  
5 1     1   7 use warnings;
  1         2  
  1         72  
6              
7             our $VERSION = '0.10';
8              
9 1     1   5 use English qw( -no_match_vars );
  1         5  
  1         22  
10 1     1   829 use Params::Validate qw( :all );
  1         2  
  1         670  
11              
12             my ( $prov, $util, $web );
13              
14             sub new {
15 1     1 0 3 my $class = shift;
16              
17 1         57 my %p = validate(
18             @_,
19             { prov => { type => OBJECT },
20             web => { type => OBJECT },
21             debug => { type => BOOLEAN, optional => 1, default => 1 },
22             fatal => { type => BOOLEAN, optional => 1, default => 1 },
23             }
24             );
25              
26 1         10 $web = $p{web};
27 1         3 $prov = $p{prov};
28             ## no critic
29 1         62 eval "require Apache::Admin::Config";
30             ## use critic
31 1 50       22643 if ( $EVAL_ERROR ) {
32 0         0 return $prov->error( 'Apache::Admin::Config not installed',
33             fatal => $p{fatal},
34             debug => $p{debug},
35             );
36             };
37 1         10 $util = $prov->get_util;
38              
39 1         2 my $self = {};
40 1         6 bless( $self, $class );
41              
42 1         21 return $self;
43             }
44              
45             sub create {
46              
47 1     1 1 2 my $self = shift;
48              
49 1         38 my %p = validate(
50             @_,
51             { 'request' => { type => HASHREF, optional => 1, },
52             'prompt' => { type => BOOLEAN, optional => 1, default => 0 },
53             'test_mode' => { type => BOOLEAN, optional => 1, default => 0 },
54             'fatal' => { type => SCALAR, optional => 1, default => 1 },
55             'debug' => { type => SCALAR, optional => 1, default => 1 },
56             },
57             );
58              
59 1         14 my $vals = $web->get_vhost_attributes(
60             { request => $p{request},
61             prompt => $p{prompt},
62             }
63             );
64              
65 1         6 $prov->audit("apache create");
66              
67 1 50       6 if ( $self->exists( request => $vals ) ) {
68 0         0 return $prov->error( "that virtual host already exists", );
69             }
70              
71             # test all the values and make sure we've got enough to form a vhost
72             # minimum needed: vhost servername, ip[:port], documentroot
73              
74 1   50     7 my $ip = $vals->{'ip'} || '*:80';
75 1         3 my $name = lc( $vals->{'vhost'} );
76 1         2 my $docroot = $vals->{'documentroot'};
77 1   50     6 my $home = $vals->{'admin_home'} || "/home";
78              
79 1 50       4 unless ($docroot) {
80 0 0       0 if ( -d "$home/$name" ) { $docroot = "$home/$name" }
  0         0  
81 0 0       0 return $prov->error(
82             "documentroot was not set and could not be determined!", )
83             unless -d $docroot;
84             }
85              
86 1 50   1   6 if ( $p{debug} ) { use Data::Dumper; print Dumper($vals); }
  1         3  
  1         2298  
  1         4  
  1         11  
87              
88             # define the vhost
89 1         155 my @lines = "\n<VirtualHost $ip>";
90 1         4 push @lines, " ServerName $name";
91 1         3 push @lines, " DocumentRoot $docroot";
92 1 50       6 push @lines, " ServerAdmin " . $vals->{'serveradmin'}
93             if $vals->{'serveradmin'};
94 1 50       5 push @lines, " ServerAlias " . $vals->{'serveralias'}
95             if $vals->{'serveralias'};
96 1 50       4 if ( $vals->{'cgi'} ) {
97 0 0       0 if ( $vals->{'cgi'} eq "basic" ) {
    0          
    0          
98 0         0 push @lines,
99             " ScriptAlias /cgi-bin/ \"/usr/local/www/cgi-bin.basic/";
100             }
101             elsif ( $vals->{'cgi'} eq "advanced" ) {
102 0         0 push @lines,
103             " ScriptAlias /cgi-bin/ \"/usr/local/www/cgi-bin.advanced/\"";
104             }
105             elsif ( $vals->{'cgi'} eq "custom" ) {
106 0         0 push @lines,
107             " ScriptAlias /cgi-bin/ \""
108             . $vals->{'documentroot'}
109             . "/cgi-bin/\"";
110             }
111             else {
112 0         0 push @lines, " ScriptAlias " . $vals->{'cgi'};
113             }
114              
115             }
116              
117             # options needs some directory logic included if it's going to be used
118             # I won't be using this initially, but maybe eventually...
119             #push @lines, " Options " . $vals->{'options'} if $vals->{'options'};
120              
121 1 50       3 push @lines, " CustomLog " . $vals->{'customlog'} if $vals->{'customlog'};
122 1 50       10 push @lines, " CustomError " . $vals->{'customerror'}
123             if $vals->{'customerror'};
124 1 50       5 if ( $vals->{'ssl'} ) {
125 0 0 0     0 if ( !$vals->{'sslkey'}
      0        
      0        
126             or !$vals->{'sslcert'}
127             or !-f $vals->{'sslkey'}
128             or !$vals->{'sslcert'} )
129             {
130 0         0 return $prov->error(
131             "ssl is enabled but either the key or cert is missing!" );
132             }
133 0         0 push @lines, " SSLEngine on";
134 0 0       0 push @lines, " SSLCertificateKey " . $vals->{'sslkey'}
135             if $vals->{'sslkey'};
136 0 0       0 push @lines, " SSLCertificateFile " . $vals->{'sslcert'}
137             if $vals->{'sslcert'};
138             }
139 1         2 push @lines, "</VirtualHost>\n";
140              
141             # write vhost definition to a file
142 1         7 my ($vhosts_conf) = $self->get_file($vals);
143              
144 1 50       12 return 1 if $p{test_mode};
145              
146 0 0       0 if ( -f $vhosts_conf ) {
147 0         0 $prov->audit("appending to file: $vhosts_conf");
148 0         0 $util->file_write( $vhosts_conf,
149             lines => \@lines,
150             append => 1,
151             );
152             }
153             else {
154 0         0 $prov->audit("writing to file: $vhosts_conf");
155 0         0 $util->file_write( $vhosts_conf, lines => \@lines );
156             }
157              
158 0         0 $self->restart($vals);
159              
160 0         0 $prov->audit("returning success");
161 0         0 return 1;
162             }
163              
164             sub conf_get_dir {
165              
166 0     0 0 0 my $self = shift;
167 0         0 my %p = validate(
168             @_,
169             { 'conf' => HASHREF,
170             'debug' => { type => SCALAR, optional => 1, default => 1 },
171             },
172             );
173              
174 0         0 my $conf = $p{'conf'};
175              
176 0         0 my $prefix = "/usr/local";
177 0         0 my $apachectl = "$prefix/sbin/apachectl";
178              
179 0 0       0 unless ( -x $apachectl ) {
180 0         0 $apachectl = $util->find_bin( "apachectl",
181             debug => 0,
182             fatal => 0
183             );
184              
185 0 0       0 unless ( -x $apachectl ) {
186 0         0 die "apache->conf_get_dir: failed to find apachectl!
187             Is Apache installed correctly?\n";
188             }
189             }
190              
191             # the -V flag to apachectl returns this string:
192             # -D SERVER_CONFIG_FILE="etc/apache22/httpd.conf"
193              
194             # and we can grab the path to httpd.conf from the string
195 0 0       0 if ( grep ( /SERVER_CONFIG_FILE/, `$apachectl -V` ) =~ /=\"(.*)\"/ ) {
196              
197             # and return a fully qualified path to httpd.conf
198 0 0 0     0 if ( -f "$prefix/$1" && -s "$prefix/$1" ) {
199 0         0 return "$prefix/$1";
200             }
201              
202             warn
203 0         0 "apachectl returned $1 as the location of your httpd.conf file but $prefix/$1 does not exist! I'm sorry but I cannot go on like this. Please fix your Apache install and try again.\n";
204             }
205              
206             # apachectl did not return anything useful from -V, must be apache 1.x
207 0         0 my @paths;
208             my @found;
209              
210 0 0       0 if ( $OSNAME eq "darwin" ) {
    0          
    0          
211 0         0 push @paths, "/opt/local/etc";
212 0         0 push @paths, "/private/etc";
213             }
214             elsif ( $OSNAME eq "freebsd" ) {
215 0         0 push @paths, "/usr/local/etc";
216             }
217             elsif ( $OSNAME eq "linux" ) {
218 0         0 push @paths, "/etc";
219             }
220             else {
221 0         0 push @paths, "/usr/local/etc";
222 0         0 push @paths, "/opt/local/etc";
223 0         0 push @paths, "/etc";
224             }
225              
226             PATH:
227 0         0 foreach my $path (@paths) {
228 0 0 0     0 if ( !-e $path && !-d $path ) {
229 0         0 next PATH;
230             }
231              
232 0         0 @found = `find $path -name httpd.conf`;
233 0         0 chomp @found;
234 0         0 foreach my $find (@found) {
235 0 0       0 if ( -f $find ) {
236 0         0 return $find;
237             }
238             }
239             }
240              
241 0         0 return;
242             }
243              
244             sub restart {
245              
246 0     0 0 0 my ( $self, $vals ) = @_;
247              
248             # restart apache
249              
250 0 0       0 print "restarting apache.\n" if $vals->{'debug'};
251              
252 0 0       0 if ( -x "/usr/local/etc/rc.d/apache2.sh" ) {
    0          
253 0         0 $util->syscmd( "/usr/local/etc/rc.d/apache2.sh stop" );
254 0         0 $util->syscmd( "/usr/local/etc/rc.d/apache2.sh start" );
255             }
256             elsif ( -x "/usr/local/etc/rc.d/apache.sh" ) {
257 0         0 $util->syscmd( "/usr/local/etc/rc.d/apache.sh stop" );
258 0         0 $util->syscmd( "/usr/local/etc/rc.d/apache.sh start" );
259             }
260             else {
261 0         0 my $apachectl = $util->find_bin( "apachectl" );
262 0 0       0 if ( -x $apachectl ) {
263 0         0 $util->syscmd( "$apachectl graceful" );
264             }
265             else {
266 0         0 warn "WARNING: couldn't restart Apache!\n ";
267             }
268             }
269             }
270              
271             sub enable {
272              
273 0     0 1 0 my $self = shift;
274              
275 0         0 my %p = validate( @_, { request => { type => HASHREF } } );
276 0         0 my $vals = $p{'request'};
277              
278 0 0       0 if ( $self->exists( request => $vals) ) {
279             return {
280 0         0 error_code => 400,
281             error_desc => "Sorry, that virtual host is already enabled."
282             };
283             }
284              
285 0         0 print "enabling $vals->{'vhost'} \n";
286              
287             # get the file the disabled vhost would live in
288 0         0 my ($vhosts_conf) = $self->get_file($vals);
289              
290 0 0       0 print "the disabled vhost should be in $vhosts_conf.disabled\n"
291             if $vals->{'debug'};
292              
293 0 0       0 unless ( -s "$vhosts_conf.disabled" ) {
294             return {
295 0         0 error_code => 400,
296             error_desc => "That vhost is not disabled, I cannot enable it!"
297             };
298             }
299              
300 0         0 $vals->{'disabled'} = 1;
301              
302             # split the file into two parts
303 0         0 ( undef, my $match, $vals ) = $self->get_match($vals);
304              
305 0         0 print "enabling: \n", join( "\n", @$match ), "\n";
306              
307             # write vhost definition to a file
308 0 0       0 if ( -f $vhosts_conf ) {
309 0 0       0 print "appending to file: $vhosts_conf\n" if $vals->{'debug'};
310 0         0 $util->file_write( $vhosts_conf,
311             lines => $match,
312             append => 1
313             );
314             }
315             else {
316 0 0       0 print "writing to file: $vhosts_conf\n" if $vals->{'debug'};
317 0         0 $util->file_write( $vhosts_conf, lines => $match );
318             }
319              
320 0         0 $self->restart($vals);
321              
322 0 0       0 if ( $vals->{'documentroot'} ) {
323 0         0 print "docroot: $vals->{'documentroot'} \n";
324              
325             # chmod 755 the documentroot directory
326 0 0 0     0 if ( $vals->{'documentroot'} && -d $vals->{'documentroot'} ) {
327 0         0 my $chmod = $util->find_bin( "chmod" );
328 0         0 $util->syscmd( "$chmod 755 $vals->{'documentroot'}" );
329             }
330             }
331              
332 0 0       0 print "returning success or error\n" if $vals->{'debug'};
333 0         0 return { error_code => 200, error_desc => "vhost enabled successfully" };
334             }
335              
336             sub disable {
337 0     0 1 0 my $self = shift;
338              
339 0         0 my %p = validate( @_, { request => { type => HASHREF } } );
340 0         0 my $vals = $p{'request'};
341              
342 0 0       0 if ( ! $self->exists( request => $vals) ) {
343 0         0 warn "Sorry, that virtual host does not exist.";
344 0         0 return;
345             }
346              
347 0         0 print "disabling $vals->{'vhost'}\n";
348              
349             # get the file the vhost lives in
350 0         0 $vals->{'disabled'} = 0;
351 0         0 my ($vhosts_conf) = $self->get_file($vals);
352              
353             # split the file into two parts
354 0         0 ( my $new, my $match, $vals ) = $self->get_match($vals);
355              
356 0         0 print "Disabling: \n" . join( "\n", @$match ) . "\n";
357              
358 0         0 $util->file_write( "$vhosts_conf.new", lines => $new );
359              
360             # write out the .disabled file (append if existing)
361 0 0       0 if ( -f "$vhosts_conf.disabled" ) {
362              
363             # check to see if it's already in there
364 0         0 $vals->{'disabled'} = 1;
365 0         0 ( undef, my $dis_match, $vals ) = $self->get_match($vals);
366              
367 0 0       0 if ( @$dis_match[1] ) {
368 0         0 print "it's already in $vhosts_conf.disabled. skipping append.\n";
369             }
370             else {
371              
372             # if not, append it
373 0 0       0 print "appending to file: $vhosts_conf.disabled\n"
374             if $vals->{'debug'};
375 0         0 $util->file_write( "$vhosts_conf.disabled",
376             lines => $match,
377             append => 1,
378             );
379             }
380             }
381             else {
382 0 0       0 print "writing to file: $vhosts_conf.disabled\n" if $vals->{'debug'};
383 0         0 $util->file_write( "$vhosts_conf.disabled",
384             lines => $match,
385             );
386             }
387              
388 0 0 0     0 if ( ( -s "$vhosts_conf.new" ) && ( -s "$vhosts_conf.disabled" ) ) {
389 0 0       0 print "Yay, success!\n" if $vals->{'debug'};
390 0 0       0 if ( $< eq 0 ) {
391 1     1   1146 use File::Copy; # this only works if we're root
  1         3057  
  1         470  
392 0         0 move( "$vhosts_conf.new", $vhosts_conf );
393             }
394             else {
395 0         0 my $mv = $util->find_bin( "move" );
396 0         0 $util->syscmd( "$mv $vhosts_conf.new $vhosts_conf" );
397             }
398             }
399             else {
400             return {
401 0         0 error_code => 500,
402             error_desc =>
403             "Oops, the size of $vhosts_conf.new or $vhosts_conf.disabled is zero. This is a likely indication of an error. I have left the files for you to examine and correct"
404             };
405             }
406              
407 0         0 $self->restart($vals);
408              
409             # chmod 0 the HTML directory
410 0 0 0     0 if ( $vals->{'documentroot'} && -d $vals->{'documentroot'} ) {
411 0         0 my $chmod = $util->find_bin( "chmod" );
412 0         0 $util->syscmd( "$chmod 0 $vals->{'documentroot'}" );
413             }
414              
415 0 0       0 print "returning success or error\n" if $vals->{'debug'};
416 0         0 return { error_code => 200, error_desc => "vhost disabled successfully" };
417             }
418              
419             sub destroy {
420              
421 0     0 1 0 my ( $self, $vals ) = @_;
422              
423 0 0       0 unless ( $self->exists( request => $vals) ) {
424             return {
425 0         0 error_code => 400,
426             error_desc => "Sorry, that virtual host does not exist."
427             };
428             }
429              
430 0         0 print "deleting vhost " . $vals->{'vhost'} . "\n";
431              
432             # this isn't going to be pretty.
433             # basically, we need to parse through the config file, find the right vhost container, and then remove only that vhost
434             # I'll do that by setting a counter that trips every time I enter a vhost and counts the lines (so if the servername declaration is on the 5th or 1st line, I'll still know where to nip the first line containing the virtualhost opening declaration)
435             #
436              
437 0         0 my ($vhosts_conf) = $self->get_file($vals);
438 0         0 my ( $new, $drop ) = $self->get_match($vals);
439              
440 0         0 print "Dropping: \n" . join( "\n", @$drop ) . "\n";
441              
442 0 0 0     0 if ( scalar @$new == 0 || scalar @$drop == 0 ) {
443             return {
444 0         0 error_code => 500,
445             error_desc => "yikes, something went horribly wrong!"
446             };
447             }
448              
449             # now, just for fun, lets make sure things work out OK
450             # we'll write out @new and @drop and compare them to make sure
451             # the two total the same size as the original
452              
453 0         0 $util->file_write( "$vhosts_conf.new", lines => $new );
454 0         0 $util->file_write( "$vhosts_conf.drop", lines => $drop );
455              
456 0 0       0 if ( ( ( -s "$vhosts_conf.new" ) + ( -s "$vhosts_conf.drop" ) )
457             == -s $vhosts_conf )
458             {
459 0         0 print "Yay, success!\n";
460 1     1   6 use File::Copy;
  1         3  
  1         1853  
461 0         0 move( "$vhosts_conf.new", $vhosts_conf );
462 0         0 unlink("$vhosts_conf.drop");
463             }
464             else {
465             return {
466 0         0 error_code => 500,
467             error_desc =>
468             "Oops, the size of $vhosts_conf.new and $vhosts_conf.drop combined is not the same as $vhosts_conf. This is a likely indication of an error. I have left the files for you to examine and correct"
469             };
470             }
471              
472 0         0 $self->restart($vals);
473              
474 0 0       0 print "returning success or error\n" if $vals->{'debug'};
475 0         0 return { error_code => 200, error_desc => "vhost deletion successful" };
476             }
477              
478             sub get_vhosts {
479 2     2 0 4 my $self = shift;
480              
481 2         6 my $vhosts_conf = $prov->{config}{Apache}{vhosts};
482 2 50       6 return $vhosts_conf if $vhosts_conf;
483              
484 2 0       9 $vhosts_conf
    0          
    50          
485             = lc( $OSNAME eq 'linux' ) ? '/etc/httpd/conf.d'
486             : lc( $OSNAME eq 'darwin' ) ? '/etc/apache2/extra/httpd-vhosts.conf'
487             : lc( $OSNAME eq 'freebsd' ) ? '/usr/local/etc/apache2/Includes'
488             : warn "could not determine where your apache vhosts are\n";
489              
490 2 50       8 return $vhosts_conf if $vhosts_conf;
491 0         0 $prov->error( "you must set [Apache][etc] in provision.conf" );
492             }
493              
494             sub exists {
495              
496 1     1 1 2 my $self = shift;
497              
498 1         19 my %p = validate( @_, { request => { type => HASHREF } } );
499 1         6 my $vals = $p{'request'};
500              
501 1         4 my $vhost = lc( $vals->{vhost} );
502 1         5 my $vhosts_conf = $self->get_vhosts;
503              
504 1 50       122 if ( -d $vhosts_conf ) {
    50          
505              
506             # test to see if the vhosts exists
507             # this implies some sort of unique naming mechanism for vhosts
508             # For now, this requires that the file be the same as the domain name
509             # (example.com) for the domain AND any subdomains. This means subdomain
510             # declarations live within the domain file.
511              
512 0         0 my ($vh_file_name) = $vhost =~ /([a-z0-9-]+\.[a-z0-9-]+)(\.)?$/;
513 0         0 $prov->audit("cleaned up vhost name: $vh_file_name");
514              
515 0         0 $prov->audit("searching for vhost $vhost in $vh_file_name");
516 0         0 my $vh_file_path = "$vhosts_conf/$vh_file_name.conf";
517            
518 0 0       0 if ( !-f $vh_file_path ) { # file does not exist
519 0         0 $prov->audit("vhost $vhost does not exist");
520 0         0 return;
521             };
522              
523             # the file exists that the virtual host should be in.
524             # determine if the vhost is defined in it
525 0         0 require Apache::ConfigFile;
526 0         0 my $ac =
527             Apache::ConfigFile->read( file => $vh_file_path, ignore_case => 1 );
528              
529 0         0 for my $vh ( $ac->cmd_context( VirtualHost => '*:80' ) ) {
530 0         0 my $server_name = $vh->directive('ServerName');
531 0 0       0 $prov->audit( "ServerName $server_name") if $vals->{'debug'};
532 0 0       0 return 1 if ( $vhost eq $server_name );
533              
534 0         0 my $alias = 0;
535 0         0 foreach my $server_alias ( $vh->directive('ServerAlias') ) {
536 0 0       0 return 1 if ( $vhost eq $server_alias );
537 0 0       0 if ( $vals->{'debug'} ) {
538 0 0       0 print "\tServerAlias " unless $alias;
539 0         0 print "$server_alias ";
540             }
541 0         0 $alias++;
542             }
543 0 0 0     0 print "\n" if ( $alias && $vals->{'debug'} );
544             }
545 0         0 return 0;
546             }
547             elsif ( -f $vhosts_conf ) {
548 0         0 print "parsing vhosts from file $vhosts_conf\n";
549              
550             # my $ac =
551             # Apache::ConfigFile->read( file => $vhosts_conf, ignore_case => 1 );
552              
553             # for my $vh ( $ac->cmd_context( VirtualHost => '*:80' ) ) {
554             # my $server_name = $vh->directive('ServerName');
555             # print "ServerName $server_name\n" if $vals->{'debug'};
556             # return 1 if ( $vhost eq $server_name );
557             #
558             # my $alias = 0;
559             # foreach my $server_alias ( $vh->directive('ServerAlias') ) {
560             # return 1 if ( $vhost eq $server_alias );
561             # if ( $vals->{'debug'} ) {
562             # print "\tServerAlias " unless $alias;
563             # print "$server_alias ";
564             # }
565             # $alias++;
566             # }
567             # print "\n" if ( $alias && $vals->{'debug'} );
568             # }
569              
570 0         0 return;
571             }
572              
573 1         6 return;
574             }
575              
576             sub show {
577              
578 0     0 1 0 my ( $self, $vals ) = @_;
579              
580 0 0       0 unless ( $self->exists($vals) ) {
581             return {
582 0         0 error_code => 400,
583             error_desc => "Sorry, that virtual host does not exist."
584             };
585             }
586              
587 0         0 my ($vhosts_conf) = $self->get_file($vals);
588              
589 0         0 ( my $new, my $match, $vals ) = $self->get_match($vals);
590 0         0 print "showing: \n" . join( "\n", @$match ) . "\n";
591              
592 0         0 return { error_code => 100, error_desc => "exiting normally" };
593             }
594              
595             sub get_file {
596              
597 1     1 1 3 my ( $self, $vals ) = @_;
598              
599             # determine the path to the file the vhost is stored in
600 1         5 my $vhosts_conf = $self->get_vhosts();
601 1 50       19 if ( -d $vhosts_conf ) {
602 0         0 my ($vh_file_name)
603             = lc( $vals->{'vhost'} ) =~ /([a-z0-9-]+\.[a-z0-9-]+)(\.)?$/;
604 0         0 $vhosts_conf .= "/$vh_file_name.conf";
605             }
606             else {
607 1 50       6 if ( $vhosts_conf !~ /\.conf$/ ) {
608 1         3 $vhosts_conf .= ".conf";
609             }
610             }
611              
612 1         3 return $vhosts_conf;
613             }
614              
615             sub get_match {
616              
617 0     0 1   my ( $self, $vals ) = @_;
618              
619 0           my ($vhosts_conf) = $self->get_file($vals);
620 0 0         $vhosts_conf .= ".disabled" if $vals->{'disabled'};
621              
622 0 0         print "reading in the vhosts file $vhosts_conf\n" if $vals->{'debug'};
623 0           my @lines = $util->file_read( $vhosts_conf);
624              
625 0           my ( $in, $match, @new, @drop );
626 0           LINE: foreach my $line (@lines) {
627 0 0         if ($match) {
628 0 0         print "match: $line\n" if $vals->{'debug'};
629 0           push @drop, $line;
630 0 0         if ( $line =~ /documentroot[\s+]["]?(.*?)["]?[\s+]?$/i ) {
631 0 0         print "setting documentroot to $1\n" if $vals->{'debug'};
632 0           $vals->{'documentroot'} = $1;
633             }
634             }
635 0           else { push @new, $line }
636              
637 0 0         if ( $line =~ /^[\s+]?<\/virtualhost/i ) {
638 0           $in = 0;
639 0           $match = 0;
640 0           next LINE;
641             }
642              
643 0 0         $in++ if $in;
644              
645 0 0         if ( $line =~ /^[\s+]?<virtualhost/i ) {
646 0           $in = 1;
647 0           next LINE;
648             }
649              
650 0           my ($servername) = $line =~ /([a-z0-9-\.]+)(:\d+)?(\s+)?$/i;
651 0 0 0       if ( $servername && $servername eq lc( $vals->{'vhost'} ) ) {
652 0           $match = 1;
653              
654             # determine how many lines are in @new
655 0           my $length = @new;
656 0 0         print "array length: $length\n" if $vals->{'debug'};
657              
658             # grab the lines from @new going back to the <virtualhost> declaration
659             # and push them onto @drop
660 0           for ( my $i = $in; $i > 0; $i-- ) {
661 0           push @drop, @new[ ( $length - $i ) ];
662 0 0         unless ( $vals->{'documentroot'} ) {
663 0 0         if ( @new[ ( $length - $i ) ]
664             =~ /documentroot[\s+]["]?(.*?)["]?[\s+]?$/i )
665             {
666 0 0         print "setting documentroot to $1\n"
667             if $vals->{'debug'};
668 0           $vals->{'documentroot'} = $1;
669             }
670             }
671             }
672              
673             # remove those lines from @new
674 0           for ( my $i = 0; $i < $in; $i++ ) { pop @new; }
  0            
675             }
676             }
677              
678 0           return \@new, \@drop, $vals;
679             }
680              
681             1;
682              
683              
684              
685             =pod
686              
687             =head1 NAME
688              
689             Provision::Unix::Web::Apache - provision web hosting accounts on Apache
690              
691             =head1 VERSION
692              
693             version 1.06
694              
695             =head1 SYNOPSIS
696              
697             =head1 FUNCTIONS
698              
699             =head2 create
700              
701             Create an Apache vhost container like this:
702              
703             <VirtualHost *:80 >
704             ServerName blockads.com
705             ServerAlias ads.blockads.com
706             DocumentRoot /usr/home/blockads.com/ads
707             ServerAdmin admin@blockads.com
708             CustomLog "| /usr/local/sbin/cronolog /usr/home/example.com/logs/access.log" combined
709             ErrorDocument 404 "blockads.com
710             </VirtualHost>
711              
712             my $apache->create($vals, $conf);
713              
714             Required values:
715              
716             ip - an ip address
717             name - vhost name (ServerName)
718             docroot - Apache DocumentRoot
719              
720             Optional values
721              
722             serveralias - Apache ServerAlias names (comma seperated)
723             serveradmin - Server Admin (email address)
724             cgi - CGI directory
725             customlog - obvious
726             customerror - obvious
727             sslkey - SSL certificate key
728             sslcert - SSL certificate
729              
730             =head2 enable
731              
732             Enable a (previously) disabled virtual host.
733              
734             $apache->enable($vals, $conf);
735              
736             =head2 disable
737              
738             Disable a previously disabled vhost.
739              
740             $apache->disable($vals, $conf);
741              
742             =head2 destroy
743              
744             Delete's an Apache vhost.
745              
746             $apache->destroy();
747              
748             =head2 exists
749              
750             Tests to see if a vhost definition already exists in your Apache config file(s).
751              
752             =head2 show
753              
754             Shows the contents of a virtualhost block that matches the virtual domain name passed in the $vals hashref.
755              
756             $apache->show($vals, $conf);
757              
758             =head2 get_file
759              
760             If vhosts are each in their own file, this determines the file name the vhost will live in and returns it. The general methods on my systems works like this:
761              
762             example.com would be stored in $apache/vhosts/example.com.conf
763              
764             so would any subdomains of example.com.
765              
766             thus, a return value for *.example.com will be "$apache/vhosts/example.com.conf".
767              
768             $apache is looked up from the contents of $conf.
769              
770             =head2 get_match
771              
772             Find a vhost declaration block in the Apache config file(s).
773              
774             =head1 BUGS
775              
776             Please report any bugs or feature requests to C<bug-unix-provision-virtualos at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Provision-Unix>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
777              
778             =head1 SUPPORT
779              
780             You can find documentation for this module with the perldoc command.
781              
782             perldoc Provision::Unix
783              
784             You can also look for information at:
785              
786             =over 4
787              
788             =item * RT: CPAN's request tracker
789              
790             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Provision-Unix>
791              
792             =item * AnnoCPAN: Annotated CPAN documentation
793              
794             L<http://annocpan.org/dist/Provision-Unix>
795              
796             =item * CPAN Ratings
797              
798             L<http://cpanratings.perl.org/d/Provision-Unix>
799              
800             =item * Search CPAN
801              
802             L<http://search.cpan.org/dist/Provision-Unix>
803              
804             =back
805              
806             =head1 ACKNOWLEDGEMENTS
807              
808             =head1 AUTHOR
809              
810             Matt Simerson <msimerson@cpan.org>
811              
812             =head1 COPYRIGHT AND LICENSE
813              
814             This software is copyright (c) 2013 by The Network People, Inc..
815              
816             This is free software; you can redistribute it and/or modify it under
817             the same terms as the Perl 5 programming language system itself.
818              
819             =cut
820              
821              
822             __END__
823              
824              
825