460 lines
14 KiB
Perl
460 lines
14 KiB
Perl
# -*- 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>
|
|
# Jacob Steenhagen <jake@bugzilla.org>
|
|
# J. Paul Reed <preed@sigkill.com>
|
|
# Bradley Baetz <bbaetz@student.usyd.edu.au>
|
|
# Joseph Heenan <joseph@heenan.me.uk>
|
|
# Erik Stambaugh <erik@dasbistro.com>
|
|
# Frédéric Buclin <LpSolit@gmail.com>
|
|
# Marc Schumann <wurblzap@gmail.com>
|
|
#
|
|
|
|
package Bugzilla::Config::Common;
|
|
|
|
use strict;
|
|
|
|
use Email::Address;
|
|
use Socket;
|
|
|
|
use Bugzilla::Util;
|
|
use Bugzilla::Constants;
|
|
use Bugzilla::Field;
|
|
use Bugzilla::Group;
|
|
use Bugzilla::Status;
|
|
|
|
use base 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_mail_delivery_method check_notification check_utf8
|
|
check_bug_status check_smtp_auth check_theschwartz_available
|
|
check_maxattachmentsize check_email
|
|
);
|
|
|
|
# Checking functions for the various values
|
|
|
|
sub check_multi {
|
|
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 "";
|
|
}
|
|
elsif ($param->{'type'} eq 'm' || $param->{'type'} eq 'o') {
|
|
foreach my $chkParam (split(',', $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 "";
|
|
}
|
|
|
|
sub check_regexp {
|
|
my ($value) = (@_);
|
|
eval { qr/$value/ };
|
|
return $@;
|
|
}
|
|
|
|
sub check_email {
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
sub check_priority {
|
|
my ($value) = (@_);
|
|
my $legal_priorities = get_legal_field_values('priority');
|
|
if (lsearch($legal_priorities, $value) < 0) {
|
|
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 (lsearch($legal_severities, $value) < 0) {
|
|
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 (lsearch(['', @$legal_platforms], $value) < 0) {
|
|
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 (lsearch(['', @$legal_OS], $value) < 0) {
|
|
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 (lsearch(\@closed_bug_statuses, $bug_status) < 0) {
|
|
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 "";
|
|
}
|
|
|
|
sub check_shadowdb {
|
|
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";
|
|
}
|
|
|
|
# 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 "";
|
|
}
|
|
|
|
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 '';
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
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 "";
|
|
}
|
|
|
|
# OK, here are the parameter definitions themselves.
|
|
#
|
|
# Each definition is a hash with keys:
|
|
#
|
|
# name - name of the param
|
|
# desc - description of the param (for editparams.cgi)
|
|
# type - see below
|
|
# choices - (optional) see below
|
|
# default - default value for the param
|
|
# checker - (optional) checking function for validating parameter entry
|
|
# It is called with the value of the param as the first arg and a
|
|
# reference to the param's hash as the second argument
|
|
#
|
|
# The type value can be one of the following:
|
|
#
|
|
# t -- A short text entry field (suitable for a single line)
|
|
# p -- A short text entry field (as with type = 't'), but the string is
|
|
# replaced by asterisks (appropriate for passwords)
|
|
# l -- A long text field (suitable for many lines)
|
|
# b -- A boolean value (either 1 or 0)
|
|
# m -- A list of values, with many selectable (shows up as a select box)
|
|
# To specify the list of values, make the 'choices' key be an array
|
|
# reference of the valid choices. The 'default' key should be a string
|
|
# with a list of selected values (as a comma-separated list), i.e.:
|
|
# {
|
|
# name => 'multiselect',
|
|
# desc => 'A list of options, choose many',
|
|
# type => 'm',
|
|
# choices => [ 'a', 'b', 'c', 'd' ],
|
|
# default => [ 'a', 'd' ],
|
|
# checker => \&check_multi
|
|
# }
|
|
#
|
|
# Here, 'a' and 'd' are the default options, and the user may pick any
|
|
# combination of a, b, c, and d as valid options.
|
|
#
|
|
# &check_multi should always be used as the param verification function
|
|
# for list (single and multiple) parameter types.
|
|
#
|
|
# o -- A list of values, orderable, and with many selectable (shows up as a
|
|
# JavaScript-enhanced select box if JavaScript is enabled, and a text
|
|
# entry field if not)
|
|
# Set up in the same way as type m.
|
|
#
|
|
# s -- A list of values, with one selectable (shows up as a select box)
|
|
# To specify the list of values, make the 'choices' key be an array
|
|
# reference of the valid choices. The 'default' key should be one of
|
|
# those values, i.e.:
|
|
# {
|
|
# name => 'singleselect',
|
|
# desc => 'A list of options, choose one',
|
|
# type => 's',
|
|
# choices => [ 'a', 'b', 'c' ],
|
|
# default => 'b',
|
|
# checker => \&check_multi
|
|
# }
|
|
#
|
|
# Here, 'b' is the default option, and 'a' and 'c' are other possible
|
|
# 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;
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=head1 NAME
|
|
|
|
Bugzilla::Config::Common - Parameter checking functions
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
All parameter checking functions are called with two parameters:
|
|
|
|
=head2 Functions
|
|
|
|
=over
|
|
|
|
=item C<check_multi>
|
|
|
|
Checks that a multi-valued parameter (ie types C<s>, C<o> or C<m>) satisfies
|
|
its contraints.
|
|
|
|
=item C<check_numeric>
|
|
|
|
Checks that the value is a valid number
|
|
|
|
=item C<check_regexp>
|
|
|
|
Checks that the value is a valid regexp
|
|
|
|
=back
|