--- /dev/null
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Terry Weissman <terry@mozilla.org>
+# Dawn Endico <endico@mozilla.org>
+# Dan Mosedale <dmose@mozilla.org>
+# Joe Robins <jmrobins@tgix.com>
+# Jake <jake@bugzilla.org>
+# J. Paul Reed <preed@sigkill.com>
+# Bradley Baetz <bbaetz@student.usyd.edu.au>
+# Christopher Aillon <christopher@aillon.com>
+# Erik Stambaugh <erik@dasbistro.com>
+# Frédéric Buclin <LpSolit@gmail.com>
+
+package Bugzilla::Config;
+
+use strict;
+
+use base qw(Exporter);
+use Bugzilla::Constants;
+use Data::Dumper;
+use File::Temp;
+
+# Don't export localvars by default - people should have to explicitly
+# ask for it, as a (probably futile) attempt to stop code using it
+# when it shouldn't
+%Bugzilla::Config::EXPORT_TAGS =
+ (
+ admin => [qw(update_params SetParam write_params)],
+ );
+Exporter::export_ok_tags('admin');
+
+use vars qw(@param_list);
+
+# INITIALISATION CODE
+# Perl throws a warning if we use bz_locations() directly after do.
+our %params;
+# Load in the param definitions
+sub _load_params {
+ my $panels = param_panels();
+ foreach my $panel (keys %$panels) {
+ my $module = $panels->{$panel};
+ eval("require $module") || die $@;
+ my @new_param_list = "$module"->get_param_list();
+ foreach my $item (@new_param_list) {
+ $params{$item->{'name'}} = $item;
+ }
+ push(@param_list, @new_param_list);
+ }
+}
+# END INIT CODE
+
+# Subroutines go here
+
+sub param_panels {
+ my $param_panels = {};
+ my $libpath = bz_locations()->{'libpath'};
+ foreach my $item ((glob "$libpath/Bugzilla/Config/*.pm")) {
+ $item =~ m#/([^/]+)\.pm$#;
+ my $module = $1;
+ $param_panels->{$module} = "Bugzilla::Config::$module" unless $module eq 'Common';
+ }
+ # Now check for any hooked params
+ Bugzilla::Hook::process('config', { config => $param_panels });
+ return $param_panels;
+}
+
+sub SetParam {
+ my ($name, $value) = @_;
+
+ _load_params unless %params;
+ die "Unknown param $name" unless (exists $params{$name});
+
+ my $entry = $params{$name};
+
+ # sanity check the value
+
+ # XXX - This runs the checks. Which would be good, except that
+ # check_shadowdb creates the database as a side effect, and so the
+ # checker fails the second time around...
+ if ($name ne 'shadowdb' && exists $entry->{'checker'}) {
+ my $err = $entry->{'checker'}->($value, $entry);
+ die "Param $name is not valid: $err" unless $err eq '';
+ }
+
+ Bugzilla->params->{$name} = $value;
+}
+
+sub update_params {
+ my ($params) = @_;
+ my $answer = Bugzilla->installation_answers;
+
+ my $param = read_param_file();
+
+ # If we didn't return any param values, then this is a new installation.
+ my $new_install = !(keys %$param);
+
+ # --- UPDATE OLD PARAMS ---
+
+ # Old Bugzilla versions stored the version number in the params file
+ # We don't want it, so get rid of it
+ delete $param->{'version'};
+
+ # Change from usebrowserinfo to defaultplatform/defaultopsys combo
+ if (exists $param->{'usebrowserinfo'}) {
+ if (!$param->{'usebrowserinfo'}) {
+ if (!exists $param->{'defaultplatform'}) {
+ $param->{'defaultplatform'} = 'Other';
+ }
+ if (!exists $param->{'defaultopsys'}) {
+ $param->{'defaultopsys'} = 'Other';
+ }
+ }
+ delete $param->{'usebrowserinfo'};
+ }
+
+ # Change from a boolean for quips to multi-state
+ if (exists $param->{'usequip'} && !exists $param->{'enablequips'}) {
+ $param->{'enablequips'} = $param->{'usequip'} ? 'on' : 'off';
+ delete $param->{'usequip'};
+ }
+
+ # Change from old product groups to controls for group_control_map
+ # 2002-10-14 bug 147275 bugreport@peshkin.net
+ if (exists $param->{'usebuggroups'} &&
+ !exists $param->{'makeproductgroups'})
+ {
+ $param->{'makeproductgroups'} = $param->{'usebuggroups'};
+ }
+ if (exists $param->{'usebuggroupsentry'}
+ && !exists $param->{'useentrygroupdefault'}) {
+ $param->{'useentrygroupdefault'} = $param->{'usebuggroupsentry'};
+ }
+
+ # Modularise auth code
+ if (exists $param->{'useLDAP'} && !exists $param->{'loginmethod'}) {
+ $param->{'loginmethod'} = $param->{'useLDAP'} ? "LDAP" : "DB";
+ }
+
+ # set verify method to whatever loginmethod was
+ if (exists $param->{'loginmethod'}
+ && !exists $param->{'user_verify_class'})
+ {
+ $param->{'user_verify_class'} = $param->{'loginmethod'};
+ delete $param->{'loginmethod'};
+ }
+
+ # Remove quip-display control from parameters
+ # and give it to users via User Settings (Bug 41972)
+ if ( exists $param->{'enablequips'}
+ && !exists $param->{'quip_list_entry_control'})
+ {
+ my $new_value;
+ ($param->{'enablequips'} eq 'on') && do {$new_value = 'open';};
+ ($param->{'enablequips'} eq 'approved') && do {$new_value = 'moderated';};
+ ($param->{'enablequips'} eq 'frozen') && do {$new_value = 'closed';};
+ ($param->{'enablequips'} eq 'off') && do {$new_value = 'closed';};
+ $param->{'quip_list_entry_control'} = $new_value;
+ delete $param->{'enablequips'};
+ }
+
+ # 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};
+ }
+
+ # --- DEFAULTS FOR NEW PARAMS ---
+
+ _load_params unless %params;
+ foreach my $item (@param_list) {
+ my $name = $item->{'name'};
+ unless (exists $param->{$name}) {
+ print "New parameter: $name\n" unless $new_install;
+ $param->{$name} = $answer->{$name} || $item->{'default'};
+ }
+ }
+
+ $param->{'utf8'} = 1 if $new_install;
+
+ # --- REMOVE OLD PARAMS ---
+
+ my %oldparams;
+ # Remove any old params, put them in old-params.txt
+ foreach my $item (keys %$param) {
+ if (!grep($_ eq $item, map ($_->{'name'}, @param_list))) {
+ $oldparams{$item} = $param->{$item};
+ delete $param->{$item};
+ }
+ }
+
+ if (scalar(keys %oldparams)) {
+ my $op_file = new IO::File('old-params.txt', '>>', 0600)
+ || die "old-params.txt: $!";
+
+ print "The following parameters are no longer used in Bugzilla,",
+ " and so have been\nmoved from your parameters file into",
+ " old-params.txt:\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 "${comma}$item";
+ $comma = ", ";
+ }
+ print "\n";
+ $op_file->close;
+ }
+
+ if (ON_WINDOWS && !-e SENDMAIL_EXE
+ && $param->{'mail_delivery_method'} eq 'Sendmail')
+ {
+ my $smtp = $answer->{'SMTP_SERVER'};
+ if (!$smtp) {
+ print "\nBugzilla requires an SMTP server to function on",
+ " Windows.\nPlease enter your SMTP server's hostname: ";
+ $smtp = <STDIN>;
+ chomp $smtp;
+ if ($smtp) {
+ $param->{'smtpserver'} = $smtp;
+ }
+ else {
+ print "\nWarning: No SMTP Server provided, defaulting to",
+ " localhost\n";
+ }
+ }
+
+ $param->{'mail_delivery_method'} = 'SMTP';
+ }
+
+ write_params($param);
+
+ # Return deleted params and values so that checksetup.pl has a chance
+ # to convert old params to new data.
+ return %oldparams;
+}
+
+sub write_params {
+ my ($param_data) = @_;
+ $param_data ||= Bugzilla->params;
+
+ 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: $!";
+
+ close $fh;
+
+ rename $tmpname, $param_file
+ or die "Can't rename $tmpname to $param_file: $!";
+
+ ChmodDataFile($param_file, 0666);
+
+ # And now we have to reset the params cache so that Bugzilla will re-read
+ # them.
+ delete Bugzilla->request_cache->{params};
+}
+
+# Some files in the data directory must be world readable if and only if
+# we don't have a webserver group. Call this function to do this.
+# This will become a private function once all the datafile handling stuff
+# moves into this package
+
+# This sub is not perldoc'd for that reason - noone should know about it
+sub ChmodDataFile {
+ my ($file, $mask) = @_;
+ my $perm = 0770;
+ if ((stat(bz_locations()->{'datadir'}))[2] & 0002) {
+ $perm = 0777;
+ }
+ $perm = $perm & $mask;
+ chmod $perm,$file;
+}
+
+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')};
+ }
+ elsif ($ENV{'SERVER_SOFTWARE'}) {
+ # We're in a CGI, but the params file doesn't exist. We can't
+ # Template Toolkit, or even install_string, since checksetup
+ # might not have thrown an error. Bugzilla::CGI->new
+ # hasn't even been called yet, so we manually use CGI::Carp here
+ # so that the user sees the error.
+ require CGI::Carp;
+ CGI::Carp->import('fatalsToBrowser');
+ die "The $datadir/params file does not exist."
+ . ' You probably need to run checksetup.pl.',
+ }
+ return \%params;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Config - Configuration parameters for Bugzilla
+
+=head1 SYNOPSIS
+
+ # Administration functions
+ use Bugzilla::Config qw(:admin);
+
+ update_params();
+ SetParam($param, $value);
+ write_params();
+
+=head1 DESCRIPTION
+
+This package contains ways to access Bugzilla configuration parameters.
+
+=head1 FUNCTIONS
+
+=head2 Parameters
+
+Parameters can be set, retrieved, and updated.
+
+=over 4
+
+=item C<SetParam($name, $value)>
+
+Sets the param named $name to $value. Values are checked using the checker
+function for the given param if one exists.
+
+=item C<update_params()>
+
+Updates the parameters, by transitioning old params to new formats, setting
+defaults for new params, and removing obsolete ones. Used by F<checksetup.pl>
+in the process of an installation or upgrade.
+
+Prints out information about what it's doing, if it makes any changes.
+
+May prompt the user for input, if certain required parameters are not
+specified.
+
+=item C<write_params($params)>
+
+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
+ C<update_params>.
+
+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.
+
+Params: none
+
+Returns: A hashref containing the current params in C<$datadir/params>.
+
+=back