diff options
Diffstat (limited to 'Bugzilla/Config/Common.pm')
-rw-r--r-- | Bugzilla/Config/Common.pm | 610 |
1 files changed, 312 insertions, 298 deletions
diff --git a/Bugzilla/Config/Common.pm b/Bugzilla/Config/Common.pm index bd9b0bf84..a0077b5b2 100644 --- a/Bugzilla/Config/Common.pm +++ b/Bugzilla/Config/Common.pm @@ -21,392 +21,406 @@ use Bugzilla::Group; use Bugzilla::Status; use parent qw(Exporter); -@Bugzilla::Config::Common::EXPORT = - qw(check_multi check_numeric check_regexp check_url check_group - check_sslbase check_priority check_severity check_platform - check_opsys check_shadowdb check_urlbase check_webdotbase - check_user_verify_class check_ip check_font_file - check_mail_delivery_method check_notification check_utf8 - check_bug_status check_smtp_auth check_theschwartz_available - check_maxattachmentsize check_email check_smtp_ssl - check_comment_taggers_group check_smtp_server +@Bugzilla::Config::Common::EXPORT + = qw(check_multi check_numeric check_regexp check_url check_group + check_sslbase check_priority check_severity check_platform + check_opsys check_shadowdb check_urlbase check_webdotbase + check_user_verify_class check_ip check_font_file + check_mail_delivery_method check_notification check_utf8 + check_bug_status check_smtp_auth check_theschwartz_available + check_maxattachmentsize check_email check_smtp_ssl + check_comment_taggers_group check_smtp_server ); # Checking functions for the various values sub check_multi { - my ($value, $param) = (@_); + my ($value, $param) = (@_); - if ($param->{'type'} eq "s") { - unless (scalar(grep {$_ eq $value} (@{$param->{'choices'}}))) { - return "Invalid choice '$value' for single-select list param '$param->{'name'}'"; - } - - return ""; + if ($param->{'type'} eq "s") { + unless (scalar(grep { $_ eq $value } (@{$param->{'choices'}}))) { + return + "Invalid choice '$value' for single-select list param '$param->{'name'}'"; } - elsif ($param->{'type'} eq 'm' || $param->{'type'} eq 'o') { - if (ref($value) ne "ARRAY") { - $value = [split(',', $value)] - } - foreach my $chkParam (@$value) { - unless (scalar(grep {$_ eq $chkParam} (@{$param->{'choices'}}))) { - return "Invalid choice '$chkParam' for multi-select list param '$param->{'name'}'"; - } - } - - return ""; + + return ""; + } + elsif ($param->{'type'} eq 'm' || $param->{'type'} eq 'o') { + if (ref($value) ne "ARRAY") { + $value = [split(',', $value)]; } - else { - return "Invalid param type '$param->{'type'}' for check_multi(); " . - "contact your Bugzilla administrator"; + foreach my $chkParam (@$value) { + unless (scalar(grep { $_ eq $chkParam } (@{$param->{'choices'}}))) { + return + "Invalid choice '$chkParam' for multi-select list param '$param->{'name'}'"; + } } + + return ""; + } + else { + return "Invalid param type '$param->{'type'}' for check_multi(); " + . "contact your Bugzilla administrator"; + } } sub check_numeric { - my ($value) = (@_); - if ($value !~ /^[0-9]+$/) { - return "must be a numeric value"; - } - return ""; + my ($value) = (@_); + if ($value !~ /^[0-9]+$/) { + return "must be a numeric value"; + } + return ""; } sub check_regexp { - my ($value) = (@_); - eval { qr/$value/ }; - return $@; + my ($value) = (@_); + eval {qr/$value/}; + return $@; } sub check_email { - my ($value) = @_; - if ($value !~ $Email::Address::mailbox) { - return "must be a valid email address."; - } - return ""; + my ($value) = @_; + if ($value !~ $Email::Address::mailbox) { + return "must be a valid email address."; + } + return ""; } sub check_sslbase { - my $url = shift; - if ($url ne '') { - if ($url !~ m#^https://([^/]+).*/$#) { - return "must be a legal URL, that starts with https and ends with a slash."; - } - my $host = $1; - # Fall back to port 443 if for some reason getservbyname() fails. - my $port = getservbyname('https', 'tcp') || 443; - if ($host =~ /^(.+):(\d+)$/) { - $host = $1; - $port = $2; - } - local *SOCK; - my $proto = getprotobyname('tcp'); - socket(SOCK, PF_INET, SOCK_STREAM, $proto); - my $iaddr = inet_aton($host) || return "The host $host cannot be resolved"; - my $sin = sockaddr_in($port, $iaddr); - if (!connect(SOCK, $sin)) { - return "Failed to connect to $host:$port ($!); unable to enable SSL"; - } - close(SOCK); - } - return ""; + my $url = shift; + if ($url ne '') { + if ($url !~ m#^https://([^/]+).*/$#) { + return "must be a legal URL, that starts with https and ends with a slash."; + } + my $host = $1; + + # Fall back to port 443 if for some reason getservbyname() fails. + my $port = getservbyname('https', 'tcp') || 443; + if ($host =~ /^(.+):(\d+)$/) { + $host = $1; + $port = $2; + } + local *SOCK; + my $proto = getprotobyname('tcp'); + socket(SOCK, PF_INET, SOCK_STREAM, $proto); + my $iaddr = inet_aton($host) || return "The host $host cannot be resolved"; + my $sin = sockaddr_in($port, $iaddr); + if (!connect(SOCK, $sin)) { + return "Failed to connect to $host:$port ($!); unable to enable SSL"; + } + close(SOCK); + } + return ""; } sub check_ip { - my $inbound_proxies = shift; - my @proxies = split(/[\s,]+/, $inbound_proxies); - foreach my $proxy (@proxies) { - validate_ip($proxy) || return "$proxy is not a valid IPv4 or IPv6 address"; - } - return ""; + my $inbound_proxies = shift; + my @proxies = split(/[\s,]+/, $inbound_proxies); + foreach my $proxy (@proxies) { + validate_ip($proxy) || return "$proxy is not a valid IPv4 or IPv6 address"; + } + return ""; } sub check_utf8 { - my $utf8 = shift; - # You cannot turn off the UTF-8 parameter if you've already converted - # your tables to utf-8. - my $dbh = Bugzilla->dbh; - if ($dbh->isa('Bugzilla::DB::Mysql') && $dbh->bz_db_is_utf8 && !$utf8) { - return "You cannot disable UTF-8 support, because your MySQL database" - . " is encoded in UTF-8"; - } - return ""; + my $utf8 = shift; + + # You cannot turn off the UTF-8 parameter if you've already converted + # your tables to utf-8. + my $dbh = Bugzilla->dbh; + if ($dbh->isa('Bugzilla::DB::Mysql') && $dbh->bz_db_is_utf8 && !$utf8) { + return "You cannot disable UTF-8 support, because your MySQL database" + . " is encoded in UTF-8"; + } + return ""; } sub check_priority { - my ($value) = (@_); - my $legal_priorities = get_legal_field_values('priority'); - if (!grep($_ eq $value, @$legal_priorities)) { - return "Must be a legal priority value: one of " . - join(", ", @$legal_priorities); - } - return ""; + my ($value) = (@_); + my $legal_priorities = get_legal_field_values('priority'); + if (!grep($_ eq $value, @$legal_priorities)) { + return "Must be a legal priority value: one of " + . join(", ", @$legal_priorities); + } + return ""; } sub check_severity { - my ($value) = (@_); - my $legal_severities = get_legal_field_values('bug_severity'); - if (!grep($_ eq $value, @$legal_severities)) { - return "Must be a legal severity value: one of " . - join(", ", @$legal_severities); - } - return ""; + my ($value) = (@_); + my $legal_severities = get_legal_field_values('bug_severity'); + if (!grep($_ eq $value, @$legal_severities)) { + return "Must be a legal severity value: one of " + . join(", ", @$legal_severities); + } + return ""; } sub check_platform { - my ($value) = (@_); - my $legal_platforms = get_legal_field_values('rep_platform'); - if (!grep($_ eq $value, '', @$legal_platforms)) { - return "Must be empty or a legal platform value: one of " . - join(", ", @$legal_platforms); - } - return ""; + my ($value) = (@_); + my $legal_platforms = get_legal_field_values('rep_platform'); + if (!grep($_ eq $value, '', @$legal_platforms)) { + return "Must be empty or a legal platform value: one of " + . join(", ", @$legal_platforms); + } + return ""; } sub check_opsys { - my ($value) = (@_); - my $legal_OS = get_legal_field_values('op_sys'); - if (!grep($_ eq $value, '', @$legal_OS)) { - return "Must be empty or a legal operating system value: one of " . - join(", ", @$legal_OS); - } - return ""; + my ($value) = (@_); + my $legal_OS = get_legal_field_values('op_sys'); + if (!grep($_ eq $value, '', @$legal_OS)) { + return "Must be empty or a legal operating system value: one of " + . join(", ", @$legal_OS); + } + return ""; } sub check_bug_status { - my $bug_status = shift; - my @closed_bug_statuses = map {$_->name} closed_bug_statuses(); - if (!grep($_ eq $bug_status, @closed_bug_statuses)) { - return "Must be a valid closed status: one of " . join(', ', @closed_bug_statuses); - } - return ""; + my $bug_status = shift; + my @closed_bug_statuses = map { $_->name } closed_bug_statuses(); + if (!grep($_ eq $bug_status, @closed_bug_statuses)) { + return "Must be a valid closed status: one of " + . join(', ', @closed_bug_statuses); + } + return ""; } sub check_group { - my $group_name = shift; - return "" unless $group_name; - my $group = new Bugzilla::Group({'name' => $group_name}); - unless (defined $group) { - return "Must be an existing group name"; - } - return ""; + my $group_name = shift; + return "" unless $group_name; + my $group = new Bugzilla::Group({'name' => $group_name}); + unless (defined $group) { + return "Must be an existing group name"; + } + return ""; } sub check_shadowdb { - my ($value) = (@_); - $value = trim($value); - if ($value eq "") { - return ""; - } + my ($value) = (@_); + $value = trim($value); + if ($value eq "") { + return ""; + } - if (!Bugzilla->params->{'shadowdbhost'}) { - return "You need to specify a host when using a shadow database"; - } + if (!Bugzilla->params->{'shadowdbhost'}) { + return "You need to specify a host when using a shadow database"; + } - # Can't test existence of this because ConnectToDatabase uses the param, - # but we can't set this before testing.... - # This can really only be fixed after we can use the DBI more openly - return ""; + # Can't test existence of this because ConnectToDatabase uses the param, + # but we can't set this before testing.... + # This can really only be fixed after we can use the DBI more openly + return ""; } sub check_urlbase { - my ($url) = (@_); - if ($url && $url !~ m:^http.*/$:) { - return "must be a legal URL, that starts with http and ends with a slash."; - } - return ""; + my ($url) = (@_); + if ($url && $url !~ m:^http.*/$:) { + return "must be a legal URL, that starts with http and ends with a slash."; + } + return ""; } sub check_url { - my ($url) = (@_); - return '' if $url eq ''; # Allow empty URLs - if ($url !~ m:/$:) { - return 'must be a legal URL, absolute or relative, ending with a slash.'; - } - return ''; + my ($url) = (@_); + return '' if $url eq ''; # Allow empty URLs + if ($url !~ m:/$:) { + return 'must be a legal URL, absolute or relative, ending with a slash.'; + } + return ''; } sub check_webdotbase { - my ($value) = (@_); - $value = trim($value); - if ($value eq "") { - return ""; - } - if($value !~ /^https?:/) { - if(! -x $value) { - return "The file path \"$value\" is not a valid executable. Please specify the complete file path to 'dot' if you intend to generate graphs locally."; - } - # Check .htaccess allows access to generated images - my $webdotdir = bz_locations()->{'webdotdir'}; - if(-e "$webdotdir/.htaccess") { - open HTACCESS, "<", "$webdotdir/.htaccess"; - if(! grep(/ \\\.png\$/,<HTACCESS>)) { - return "Dependency graph images are not accessible.\nAssuming that you have not modified the file, delete $webdotdir/.htaccess and re-run checksetup.pl to rectify.\n"; - } - close HTACCESS; - } - } + my ($value) = (@_); + $value = trim($value); + if ($value eq "") { return ""; + } + if ($value !~ /^https?:/) { + if (!-x $value) { + return + "The file path \"$value\" is not a valid executable. Please specify the complete file path to 'dot' if you intend to generate graphs locally."; + } + + # Check .htaccess allows access to generated images + my $webdotdir = bz_locations()->{'webdotdir'}; + if (-e "$webdotdir/.htaccess") { + open HTACCESS, "<", "$webdotdir/.htaccess"; + if (!grep(/ \\\.png\$/, <HTACCESS>)) { + return + "Dependency graph images are not accessible.\nAssuming that you have not modified the file, delete $webdotdir/.htaccess and re-run checksetup.pl to rectify.\n"; + } + close HTACCESS; + } + } + return ""; } sub check_font_file { - my ($font) = @_; - $font = trim($font); - return '' unless $font; - - if ($font !~ /\.(ttf|otf)$/) { - return "The file must point to a TrueType or OpenType font file (its extension must be .ttf or .otf)" - } - if (! -f $font) { - return "The file '$font' cannot be found. Make sure you typed the full path to the file" - } - return ''; + my ($font) = @_; + $font = trim($font); + return '' unless $font; + + if ($font !~ /\.(ttf|otf)$/) { + return + "The file must point to a TrueType or OpenType font file (its extension must be .ttf or .otf)"; + } + if (!-f $font) { + return + "The file '$font' cannot be found. Make sure you typed the full path to the file"; + } + return ''; } sub check_user_verify_class { - # doeditparams traverses the list of params, and for each one it checks, - # then updates. This means that if one param checker wants to look at - # other params, it must be below that other one. So you can't have two - # params mutually dependent on each other. - # This means that if someone clears the LDAP config params after setting - # the login method as LDAP, we won't notice, but all logins will fail. - # So don't do that. - - my $params = Bugzilla->params; - my ($list, $entry) = @_; - $list || return 'You need to specify at least one authentication mechanism'; - for my $class (split /,\s*/, $list) { - my $res = check_multi($class, $entry); - return $res if $res; - if ($class eq 'RADIUS') { - if (!Bugzilla->feature('auth_radius')) { - return "RADIUS support is not available. Run checksetup.pl" - . " for more details"; - } - return "RADIUS servername (RADIUS_server) is missing" - if !$params->{"RADIUS_server"}; - return "RADIUS_secret is empty" if !$params->{"RADIUS_secret"}; - } - elsif ($class eq 'LDAP') { - if (!Bugzilla->feature('auth_ldap')) { - return "LDAP support is not available. Run checksetup.pl" - . " for more details"; - } - return "LDAP servername (LDAPserver) is missing" - if !$params->{"LDAPserver"}; - return "LDAPBaseDN is empty" if !$params->{"LDAPBaseDN"}; - } - } - return ""; + + # doeditparams traverses the list of params, and for each one it checks, + # then updates. This means that if one param checker wants to look at + # other params, it must be below that other one. So you can't have two + # params mutually dependent on each other. + # This means that if someone clears the LDAP config params after setting + # the login method as LDAP, we won't notice, but all logins will fail. + # So don't do that. + + my $params = Bugzilla->params; + my ($list, $entry) = @_; + $list || return 'You need to specify at least one authentication mechanism'; + for my $class (split /,\s*/, $list) { + my $res = check_multi($class, $entry); + return $res if $res; + if ($class eq 'RADIUS') { + if (!Bugzilla->feature('auth_radius')) { + return "RADIUS support is not available. Run checksetup.pl" + . " for more details"; + } + return "RADIUS servername (RADIUS_server) is missing" + if !$params->{"RADIUS_server"}; + return "RADIUS_secret is empty" if !$params->{"RADIUS_secret"}; + } + elsif ($class eq 'LDAP') { + if (!Bugzilla->feature('auth_ldap')) { + return "LDAP support is not available. Run checksetup.pl" . " for more details"; + } + return "LDAP servername (LDAPserver) is missing" if !$params->{"LDAPserver"}; + return "LDAPBaseDN is empty" if !$params->{"LDAPBaseDN"}; + } + } + return ""; } sub check_mail_delivery_method { - my $check = check_multi(@_); - return $check if $check; - my $mailer = shift; - if ($mailer eq 'Sendmail' and ON_WINDOWS) { - # look for sendmail.exe - return "Failed to locate " . SENDMAIL_EXE - unless -e SENDMAIL_EXE; - } - return ""; + my $check = check_multi(@_); + return $check if $check; + my $mailer = shift; + if ($mailer eq 'Sendmail' and ON_WINDOWS) { + + # look for sendmail.exe + return "Failed to locate " . SENDMAIL_EXE unless -e SENDMAIL_EXE; + } + return ""; } sub check_maxattachmentsize { - my $check = check_numeric(@_); - return $check if $check; - my $size = shift; - my $dbh = Bugzilla->dbh; - if ($dbh->isa('Bugzilla::DB::Mysql')) { - my (undef, $max_packet) = $dbh->selectrow_array( - q{SHOW VARIABLES LIKE 'max\_allowed\_packet'}); - my $byte_size = $size * 1024; - if ($max_packet < $byte_size) { - return "You asked for a maxattachmentsize of $byte_size bytes," - . " but the max_allowed_packet setting in MySQL currently" - . " only allows packets up to $max_packet bytes"; - } - } - return ""; + my $check = check_numeric(@_); + return $check if $check; + my $size = shift; + my $dbh = Bugzilla->dbh; + if ($dbh->isa('Bugzilla::DB::Mysql')) { + my (undef, $max_packet) + = $dbh->selectrow_array(q{SHOW VARIABLES LIKE 'max\_allowed\_packet'}); + my $byte_size = $size * 1024; + if ($max_packet < $byte_size) { + return + "You asked for a maxattachmentsize of $byte_size bytes," + . " but the max_allowed_packet setting in MySQL currently" + . " only allows packets up to $max_packet bytes"; + } + } + return ""; } sub check_notification { - my $option = shift; - my @current_version = - (BUGZILLA_VERSION =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/); - if ($current_version[1] % 2 && $option eq 'stable_branch_release') { - return "You are currently running a development snapshot, and so your " . - "installation is not based on a branch. If you want to be notified " . - "about the next stable release, you should select " . - "'latest_stable_release' instead"; - } - if ($option ne 'disabled' && !Bugzilla->feature('updates')) { - return "Some Perl modules are missing to get notifications about " . - "new releases. See the output of checksetup.pl for more information"; - } - return ""; + my $option = shift; + my @current_version + = (BUGZILLA_VERSION =~ m/^(\d+)\.(\d+)(?:(rc|\.)(\d+))?\+?$/); + if ($current_version[1] % 2 && $option eq 'stable_branch_release') { + return + "You are currently running a development snapshot, and so your " + . "installation is not based on a branch. If you want to be notified " + . "about the next stable release, you should select " + . "'latest_stable_release' instead"; + } + if ($option ne 'disabled' && !Bugzilla->feature('updates')) { + return "Some Perl modules are missing to get notifications about " + . "new releases. See the output of checksetup.pl for more information"; + } + return ""; } sub check_smtp_server { - my $host = shift; - my $port; - - return '' unless $host; - - if ($host =~ /:/) { - ($host, $port) = split(/:/, $host, 2); - unless ($port && detaint_natural($port)) { - return "Invalid port. It must be an integer (typically 25, 465 or 587)"; - } - } - trick_taint($host); - # Let's first try to connect using SSL. If this fails, we fall back to - # an unencrypted connection. - foreach my $method (['Net::SMTP::SSL', 465], ['Net::SMTP', 25]) { - my ($class, $default_port) = @$method; - next if $class eq 'Net::SMTP::SSL' && !Bugzilla->feature('smtp_ssl'); - eval "require $class"; - my $smtp = $class->new($host, Port => $port || $default_port, Timeout => 5); - if ($smtp) { - # The connection works! - $smtp->quit; - return ''; - } - } - return "Cannot connect to $host" . ($port ? " using port $port" : ""); + my $host = shift; + my $port; + + return '' unless $host; + + if ($host =~ /:/) { + ($host, $port) = split(/:/, $host, 2); + unless ($port && detaint_natural($port)) { + return "Invalid port. It must be an integer (typically 25, 465 or 587)"; + } + } + trick_taint($host); + + # Let's first try to connect using SSL. If this fails, we fall back to + # an unencrypted connection. + foreach my $method (['Net::SMTP::SSL', 465], ['Net::SMTP', 25]) { + my ($class, $default_port) = @$method; + next if $class eq 'Net::SMTP::SSL' && !Bugzilla->feature('smtp_ssl'); + eval "require $class"; + my $smtp = $class->new($host, Port => $port || $default_port, Timeout => 5); + if ($smtp) { + + # The connection works! + $smtp->quit; + return ''; + } + } + return "Cannot connect to $host" . ($port ? " using port $port" : ""); } sub check_smtp_auth { - my $username = shift; - if ($username and !Bugzilla->feature('smtp_auth')) { - return "SMTP Authentication is not available. Run checksetup.pl for" - . " more details"; - } - return ""; + my $username = shift; + if ($username and !Bugzilla->feature('smtp_auth')) { + return "SMTP Authentication is not available. Run checksetup.pl for" + . " more details"; + } + return ""; } sub check_smtp_ssl { - my $use_ssl = shift; - if ($use_ssl && !Bugzilla->feature('smtp_ssl')) { - return "SSL support is not available. Run checksetup.pl for more details"; - } - return ""; + my $use_ssl = shift; + if ($use_ssl && !Bugzilla->feature('smtp_ssl')) { + return "SSL support is not available. Run checksetup.pl for more details"; + } + return ""; } sub check_theschwartz_available { - my $use_queue = shift; - if ($use_queue && !Bugzilla->feature('jobqueue')) { - return "Using the job queue requires that you have certain Perl" - . " modules installed. See the output of checksetup.pl" - . " for more information"; - } - return ""; + my $use_queue = shift; + if ($use_queue && !Bugzilla->feature('jobqueue')) { + return + "Using the job queue requires that you have certain Perl" + . " modules installed. See the output of checksetup.pl" + . " for more information"; + } + return ""; } sub check_comment_taggers_group { - my $group_name = shift; - if ($group_name && !Bugzilla->feature('jsonrpc')) { - return "Comment tagging requires installation of the JSONRPC feature"; - } - return check_group($group_name); + my $group_name = shift; + if ($group_name && !Bugzilla->feature('jsonrpc')) { + return "Comment tagging requires installation of the JSONRPC feature"; + } + return check_group($group_name); } # OK, here are the parameter definitions themselves. @@ -467,13 +481,13 @@ sub check_comment_taggers_group { # } # # Here, 'b' is the default option, and 'a' and 'c' are other possible -# options, but only one at a time! +# options, but only one at a time! # # &check_multi should always be used as the param verification function # for list (single and multiple) parameter types. sub get_param_list { - return; + return; } 1; |