diff options
Diffstat (limited to 'Bugzilla/Install/Localconfig.pm')
-rw-r--r-- | Bugzilla/Install/Localconfig.pm | 405 |
1 files changed, 186 insertions, 219 deletions
diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index 7f473cc77..2769dca12 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -22,6 +22,7 @@ use warnings; use Bugzilla::Constants; use Bugzilla::Install::Util qw(bin_loc install_string); use Bugzilla::Util qw(generate_random_password wrap_hard); +use Bugzilla::Hook; use Data::Dumper; use File::Basename qw(dirname); @@ -31,151 +32,106 @@ use Term::ANSIColor; use parent qw(Exporter); our @EXPORT_OK = qw( - read_localconfig - update_localconfig + read_localconfig + update_localconfig ); use constant LOCALCONFIG_VARS => ( - { - name => 'create_htaccess', - default => 1, - }, - { - name => 'webservergroup', - default => ON_WINDOWS ? '' : 'apache', - }, - { - name => 'use_suexec', - default => 0, - }, - { - name => 'db_driver', - default => 'mysql', - }, - { - name => 'db_host', - default => 'localhost', - }, - { - name => 'db_name', - default => 'bugs', - }, - { - name => 'db_user', - default => 'bugs', - }, - { - name => 'db_pass', - default => '', - }, - { - name => 'db_port', - default => 0, - }, - { - name => 'db_sock', - default => '', - }, - { - name => 'db_check', - default => 1, - }, - { - name => 'db_mysql_ssl_ca_file', - default => '', - }, - { - name => 'db_mysql_ssl_ca_path', - default => '', - }, - { - name => 'db_mysql_ssl_client_cert', - default => '', - }, - { - name => 'db_mysql_ssl_client_key', - default => '', - }, - { - name => 'index_html', - default => 0, - }, - { - name => 'interdiffbin', - default => sub { bin_loc('interdiff') }, - }, - { - name => 'diffpath', - default => sub { dirname(bin_loc('diff')) }, - }, - { - name => 'site_wide_secret', - # 64 characters is roughly the equivalent of a 384-bit key, which - # is larger than anybody would ever be able to brute-force. - default => sub { generate_random_password(64) }, - }, + {name => 'create_htaccess', default => 1,}, + {name => 'webservergroup', default => ON_WINDOWS ? '' : 'apache',}, + {name => 'use_suexec', default => 0,}, + {name => 'db_driver', default => 'mysql',}, + {name => 'db_host', default => 'localhost',}, + {name => 'db_name', default => 'bugs',}, + {name => 'db_user', default => 'bugs',}, + {name => 'db_pass', default => '',}, + {name => 'db_port', default => 0,}, + {name => 'db_sock', default => '',}, + {name => 'db_check', default => 1,}, + {name => 'db_mysql_ssl_ca_file', default => '',}, + {name => 'db_mysql_ssl_ca_path', default => '',}, + {name => 'db_mysql_ssl_client_cert', default => '',}, + {name => 'db_mysql_ssl_client_key', default => '',}, + {name => 'index_html', default => 0,}, + {name => 'interdiffbin', default => sub { bin_loc('interdiff') },}, + {name => 'diffpath', default => sub { dirname(bin_loc('diff')) },}, + { + name => 'site_wide_secret', + + # 64 characters is roughly the equivalent of a 384-bit key, which + # is larger than anybody would ever be able to brute-force. + default => sub { generate_random_password(64) }, + }, ); sub read_localconfig { - my ($include_deprecated) = @_; - my $filename = bz_locations()->{'localconfig'}; - - my %localconfig; - if (-e $filename) { - my $s = new Safe; - # Some people like to store their database password in another file. - $s->permit('dofile'); - - $s->rdo($filename); - if ($@ || $!) { - my $err_msg = $@ ? $@ : $!; - die install_string('error_localconfig_read', - { error => $err_msg, localconfig => $filename }), "\n"; - } + my ($include_deprecated) = @_; + my $filename = bz_locations()->{'localconfig'}; + + my %localconfig; + if (-e $filename) { + my $s = new Safe; + + # Some people like to store their database password in another file. + $s->permit('dofile'); + + $s->rdo($filename); + if ($@ || $!) { + my $err_msg = $@ ? $@ : $!; + die install_string( + 'error_localconfig_read', {error => $err_msg, localconfig => $filename} + ), + "\n"; + } - my @read_symbols; - if ($include_deprecated) { - # First we have to get the whole symbol table - my $safe_root = $s->root; - my %safe_package; - { no strict 'refs'; %safe_package = %{$safe_root . "::"}; } - # And now we read the contents of every var in the symbol table. - # However: - # * We only include symbols that start with an alphanumeric - # character. This excludes symbols like "_<./localconfig" - # that show up in some perls. - # * We ignore the INC symbol, which exists in every package. - # * Perl 5.10 imports a lot of random symbols that all - # contain "::", and we want to ignore those. - @read_symbols = grep { /^[A-Za-z0-1]/ and !/^INC$/ and !/::/ } - (keys %safe_package); - } - else { - @read_symbols = map($_->{name}, LOCALCONFIG_VARS); - } - foreach my $var (@read_symbols) { - my $glob = $s->varglob($var); - # We can't get the type of a variable out of a Safe automatically. - # We can only get the glob itself. So we figure out its type this - # way, by trying first a scalar, then an array, then a hash. - # - # The interesting thing is that this converts all deprecated - # array or hash vars into hashrefs or arrayrefs, but that's - # fine since as I write this all modern localconfig vars are - # actually scalars. - if (defined $$glob) { - $localconfig{$var} = $$glob; - } - elsif (@$glob) { - $localconfig{$var} = \@$glob; - } - elsif (%$glob) { - $localconfig{$var} = \%$glob; - } - } + my @read_symbols; + if ($include_deprecated) { + + # First we have to get the whole symbol table + my $safe_root = $s->root; + my %safe_package; + { no strict 'refs'; %safe_package = %{$safe_root . "::"}; } + + # And now we read the contents of every var in the symbol table. + # However: + # * We only include symbols that start with an alphanumeric + # character. This excludes symbols like "_<./localconfig" + # that show up in some perls. + # * We ignore the INC symbol, which exists in every package. + # * Perl 5.10 imports a lot of random symbols that all + # contain "::", and we want to ignore those. + @read_symbols + = grep { /^[A-Za-z0-1]/ and !/^INC$/ and !/::/ } (keys %safe_package); + } + else { + @read_symbols = map($_->{name}, LOCALCONFIG_VARS); + Bugzilla::Hook::process('localconfig_symbols', + {read_symbols => \@read_symbols}); } + foreach my $var (@read_symbols) { + my $glob = $s->varglob($var); + + # We can't get the type of a variable out of a Safe automatically. + # We can only get the glob itself. So we figure out its type this + # way, by trying first a scalar, then an array, then a hash. + # + # The interesting thing is that this converts all deprecated + # array or hash vars into hashrefs or arrayrefs, but that's + # fine since as I write this all modern localconfig vars are + # actually scalars. + if (defined $$glob) { + $localconfig{$var} = $$glob; + } + elsif (@$glob) { + $localconfig{$var} = \@$glob; + } + elsif (%$glob) { + $localconfig{$var} = \%$glob; + } + } + } - return \%localconfig; + return \%localconfig; } @@ -204,94 +160,105 @@ sub read_localconfig { # Cute, ey? # sub update_localconfig { - my ($params) = @_; - - my $output = $params->{output} || 0; - my $answer = Bugzilla->installation_answers; - my $localconfig = read_localconfig('include deprecated'); - - my @new_vars; - foreach my $var (LOCALCONFIG_VARS) { - my $name = $var->{name}; - my $value = $localconfig->{$name}; - # Regenerate site_wide_secret if it was made by our old, weak - # generate_random_password. Previously we used to generate - # a 256-character string for site_wide_secret. - $value = undef if ($name eq 'site_wide_secret' and defined $value - and length($value) == 256); - - if (!defined $value) { - $var->{default} = &{$var->{default}} if ref($var->{default}) eq 'CODE'; - if (exists $answer->{$name}) { - $localconfig->{$name} = $answer->{$name}; - } - else { - # If the user did not supply an answers file, then they get - # notified about every variable that gets added. If there was - # an answer file, then we don't notify about site_wide_secret - # because we assume the intent was to auto-generate it anyway. - if (!scalar(keys %$answer) || $name ne 'site_wide_secret') { - push(@new_vars, $name); - } - $localconfig->{$name} = $var->{default}; - } + my ($params) = @_; + + my $output = $params->{output} || 0; + my $answer = Bugzilla->installation_answers; + my $localconfig = read_localconfig('include deprecated'); + + my @new_vars; + my @localconfig_vars = LOCALCONFIG_VARS; + Bugzilla::Hook::process('localconfig_vars', + {localconfig_vars => \@localconfig_vars}); + foreach my $var (@localconfig_vars) { + my $name = $var->{name}; + my $value = $localconfig->{$name}; + + # Regenerate site_wide_secret if it was made by our old, weak + # generate_random_password. Previously we used to generate + # a 256-character string for site_wide_secret. + $value = undef + if ($name eq 'site_wide_secret' and defined $value and length($value) == 256); + + if (!defined $value) { + $var->{default} = &{$var->{default}} if ref($var->{default}) eq 'CODE'; + if (exists $answer->{$name}) { + $localconfig->{$name} = $answer->{$name}; + } + else { + # If the user did not supply an answers file, then they get + # notified about every variable that gets added. If there was + # an answer file, then we don't notify about site_wide_secret + # because we assume the intent was to auto-generate it anyway. + if (!scalar(keys %$answer) || $name ne 'site_wide_secret') { + push(@new_vars, $name); } + $localconfig->{$name} = $var->{default}; + } } - if (!$localconfig->{'interdiffbin'} && $output) { - print "\n", install_string('patchutils_missing'), "\n"; +# but if you supplied an answers file and the value differs then you are asking to change it + elsif (exists $answer->{$name} && $answer->{$name} ne $value) { + $localconfig->{$name} = $answer->{$name}; } - - my @old_vars; - foreach my $var (keys %$localconfig) { - push(@old_vars, $var) if !grep($_->{name} eq $var, LOCALCONFIG_VARS); + } + + if (!$localconfig->{'interdiffbin'} && $output) { + print "\n", install_string('patchutils_missing'), "\n"; + } + + my @old_vars; + foreach my $var (keys %$localconfig) { + push(@old_vars, $var) if !grep($_->{name} eq $var, @localconfig_vars); + } + + my $filename = bz_locations->{'localconfig'}; + + # Move any custom or old variables into a separate file. + if (scalar @old_vars) { + my $filename_old = "$filename.old"; + open(my $old_file, ">>:utf8", $filename_old) or die "$filename_old: $!"; + local $Data::Dumper::Purity = 1; + foreach my $var (@old_vars) { + print $old_file Data::Dumper->Dump([$localconfig->{$var}], ["*$var"]) . "\n\n"; } - - my $filename = bz_locations->{'localconfig'}; - - # Move any custom or old variables into a separate file. - if (scalar @old_vars) { - my $filename_old = "$filename.old"; - open(my $old_file, ">>:utf8", $filename_old) - or die "$filename_old: $!"; - local $Data::Dumper::Purity = 1; - foreach my $var (@old_vars) { - print $old_file Data::Dumper->Dump([$localconfig->{$var}], - ["*$var"]) . "\n\n"; - } - close $old_file; - my $oldstuff = join(', ', @old_vars); - print install_string('lc_old_vars', - { localconfig => $filename, old_file => $filename_old, - vars => $oldstuff }), "\n"; - } - - # Re-write localconfig - open(my $fh, ">:utf8", $filename) or die "$filename: $!"; - foreach my $var (LOCALCONFIG_VARS) { - my $name = $var->{name}; - my $desc = install_string("localconfig_$name", { root => ROOT_USER }); - chomp($desc); - # Make the description into a comment. - $desc =~ s/^/# /mg; - print $fh $desc, "\n", - Data::Dumper->Dump([$localconfig->{$name}], - ["*$name"]), "\n"; - } - - if (@new_vars) { - my $newstuff = join(', ', @new_vars); - print "\n"; - print colored(install_string('lc_new_vars', { localconfig => $filename, - new_vars => wrap_hard($newstuff, 70) }), - COLOR_ERROR), "\n"; - exit; - } - - # Reset the cache for Bugzilla->localconfig so that it will be re-read - delete Bugzilla->request_cache->{localconfig}; - - return { old_vars => \@old_vars, new_vars => \@new_vars }; + close $old_file; + my $oldstuff = join(', ', @old_vars); + print install_string('lc_old_vars', + {localconfig => $filename, old_file => $filename_old, vars => $oldstuff}), + "\n"; + } + + # Re-write localconfig + open(my $fh, ">:utf8", $filename) or die "$filename: $!"; + foreach my $var (@localconfig_vars) { + my $name = $var->{name}; + my $desc = install_string("localconfig_$name", {root => ROOT_USER}); + chomp($desc); + + # Make the description into a comment. + $desc =~ s/^/# /mg; + print $fh $desc, "\n", Data::Dumper->Dump([$localconfig->{$name}], ["*$name"]), + "\n"; + } + + if (@new_vars) { + my $newstuff = join(', ', @new_vars); + print "\n"; + print colored( + install_string( + 'lc_new_vars', {localconfig => $filename, new_vars => wrap_hard($newstuff, 70)} + ), + COLOR_ERROR + ), + "\n"; + exit; + } + + # Reset the cache for Bugzilla->localconfig so that it will be re-read + delete Bugzilla->request_cache->{localconfig}; + + return {old_vars => \@old_vars, new_vars => \@new_vars}; } 1; |