aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Config.pm')
-rw-r--r--Bugzilla/Config.pm148
1 files changed, 93 insertions, 55 deletions
diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm
index 150996e05..1e22b5239 100644
--- a/Bugzilla/Config.pm
+++ b/Bugzilla/Config.pm
@@ -7,14 +7,21 @@
package Bugzilla::Config;
+use 5.10.1;
use strict;
+use warnings;
+
+use parent qw(Exporter);
+use autodie qw(:default);
-use base qw(Exporter);
use Bugzilla::Constants;
use Bugzilla::Hook;
-use Bugzilla::Install::Filesystem qw(fix_file_permissions);
-use Data::Dumper;
+use Bugzilla::Util qw(trick_taint);
+
+use JSON::XS;
+use File::Slurp;
use File::Temp;
+use File::Basename;
# Don't export localvars by default - people should have to explicitly
# ask for it, as a (probably futile) attempt to stop code using it
@@ -91,8 +98,35 @@ sub SetParam {
sub update_params {
my ($params) = @_;
my $answer = Bugzilla->installation_answers;
+ my $datadir = bz_locations()->{'datadir'};
+ my $param;
+
+ # If the old data/params file using Data::Dumper output still exists,
+ # read it. It will be deleted once the parameters are stored in the new
+ # data/params.json file.
+ my $old_file = "$datadir/params";
+
+ if (-e $old_file) {
+ require Safe;
+ my $s = new Safe;
+
+ $s->rdo($old_file);
+ die "Error reading $old_file: $!" if $!;
+ die "Error evaluating $old_file: $@" if $@;
+
+ # Now read the param back out from the sandbox.
+ $param = \%{ $s->varglob('param') };
+ }
+ else {
+ # Rename params.js to params.json if checksetup.pl
+ # was executed with an earlier version of this change
+ rename "$old_file.js", "$old_file.json"
+ if -e "$old_file.js" && !-e "$old_file.json";
+
+ # Read the new data/params.json file.
+ $param = read_param_file();
+ }
- my $param = read_param_file();
my %new_params;
# If we didn't return any param values, then this is a new installation.
@@ -151,16 +185,19 @@ sub update_params {
}
# Old mail_delivery_method choices contained no uppercase characters
- if (exists $param->{'mail_delivery_method'}
- && $param->{'mail_delivery_method'} !~ /[A-Z]/) {
- my $method = $param->{'mail_delivery_method'};
- my %translation = (
- 'sendmail' => 'Sendmail',
- 'smtp' => 'SMTP',
- 'qmail' => 'Qmail',
- 'testfile' => 'Test',
- 'none' => 'None');
- $param->{'mail_delivery_method'} = $translation{$method};
+ my $mta = $param->{'mail_delivery_method'};
+ if ($mta) {
+ if ($mta !~ /[A-Z]/) {
+ my %translation = (
+ 'sendmail' => 'Sendmail',
+ 'smtp' => 'SMTP',
+ 'qmail' => 'Qmail',
+ 'testfile' => 'Test',
+ 'none' => 'None');
+ $param->{'mail_delivery_method'} = $translation{$mta};
+ }
+ # This will force the parameter to be reset to its default value.
+ delete $param->{'mail_delivery_method'} if $param->{'mail_delivery_method'} eq 'Qmail';
}
# Convert the old "ssl" parameter to the new "ssl_redirect" parameter.
@@ -196,6 +233,9 @@ sub update_params {
$param->{'utf8'} = 1 if $new_install;
+ # Bug 452525: OR based groups are on by default for new installations
+ $param->{'or_groups'} = 1 if $new_install;
+
# --- REMOVE OLD PARAMS ---
my %oldparams;
@@ -207,7 +247,6 @@ sub update_params {
}
# Write any old parameters to old-params.txt
- my $datadir = bz_locations()->{'datadir'};
my $old_param_file = "$datadir/old-params.txt";
if (scalar(keys %oldparams)) {
my $op_file = new IO::File($old_param_file, '>>', 0600)
@@ -217,12 +256,9 @@ sub update_params {
" and so have been\nmoved from your parameters file into",
" $old_param_file:\n";
- local $Data::Dumper::Terse = 1;
- local $Data::Dumper::Indent = 0;
-
my $comma = "";
foreach my $item (keys %oldparams) {
- print $op_file "\n\n$item:\n" . Data::Dumper->Dump([$oldparams{$item}]) . "\n";
+ print $op_file "\n\n$item:\n" . $oldparams{$item} . "\n";
print "${comma}$item";
$comma = ", ";
}
@@ -253,6 +289,11 @@ sub update_params {
write_params($param);
+ if (-e $old_file) {
+ unlink $old_file;
+ say "$old_file has been converted into $old_file.json, using the JSON format.";
+ }
+
# Return deleted params and values so that checksetup.pl has a chance
# to convert old params to new data.
return %oldparams;
@@ -261,24 +302,15 @@ sub update_params {
sub write_params {
my ($param_data) = @_;
$param_data ||= Bugzilla->params;
+ my $param_file = bz_locations()->{'datadir'} . '/params.json';
- my $datadir = bz_locations()->{'datadir'};
- my $param_file = "$datadir/params";
-
- local $Data::Dumper::Sortkeys = 1;
-
- my ($fh, $tmpname) = File::Temp::tempfile('params.XXXXX',
- DIR => $datadir );
-
- print $fh (Data::Dumper->Dump([$param_data], ['*param']))
- || die "Can't write param file: $!";
+ my $json_data = JSON::XS->new->canonical->pretty->encode($param_data);
+ write_file($param_file, { binmode => ':utf8', atomic => 1 }, \$json_data);
- close $fh;
-
- rename $tmpname, $param_file
- or die "Can't rename $tmpname to $param_file: $!";
-
- fix_file_permissions($param_file);
+ # It's not common to edit parameters and loading
+ # Bugzilla::Install::Filesystem is slow.
+ require Bugzilla::Install::Filesystem;
+ Bugzilla::Install::Filesystem::fix_file_permissions($param_file);
# And now we have to reset the params cache so that Bugzilla will re-read
# them.
@@ -287,21 +319,25 @@ sub write_params {
sub read_param_file {
my %params;
- my $datadir = bz_locations()->{'datadir'};
- if (-e "$datadir/params") {
- # Note that checksetup.pl sets file permissions on '$datadir/params'
-
- # Using Safe mode is _not_ a guarantee of safety if someone does
- # manage to write to the file. However, it won't hurt...
- # See bug 165144 for not needing to eval this at all
- my $s = new Safe;
-
- $s->rdo("$datadir/params");
- die "Error reading $datadir/params: $!" if $!;
- die "Error evaluating $datadir/params: $@" if $@;
-
- # Now read the param back out from the sandbox
- %params = %{$s->varglob('param')};
+ my $file = bz_locations()->{'datadir'} . '/params.json';
+
+ if (-e $file) {
+ my $data;
+ read_file($file, binmode => ':utf8', buf_ref => \$data);
+
+ # If params.json has been manually edited and e.g. some quotes are
+ # missing, we don't want JSON::XS to leak the content of the file
+ # to all users in its error message, so we have to eval'uate it.
+ %params = eval { %{JSON::XS->new->decode($data)} };
+ if ($@) {
+ my $error_msg = (basename($0) eq 'checksetup.pl') ?
+ $@ : 'run checksetup.pl to see the details.';
+ die "Error parsing $file: $error_msg";
+ }
+ # JSON::XS doesn't detaint data for us.
+ foreach my $key (keys %params) {
+ trick_taint($params{$key}) if defined $params{$key};
+ }
}
elsif ($ENV{'SERVER_SOFTWARE'}) {
# We're in a CGI, but the params file doesn't exist. We can't
@@ -311,7 +347,7 @@ sub read_param_file {
# so that the user sees the error.
require CGI::Carp;
CGI::Carp->import('fatalsToBrowser');
- die "The $datadir/params file does not exist."
+ die "The $file file does not exist."
. ' You probably need to run checksetup.pl.',
}
return \%params;
@@ -367,7 +403,7 @@ specified.
Description: Writes the parameters to disk.
Params: C<$params> (optional) - A hashref to write to the disk
- instead of C<Bugzilla->params>. Used only by
+ instead of C<Bugzilla-E<gt>params>. Used only by
C<update_params>.
Returns: nothing
@@ -375,11 +411,13 @@ Returns: nothing
=item C<read_param_file()>
Description: Most callers should never need this. This is used
- by C<Bugzilla->params> to directly read C<$datadir/params>
- and load it into memory. Use C<Bugzilla->params> instead.
+ by C<Bugzilla-E<gt>params> to directly read C<$datadir/params.json>
+ and load it into memory. Use C<Bugzilla-E<gt>params> instead.
Params: none
-Returns: A hashref containing the current params in C<$datadir/params>.
+Returns: A hashref containing the current params in C<$datadir/params.json>.
+
+=item C<param_panels()>
=back