From 761ae5de8e84ffd70489260364db5789ec135b55 Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Thu, 14 Sep 2006 13:57:29 +0000 Subject: Bug 352608: Make checksetup more localizable Patch By Max Kanat-Alexander (module owner) a=myk --- Bugzilla.pm | 6 ++- Bugzilla/DB.pm | 38 ++++++++------- Bugzilla/Group.pm | 4 +- Bugzilla/Install.pm | 20 ++------ Bugzilla/Install/Filesystem.pm | 50 +++++++++++++++---- Bugzilla/Install/Localconfig.pm | 65 ------------------------- Bugzilla/Template.pm | 3 ++ Bugzilla/User/Setting.pm | 5 +- Bugzilla/Util.pm | 45 ++++++++++++++++- checksetup.pl | 5 ++ template/en/default/global/code-error.html.tmpl | 18 +++++++ template/en/default/global/messages.html.tmpl | 56 +++++++++++++++++++++ 12 files changed, 203 insertions(+), 112 deletions(-) diff --git a/Bugzilla.pm b/Bugzilla.pm index 287e054ae..c4300b0b5 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -338,7 +338,11 @@ sub switch_to_main_db { sub get_fields { my $class = shift; my $criteria = shift; - return @{Bugzilla::Field->match($criteria)}; + # This function may be called during installation, and Field::match + # may fail at that time. so we want to return an empty list in that + # case. + my $fields = eval { Bugzilla::Field->match($criteria) } || []; + return @$fields; } sub custom_field_names { diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 5fceb961d..a87c1a606 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -424,9 +424,8 @@ sub bz_add_column { if ( $new_def->{NOTNULL} && !exists $new_def->{DEFAULT} && !defined $init_value && $new_def->{TYPE} !~ /SERIAL/) { - die "Failed adding the column ${table}.${name}:\n You cannot add" - . " a NOT NULL column with no default to an existing table,\n" - . " unless you specify something for \$init_value." + ThrowCodeError('column_not_null_without_default', + { name => "$table.$name" }); } my $current_def = $self->bz_column_info($table, $name); @@ -435,8 +434,9 @@ sub bz_add_column { my @statements = $self->_bz_real_schema->get_add_column_ddl( $table, $name, $new_def, defined $init_value ? $self->quote($init_value) : undef); - print "Adding new column $name to table $table ...\n" - unless i_am_cgi(); + print get_text('install_column_add', + { column => $name, table => $table }) . "\n" + if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; foreach my $sql (@statements) { $self->do($sql); } @@ -460,12 +460,8 @@ sub bz_alter_column { # Check for NULLs my $any_nulls = $self->selectrow_array( "SELECT 1 FROM $table WHERE $name IS NULL"); - if ($any_nulls) { - die "You cannot alter the ${table}.${name} column to be" - . " NOT NULL without\nspecifying a default or" - . " something for \$set_nulls_to, because" - . " there are\nNULL values currently in it."; - } + ThrowCodeError('column_not_null_no_default_alter', + { name => "$table.$name" }) if ($any_nulls); } $self->bz_alter_column_raw($table, $name, $new_def, $current_def, $set_nulls_to); @@ -604,7 +600,9 @@ sub bz_drop_column { if ($current_def) { my @statements = $self->_bz_real_schema->get_drop_column_ddl( $table, $column); - print "Deleting unused column $column from table $table ...\n"; + print get_text('install_column_drop', + { table => $table, column => $column }) . "\n" + if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; foreach my $sql (@statements) { # Because this is a deletion, we don't want to die hard if # we fail because of some local customization. If something @@ -664,7 +662,8 @@ sub bz_drop_table { if ($table_exists) { my @statements = $self->_bz_schema->get_drop_table_ddl($name); - print "Dropping table $name...\n"; + print get_text('install_table_drop', { name => $name }) . "\n" + if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; foreach my $sql (@statements) { # Because this is a deletion, we don't want to die hard if # we fail because of some local customization. If something @@ -683,13 +682,16 @@ sub bz_rename_column { if ($old_col_exists) { my $already_renamed = $self->bz_column_info($table, $new_name); - die "Name conflict: Cannot rename ${table}.${old_name} to" - . " ${table}.${new_name},\nbecause ${table}.${new_name}" - . " already exists." if $already_renamed; + ThrowCodeError('column_rename_conflict', + { old => "$table.$old_name", + new => "$table.$new_name" }) if $already_renamed; my @statements = $self->_bz_real_schema->get_rename_column_ddl( $table, $old_name, $new_name); - print "Changing column $old_name in table $table to" - . " be named $new_name...\n"; + + print get_text('install_column_rename', + { old => "$table.$old_name", new => "$table.$new_name" }) + . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; + foreach my $sql (@statements) { $self->do($sql); } diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm index 93a78331c..69c3f51de 100644 --- a/Bugzilla/Group.pm +++ b/Bugzilla/Group.pm @@ -27,6 +27,7 @@ use strict; package Bugzilla::Group; use base qw(Bugzilla::Object); + use Bugzilla::Constants; use Bugzilla::Util; use Bugzilla::Error; @@ -84,7 +85,8 @@ sub create { my ($params) = @_; my $dbh = Bugzilla->dbh; - print "Creating group $params->{name}...\n" unless i_am_cgi(); + print get_text('install_group_create', { name => $params->{name} }) . "\n" + if Bugzilla->usage_mode == USAGE_MODE_CMDLINE; my $group = $class->SUPER::create(@_); diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm index c50abea95..18f7473ae 100644 --- a/Bugzilla/Install.pm +++ b/Bugzilla/Install.pm @@ -32,6 +32,7 @@ use Bugzilla::Group; use Bugzilla::Product; use Bugzilla::User; use Bugzilla::User::Setting; +use Bugzilla::Util qw(get_text); use Bugzilla::Version; use constant SETTINGS => { @@ -210,7 +211,8 @@ sub create_default_product { # Make the default Classification if it doesn't already exist. if (!$dbh->selectrow_array('SELECT 1 FROM classifications')) { my $class = DEFAULT_CLASSIFICATION; - print "Creating default classification '$class->{name}'...\n"; + print get_text('install_default_classification', + { name => $class->{name} }) . "\n"; $dbh->do('INSERT INTO classifications (name, description) VALUES (?, ?)', undef, $class->{name}, $class->{description}); @@ -219,7 +221,8 @@ sub create_default_product { # And same for the default product/component. if (!$dbh->selectrow_array('SELECT 1 FROM products')) { my $default_prod = DEFAULT_PRODUCT; - print "Creating initial dummy product '$default_prod->{name}'...\n"; + print get_text('install_default_product', + { name => $default_prod->{name} }) . "\n"; $dbh->do(q{INSERT INTO products (name, description) VALUES (?,?)}, @@ -367,19 +370,6 @@ sub _create_admin_exit { exit 1; } -sub get_text { - my ($name, $vars) = @_; - my $template = Bugzilla->template; - $vars ||= {}; - $vars->{'message'} = $name; - my $message; - $template->process('global/message.txt.tmpl', $vars, \$message) - || ThrowTemplateError($template->error()); - # Remove the indenting that exists in messages.html.tmpl. - $message =~ s/^ //gm; - return $message; -} - 1; __END__ diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 3fd24cdd1..4986e4d7a 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -27,7 +27,9 @@ package Bugzilla::Install::Filesystem; use strict; use Bugzilla::Constants; +use Bugzilla::Error; use Bugzilla::Install::Localconfig; +use Bugzilla::Util; use File::Find; use File::Path; @@ -484,6 +486,9 @@ sub _update_old_charts { sub fix_all_file_permissions { my ($output) = @_; + my $ws_group = Bugzilla->localconfig->{'webservergroup'}; + my $group_id = _check_web_server_group($ws_group, $output); + return if ON_WINDOWS; my $fs = FILESYSTEM(); @@ -491,17 +496,10 @@ sub fix_all_file_permissions { my %dirs = %{$fs->{all_dirs}}; my %recurse_dirs = %{$fs->{recurse_dirs}}; - print "Fixing file permissions...\n" if $output; + print get_text('install_file_perms_fix') . "\n" if $output; my $owner_id = POSIX::getuid(); - my $group_id = POSIX::getgid(); - my $ws_group = Bugzilla->localconfig->{'webservergroup'}; - if ($ws_group) { - my $ws_group_id = getgrnam($ws_group); - die "There is no such group: $ws_group. Check your \$webservergroup" - . " setting in localconfig" unless defined $ws_group_id; - $group_id = $ws_group_id; - } + $group_id = POSIX::getgid() unless defined $group_id; foreach my $dir (sort keys %dirs) { next unless -d $dir; @@ -561,6 +559,40 @@ sub _fix_perms { || warn "Failed to change permissions of $name: $!"; } +sub _check_web_server_group { + my ($group, $output) = @_; + + my $filename = bz_locations()->{'localconfig'}; + my $group_id; + + # If we are on Windows, webservergroup does nothing + if (ON_WINDOWS && $group && $output) { + print "\n\n" . get_text('install_webservergroup_windows') . "\n\n"; + } + + # If we're not on Windows, make sure that webservergroup isn't + # empty. + elsif (!ON_WINDOWS && !$group && $output) { + print "\n\n" . get_text('install_webservergroup_empty') . "\n\n"; + } + + # If we're not on Windows, make sure we are actually a member of + # the webservergroup. + elsif (!ON_WINDOWS && $group) { + $group_id = getgrnam($group); + ThrowCodeError('invalid_webservergroup', { group => $group }) + unless defined $group_id; + + # If on unix, see if we need to print a warning about a webservergroup + # that we can't chgrp to + if ($output && $< != 0 && !grep($_ eq $group_id, split(" ", $)))) { + print "\n\n" . get_text('install_webservergroup_not_in') . "\n\n"; + } + } + + return $group_id; +} + 1; __END__ diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index f01be8bf9..971c27d02 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -339,9 +339,6 @@ EOT exit; } - # Now we do some checks on localconfig values. - _check_web_server_group($localconfig->{'webservergroup'}) if $output; - # Reset the cache for Bugzilla->localconfig so that it will be re-read delete Bugzilla->request_cache->{localconfig}; @@ -388,68 +385,6 @@ sub _get_default_diffpath { return $diff_binaries; } -sub _check_web_server_group { - my ($group) = @_; - - my $filename = bz_locations()->{'localconfig'}; - - # If we are on Windows, webservergroup does nothing - if (ON_WINDOWS && $group) { - print <context->template($file); } } + + # If anything created a Template object before now, clear it out. + delete Bugzilla->request_cache->{template}; } # Helper for precompile_templates diff --git a/Bugzilla/User/Setting.pm b/Bugzilla/User/Setting.pm index 7ed1b2f11..ad39d194b 100644 --- a/Bugzilla/User/Setting.pm +++ b/Bugzilla/User/Setting.pm @@ -23,12 +23,13 @@ package Bugzilla::User::Setting; use strict; use base qw(Exporter); + # Module stuff @Bugzilla::User::Setting::EXPORT = qw(get_all_settings get_defaults add_setting); use Bugzilla::Error; -use Bugzilla::Util qw{trick_taint}; +use Bugzilla::Util qw(trick_taint get_text); ############################### ### Module Initialization ### @@ -135,7 +136,7 @@ sub add_setting { ($name && $default_value) || ThrowCodeError("setting_info_invalid"); - print "Adding a new user setting called '$name'\n"; + print get_text('install_setting_new', { name => $name }) . "\n"; $dbh->do(q{INSERT INTO setting (name, default_value, is_enabled, subclass) VALUES (?, ?, 1, ?)}, undef, ($name, $default_value, $subclass)); diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 8821a6c66..c051a987f 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -43,7 +43,8 @@ use base qw(Exporter); format_time format_time_decimal validate_date file_mod_time is_7bit_clean bz_crypt generate_random_password - validate_email_syntax clean_text); + validate_email_syntax clean_text + get_text); use Bugzilla::Constants; @@ -397,6 +398,20 @@ sub clean_text { return trim($dtext); } +sub get_text { + my ($name, $vars) = @_; + my $template = Bugzilla->template; + $vars ||= {}; + $vars->{'message'} = $name; + my $message; + $template->process('global/message.txt.tmpl', $vars, \$message) + || ThrowTemplateError($template->error()); + # Remove the indenting that exists in messages.html.tmpl. + $message =~ s/^ //gm; + return $message; +} + + sub get_netaddr { my $ipaddr = shift; @@ -683,6 +698,34 @@ ASCII 10 (LineFeed) and ASCII 13 (Carrage Return). Returns the parameter "cleaned" by exchanging non-printable characters with spaces. Specifically characters (ASCII 0 through 31) and (ASCII 127) will become ASCII 32 (Space). +=item C + +=over + +=item B + +This is a method of getting localized strings within Bugzilla code. +Use this when you don't want to display a whole template, you just +want a particular string. + +It uses the F template to return a string. + +=item B + +=over + +=item C<$message> - The identifier for the message. + +=item C<$vars> - A hashref. Any variables you want to pass to the template. + +=back + +=item B + +A string. + +=back + =back =head2 Formatting Time diff --git a/checksetup.pl b/checksetup.pl index d38fb5441..d8e920a6d 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -47,6 +47,7 @@ use 5.008; use File::Basename; use Getopt::Long qw(:config bundling); use Pod::Usage; +use POSIX qw(setlocale LC_CTYPE); use Safe; BEGIN { chdir dirname($0); } @@ -130,6 +131,10 @@ require Bugzilla::Install; Bugzilla->usage_mode(USAGE_MODE_CMDLINE); +# When we're running at the command line, we need to pick the right +# language before ever creating a template object. +$ENV{'HTTP_ACCEPT_LANGUAGE'} ||= setlocale(LC_CTYPE); + ########################################################################### # Check and update --LOCAL-- configuration ########################################################################### diff --git a/template/en/default/global/code-error.html.tmpl b/template/en/default/global/code-error.html.tmpl index c6d1ee198..63ce0ffab 100644 --- a/template/en/default/global/code-error.html.tmpl +++ b/template/en/default/global/code-error.html.tmpl @@ -108,6 +108,20 @@ Charts will not work without the Chart::Lines Perl module being installed. Run checksetup.pl for installation instructions. + [% ELSIF error == "column_not_null_without_default" %] + Failed adding the column [% name FILTER html %]: + You cannot add a NOT NULL column with no default to an existing table + unless you specify something for the $init_value argument. + + [% ELSIF error == "column_not_null_no_default_alter" %] + You cannot alter the [% name FILTER html %] column to be NOT NULL + without specifying a default or something for $set_nulls_to, because + there are NULL values currently in it. + + [% ELSIF error == "column_rename_conflict" %] + Name conflict: Cannot rename [% old FILTER html %] to + [% new FILTER html %] because [% new FILTER html %] already exists. + [% ELSIF error == "cookies_need_value" %] Every cookie must have a value. @@ -192,6 +206,10 @@ The series_id [% series_id FILTER html %] is not valid. It may be that this series has been deleted. + [% ELSIF error == "invalid_webservergroup" %] + There is no such group: [% group FILTER html %]. Check your $webservergroup + setting in [% constants.bz_locations.localconfig FILTER html %]. + [% ELSIF error == "list_comparison_error" %] Unexpected error in list comparing code. diff --git a/template/en/default/global/messages.html.tmpl b/template/en/default/global/messages.html.tmpl index f7a5e6b6b..21c79b8ac 100644 --- a/template/en/default/global/messages.html.tmpl +++ b/template/en/default/global/messages.html.tmpl @@ -282,12 +282,68 @@ Either this is your first time using [% terms.Bugzilla %], or your administrator's privileges might have accidentally been deleted. + [% ELSIF message_tag == "install_column_add" %] + Adding new column '[% column FILTER html %]' to the '[% table FILTER html %]' table... + + [% ELSIF message_tag == "install_column_drop" %] + Deleting the '[% column FILTER html %]' column from the '[% table FILTER html %]' table... + + [% ELSIF message_tag == "install_column_rename" %] + Renaming column '[% old FILTER html %]' to '[% new FILTER html %]'... + + [% ELSIF message_tag == "install_default_classification" %] + Creating default classification '[% name FILTER html %]'... + + [% ELSIF message_tag == "install_default_product" %] + Creating initial dummy product '[% name FILTER html %]'... + + [% ELSIF message_tag == "install_file_perms_fix" %] + Fixing file permissions... + + [% ELSIF message_tag == "install_group_create" %] + Creating group [% name FILTER html %]... + + [% ELSIF message_tag == "install_setting_new" %] + Adding a new user setting called '[% name FILTER html %]' + + [% ELSIF message_tag == "install_table_drop" %] + Dropping the '[% name FILTER html %]' table... + [% ELSIF message_tag == "install_urlbase_default" %] Now that you have installed [% terms.Bugzilla %], you should visit the 'Parameters' page (linked in the footer of the Administrator account) to ensure it is set up as you wish - this includes setting the 'urlbase' option to the correct url. + [% ELSIF message_tag == "install_webservergroup_empty" %] + **************************************************************************** + WARNING! You have not entered a value for the "webservergroup" parameter + in localconfig. This means that certain files and directories which need + to be editable by both you and the webserver must be world writable, and + other files (including the localconfig file which stores your database + password) must be world readable. This means that _anyone_ who can obtain + local access to this machine can do whatever they want to your + [%+ terms.Bugzilla %] installation, and is probably also able to run + arbitrary Perl code as the user that the webserver runs as. + + You really, really, really need to change this setting. + **************************************************************************** + + [% ELSIF message_tag == "install_webservergroup_not_in" %] + Warning: you have entered a value for the "webservergroup" parameter in + localconfig, but you are not either a) running this script as [% constants.ROOT_USER FILTER html %]; + or b) a member of this group. This can cause permissions problems and + decreased security. If you experience problems running [% terms.Bugzilla %] + scripts, log in as [% constants.ROOT_USER FILTER html %] and re-run this script, become a + member of the group, or remove the value of the "webservergroup" parameter. + + [% ELSIF message_tag == "install_webservergroup_windows" %] + Warning: You have set webservergroup in [% constants.bz_locations.localconfig FILTER html %] + Please understand that this does not bring you any security when + running under Windows. + Verify that the file permissions in your [% terms.Bugzilla %] directory are + suitable for your system. Avoid unnecessary write access. + [% ELSIF message_tag == "product_invalid" %] [% title = "$terms.Bugzilla Component Descriptions" %] The product [% product FILTER html %] does not exist -- cgit v1.2.3-24-g4f1b