From 46317c3190e95cca62cd5d932bd6bc4b45e75d23 Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Sat, 18 Sep 2010 16:24:06 -0700 Subject: Bug 586244: Make mod_headers and mod_expires optional r=glob, a=mkanat --- Bugzilla/Install/Requirements.pm | 213 ++++++++++++++++++++++++++++++--------- 1 file changed, 163 insertions(+), 50 deletions(-) (limited to 'Bugzilla/Install/Requirements.pm') diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index 5ed2d7dcd..5d2b6c39f 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -26,7 +26,7 @@ package Bugzilla::Install::Requirements; use strict; use Bugzilla::Constants; -use Bugzilla::Install::Util qw(vers_cmp install_string +use Bugzilla::Install::Util qw(vers_cmp install_string bin_loc extension_requirement_packages); use List::Util qw(max); use Safe; @@ -49,6 +49,34 @@ our @EXPORT = qw( # by checksetup.pl. use constant TABLE_WIDTH => 71; +# Optional Apache modules that have no Perl component to them. +# If these are installed, Bugzilla has additional functionality. +# +# The keys are the names of the modules, the values are what the module +# is called in the output of "apachectl -t -D DUMP_MODULES". +use constant APACHE_MODULES => { + mod_headers => 'headers_module', + mod_env => 'env_module', + mod_expires => 'expires_module', +}; + +# These are all of the binaries that we could possibly use that can +# give us info about which Apache modules are installed. +# If we can't use "apachectl", the "httpd" binary itself takes the same +# parameters. Note that on Debian and Gentoo, there is an "apache2ctl", +# but it takes different parameters on each of those two distros, so we +# don't use apache2ctl. +use constant APACHE => qw(apachectl httpd apache2 apache); + +# If we don't find any of the above binaries in the normal PATH, +# these are extra places we look. +use constant APACHE_PATH => [qw( + /usr/sbin + /usr/local/sbin + /usr/libexec + /usr/local/libexec +)]; + # The below two constants are subroutines so that they can implement # a hook. Other than that they are actually constants. @@ -347,6 +375,8 @@ sub check_requirements { print "\n", install_string('checking_optional'), "\n" if $output; my $missing_optional = _check_missing(OPTIONAL_MODULES, $output); + my $missing_apache = _missing_apache_modules(APACHE_MODULES, $output); + # If we're running on Windows, reset the input line terminator so that # console input works properly - loading CGI tends to mess it up $/ = "\015\012" if ON_WINDOWS; @@ -357,6 +387,7 @@ sub check_requirements { one_dbd => $have_one_dbd, missing => $missing, optional => $missing_optional, + apache => $missing_apache, any_missing => !$pass || scalar(@$missing_optional), }; } @@ -375,6 +406,54 @@ sub _check_missing { return \@missing; } +sub _missing_apache_modules { + my ($modules, $output) = @_; + my $apachectl = _get_apachectl(); + return [] if !$apachectl; + my $command = "$apachectl -t -D DUMP_MODULES"; + my $cmd_info = `$command 2>&1`; + # If apachectl returned a value greater than 0, then there was an + # error parsing Apache's configuration, and we can't check modules. + my $retval = $?; + if ($retval > 0) { + print STDERR install_string('apachectl_failed', + { command => $command, root => ROOT_USER }), "\n"; + return []; + } + my @missing; + foreach my $module (keys %$modules) { + my $ok = _check_apache_module($module, $modules->{$module}, + $cmd_info, $output); + push(@missing, $module) if !$ok; + } + return \@missing; +} + +sub _get_apachectl { + foreach my $bin_name (APACHE) { + my $bin = bin_loc($bin_name); + return $bin if $bin; + } + # Try again with a possibly different path. + foreach my $bin_name (APACHE) { + my $bin = bin_loc($bin_name, APACHE_PATH); + return $bin if $bin; + } + return undef; +} + +sub _check_apache_module { + my ($module, $config_name, $mod_info, $output) = @_; + my $ok; + if ($mod_info =~ /^\s+\Q$config_name\E\b/m) { + $ok = 1; + } + if ($output) { + _checking_for({ package => $module, ok => $ok }); + } + return $ok; +} + sub print_module_instructions { my ($check_results, $output) = @_; @@ -411,30 +490,41 @@ sub print_module_instructions { } } + if (my @missing = @{ $check_results->{apache} }) { + print install_string('modules_message_apache'); + my $missing_string = join(', ', @missing); + my $size = TABLE_WIDTH - 7; + printf "* \%-${size}s *\n", $missing_string; + my $spaces = TABLE_WIDTH - 2; + print "*", (' ' x $spaces), "*\n"; + } + + my $need_module_instructions = + ( (!$output and @{$check_results->{missing}}) + or ($output and $check_results->{any_missing}) ) ? 1 : 0; + # We only print the PPM repository note if we have to. - if ((!$output && @{$check_results->{missing}}) - || ($output && $check_results->{any_missing})) - { - if (ON_ACTIVESTATE) { - my $perl_ver = sprintf('%vd', $^V); + if ($need_module_instructions and ON_ACTIVESTATE) { + my $perl_ver = sprintf('%vd', $^V); - # URL when running Perl 5.8.x. - my $url_to_theory58S = 'http://theoryx5.uwinnipeg.ca/ppms'; - # Packages for Perl 5.10 are not compatible with Perl 5.8. - if (vers_cmp($perl_ver, '5.10') > -1) { - $url_to_theory58S = 'http://cpan.uwinnipeg.ca/PPMPackages/10xx/'; - } - print colored( - install_string('ppm_repo_add', - { theory_url => $url_to_theory58S }), - COLOR_ERROR); - - # ActivePerls older than revision 819 require an additional command. - if (ON_ACTIVESTATE < 819) { - print install_string('ppm_repo_up'); - } + # URL when running Perl 5.8.x. + my $url_to_theory58S = 'http://theoryx5.uwinnipeg.ca/ppms'; + # Packages for Perl 5.10 are not compatible with Perl 5.8. + if (vers_cmp($perl_ver, '5.10') > -1) { + $url_to_theory58S = 'http://cpan.uwinnipeg.ca/PPMPackages/10xx/'; } + print colored( + install_string('ppm_repo_add', + { theory_url => $url_to_theory58S }), + COLOR_ERROR); + + # ActivePerls older than revision 819 require an additional command. + if (ON_ACTIVESTATE < 819) { + print install_string('ppm_repo_up'); + } + } + if ($need_module_instructions or @{ $check_results->{apache} }) { # If any output was required, we want to close the "table" print "*" x TABLE_WIDTH . "\n"; } @@ -494,15 +584,14 @@ sub check_graphviz { my $webdotbase = Bugzilla->params->{'webdotbase'}; return 1 if $webdotbase =~ /^https?:/; - my $checking_for = install_string('checking_for'); - my $any = install_string('any'); - printf("%s %15s %-9s ", $checking_for, "GraphViz", "($any)") if $output; + my $return; + $return = 1 if -x $webdotbase; + + if ($output) { + _checking_for({ package => 'GraphViz', ok => $return }); + } - my $return = 0; - if(-x $webdotbase) { - print install_string('module_ok'), "\n" if $output; - $return = 1; - } else { + if (!$return) { print install_string('bad_executable', { bin => $webdotbase }), "\n"; } @@ -554,17 +643,6 @@ sub have_vers { $vnum = $1; } - my $vstr; - if ($vnum eq "-1") { # string compare just in case it's non-numeric - $vstr = install_string('module_not_found'); - } - elsif (vers_cmp($vnum,"0") > -1) { - $vstr = install_string('module_found', { ver => $vnum }); - } - else { - $vstr = install_string('module_unknown_version'); - } - my $vok = (vers_cmp($vnum,$wanted) > -1); my $blacklisted; if ($vok && $params->{blacklist}) { @@ -573,19 +651,52 @@ sub have_vers { } if ($output) { - my $ok = $vok ? install_string('module_ok') : ''; - my $black_string = $blacklisted ? install_string('blacklisted') : ''; - my $want_string = $wanted ? "v$wanted" : install_string('any'); - - $ok = "$ok:" if $ok; - my $str = sprintf "%s %19s %-9s $ok $vstr $black_string\n", - install_string('checking_for'), $package, "($want_string)"; - print $vok ? $str : colored($str, COLOR_ERROR); + _checking_for({ + package => $package, ok => $vok, wanted => $wanted, + found => $vnum, blacklisted => $blacklisted + }); } return $vok ? 1 : 0; } +sub _checking_for { + my ($params) = @_; + my ($package, $ok, $wanted, $blacklisted, $found) = + @$params{qw(package ok wanted blacklisted found)}; + + my $ok_string = $ok ? install_string('module_ok') : ''; + + # If we're actually checking versions (like for Perl modules), then + # we have some rather complex logic to determine what we want to + # show. If we're not checking versions (like for GraphViz) we just + # show "ok" or "not found". + if (exists $params->{found}) { + my $found_string; + # We do a string compare in case it's non-numeric. + if ($found and $found eq "-1") { + $found_string = install_string('module_not_found'); + } + elsif ($found) { + $found_string = install_string('module_found', { ver => $found }); + } + else { + $found_string = install_string('module_unknown_version'); + } + $ok_string = $ok ? "$ok_string: $found_string" : $found_string; + } + elsif (!$ok) { + $ok_string = install_string('module_not_found'); + } + + my $black_string = $blacklisted ? install_string('blacklisted') : ''; + my $want_string = $wanted ? "v$wanted" : install_string('any'); + + my $str = sprintf "%s %20s %-11s $ok_string $black_string\n", + install_string('checking_for'), $package, "($want_string)"; + print $ok ? $str : colored($str, COLOR_ERROR); +} + sub install_command { my $module = shift; my ($command, $package); @@ -707,10 +818,12 @@ a hashref in the format of items from L. =item C - The same as C, but for optional modules. +=item C - The name of each optional Apache module that is missing. + =item C - True if at least one C module is installed. -=item C - True if there are any missing modules, even optional -modules. +=item C - True if there are any missing Perl modules, even +optional modules. =back -- cgit v1.2.3-24-g4f1b