diff options
Diffstat (limited to 'Bugzilla')
-rw-r--r-- | Bugzilla/CGI.pm | 18 | ||||
-rw-r--r-- | Bugzilla/Constants.pm | 5 | ||||
-rw-r--r-- | Bugzilla/DB.pm | 9 | ||||
-rw-r--r-- | Bugzilla/Error.pm | 10 | ||||
-rw-r--r-- | Bugzilla/Install/Localconfig.pm | 8 | ||||
-rw-r--r-- | Bugzilla/JobQueue.pm | 4 | ||||
-rw-r--r-- | Bugzilla/JobQueue/Runner.pm | 10 | ||||
-rw-r--r-- | Bugzilla/Mailer.pm | 9 | ||||
-rw-r--r-- | Bugzilla/Memcached.pm | 26 | ||||
-rw-r--r-- | Bugzilla/ModPerl.pm | 8 | ||||
-rw-r--r-- | Bugzilla/ModPerl/BasicAuth.pm | 13 | ||||
-rw-r--r-- | Bugzilla/ModPerl/Hostage.pm | 71 | ||||
-rw-r--r-- | Bugzilla/WebService/Server/REST.pm | 3 |
13 files changed, 150 insertions, 44 deletions
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index cd947841e..b0bc15e78 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -600,16 +600,18 @@ sub param { # We don't let CGI.pm warn about list context, but we do it ourselves. local $CGI::LIST_CONTEXT_WARN = 0; - state $has_warned = {}; - - ## no critic (Freenode::Wantarray) - if ( wantarray && @_ ) { - my ( $package, $filename, $line ) = caller; - if ( $package ne 'CGI' && ! $has_warned->{"$filename:$line"}++) { - WARN("Bugzilla::CGI::param called in list context from $package $filename:$line"); + if (0) { + state $has_warned = {}; + + ## no critic (Freenode::Wantarray) + if ( wantarray && @_ ) { + my ( $package, $filename, $line ) = caller; + if ( $package ne 'CGI' && ! $has_warned->{"$filename:$line"}++) { + WARN("Bugzilla::CGI::param called in list context from $package $filename:$line"); + } } + ## use critic } - ## use critic # When we are just requesting the value of a parameter... if (scalar(@_) == 1) { diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 00f0f8104..6e3a12736 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -19,7 +19,6 @@ use Memoize; @Bugzilla::Constants::EXPORT = qw( BUGZILLA_VERSION - REST_DOC REMOTE_FILE LOCAL_FILE @@ -209,10 +208,6 @@ sub BUGZILLA_VERSION { eval { Bugzilla->VERSION } || $bugzilla_version; } -# A base link to the current REST Documentation. We place it here -# as it will need to be updated to whatever the current release is. -use constant REST_DOC => "https://bugzilla.readthedocs.io/en/latest/api/"; - # Location of the remote and local XML files to track new releases. use constant REMOTE_FILE => 'http://updates.bugzilla.org/bugzilla-update.xml'; use constant LOCAL_FILE => 'bugzilla-update.xml'; # Relative to datadir. diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index ff75aa2cf..0dfa47c23 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -111,8 +111,13 @@ sub connect_shadow { my $connect_params = dclone(Bugzilla->localconfig); $connect_params->{db_host} = Bugzilla->get_param_with_override('shadowdbhost'); $connect_params->{db_name} = Bugzilla->get_param_with_override('shadowdb'); - $connect_params->{db_port} = Bugzilla->get_param_with_override('shadowport'); - $connect_params->{db_sock} = Bugzilla->get_param_with_override('shadowsock'); + $connect_params->{db_port} = Bugzilla->get_param_with_override('shadowdbport'); + $connect_params->{db_sock} = Bugzilla->get_param_with_override('shadowdbsock'); + + if ( Bugzilla->localconfig->{'shadowdb_user'} && Bugzilla->localconfig->{'shadowdb_pass'} ) { + $connect_params->{db_user} = Bugzilla->localconfig->{'shadowdb_user'}; + $connect_params->{db_pass} = Bugzilla->localconfig->{'shadowdb_pass'}; + } return _connect($connect_params); } diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm index e7a99dba0..d67571848 100644 --- a/Bugzilla/Error.pm +++ b/Bugzilla/Error.pm @@ -38,15 +38,14 @@ sub _in_eval { sub _throw_error { my ($name, $error, $vars) = @_; - my $dbh = Bugzilla->dbh; $vars ||= {}; - $vars->{error} = $error; # Make sure any transaction is rolled back (if supported). # If we are within an eval(), do not roll back transactions as we are # eval'uating some test on purpose. - $dbh->bz_rollback_transaction() if ($dbh->bz_in_transaction() && !_in_eval()); + my $dbh = eval { Bugzilla->dbh }; + $dbh->bz_rollback_transaction() if ($dbh && $dbh->bz_in_transaction() && !_in_eval()); my $datadir = bz_locations()->{'datadir'}; # If a writable $datadir/errorlog exists, log error details there. @@ -191,10 +190,9 @@ sub ThrowCodeError { sub ThrowTemplateError { my ($template_err) = @_; - my $dbh = Bugzilla->dbh; - + my $dbh = eval { Bugzilla->dbh }; # Make sure the transaction is rolled back (if supported). - $dbh->bz_rollback_transaction() if $dbh->bz_in_transaction(); + $dbh->bz_rollback_transaction() if $dbh && $dbh->bz_in_transaction(); if (blessed($template_err) && $template_err->isa('Template::Exception')) { my $type = $template_err->type; diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm index de2219f16..7a913358c 100644 --- a/Bugzilla/Install/Localconfig.pm +++ b/Bugzilla/Install/Localconfig.pm @@ -175,6 +175,14 @@ use constant LOCALCONFIG_VARS => ( name => 'inbound_proxies', default => _migrate_param( 'inbound_proxies', '' ), }, + { + name => 'shadowdb_user', + default => '', + }, + { + name => 'shadowdb_pass', + default => '', + } ); diff --git a/Bugzilla/JobQueue.pm b/Bugzilla/JobQueue.pm index 8c8d73dcd..53b088c6e 100644 --- a/Bugzilla/JobQueue.pm +++ b/Bugzilla/JobQueue.pm @@ -101,12 +101,12 @@ sub debug { my $caller_pkg = caller; local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 1; my $logger = Log::Log4perl->get_logger($caller_pkg); - $logger->debug(@args); + $logger->info(@args); } sub work { my ($self, $delay) = @_; - $delay ||= 5; + $delay ||= 1; my $loop = IO::Async::Loop->new; my $timer = IO::Async::Timer::Periodic->new( first_interval => 0, diff --git a/Bugzilla/JobQueue/Runner.pm b/Bugzilla/JobQueue/Runner.pm index 1c74bc28f..0177de40a 100644 --- a/Bugzilla/JobQueue/Runner.pm +++ b/Bugzilla/JobQueue/Runner.pm @@ -26,7 +26,7 @@ use Cwd qw(abs_path); use English qw(-no_match_vars $PROGRAM_NAME $EXECUTABLE_NAME); use File::Basename; use File::Copy; -use File::Spec::Functions qw(catfile); +use File::Spec::Functions qw(catfile tmpdir); use Future; use Future::Utils qw(fmap_void); use IO::Async::Loop; @@ -52,7 +52,7 @@ sub gd_preconfig { my $pidfile = $self->{gd_args}{pidfile}; if ( !$pidfile ) { - $pidfile = bz_locations()->{datadir} . '/' . $self->{gd_progname} . '.pid'; + $pidfile = catfile(tmpdir(), $self->{gd_progname} . '.pid'); } return ( pidfile => $pidfile ); } @@ -211,7 +211,7 @@ sub gd_run { my $self = shift; my $jobs = $self->{gd_args}{jobs} // 1; my $signal_f = $self->{_signal_future}; - my $workers_f = fmap_void { $self->run_worker("work") } + my $workers_f = fmap_void { $self->run_worker() } concurrent => $jobs, generate => sub { !$signal_f->is_ready }; @@ -225,10 +225,10 @@ sub gd_run { # This executes the script "jobqueue-worker.pl" # $EXECUTABLE_NAME is the name of the perl interpreter. sub run_worker { - my ( $self, $fn ) = @_; + my ( $self ) = @_; my $script = catfile( bz_locations->{cgi_path}, 'jobqueue-worker.pl' ); - my @command = ( $EXECUTABLE_NAME, $script, '--function' => $fn ); + my @command = ( $EXECUTABLE_NAME, $script); if ( $self->{gd_args}{progname} ) { push @command, '--name' => "$self->{gd_args}{progname} [worker]"; } diff --git a/Bugzilla/Mailer.pm b/Bugzilla/Mailer.pm index e245a05e0..1dec3d4ff 100644 --- a/Bugzilla/Mailer.pm +++ b/Bugzilla/Mailer.pm @@ -252,15 +252,14 @@ sub build_thread_marker { $sitespec = "-$2$sitespec"; # Put the port number back in, before the '@' } - my $threadingmarker; + my $threadingmarker = "References: <bug-$bug_id-$user_id$sitespec>"; if ($is_new) { - $threadingmarker = "Message-ID: <bug-$bug_id-$user_id$sitespec>"; + $threadingmarker .= "\nMessage-ID: <bug-$bug_id-$user_id$sitespec>"; } else { my $rand_bits = generate_random_password(10); - $threadingmarker = "Message-ID: <bug-$bug_id-$user_id-$rand_bits$sitespec>" . - "\nIn-Reply-To: <bug-$bug_id-$user_id$sitespec>" . - "\nReferences: <bug-$bug_id-$user_id$sitespec>"; + $threadingmarker .= "\nMessage-ID: <bug-$bug_id-$user_id-$rand_bits$sitespec>" . + "\nIn-Reply-To: <bug-$bug_id-$user_id$sitespec>"; } return $threadingmarker; diff --git a/Bugzilla/Memcached.pm b/Bugzilla/Memcached.pm index 85e3505e1..d34aaa595 100644 --- a/Bugzilla/Memcached.pm +++ b/Bugzilla/Memcached.pm @@ -36,11 +36,25 @@ sub _new { if (Bugzilla->feature('memcached') && $servers) { $self->{namespace} = Bugzilla->localconfig->{memcached_namespace}; TRACE("connecting servers: $servers, namespace: $self->{namespace}"); - $self->{memcached} = Cache::Memcached::Fast->new({ - servers => [ _parse_memcached_server_list($servers) ], - namespace => $self->{namespace}, - max_size => 1024 * 1024 * 4, - }); + $self->{memcached} = Cache::Memcached::Fast->new( + { + servers => [ _parse_memcached_server_list($servers) ], + namespace => $self->{namespace}, + max_size => 1024 * 1024 * 4, + max_failures => 1, + failure_timeout => 60, + io_timeout => 0.2, + connect_timeout => 0.2, + } + ); + my $versions = $self->{memcached}->server_versions; + if (keys %$versions) { + # this is needed to ensure forked processes don't start out with a connected memcached socket. + $self->{memcached}->disconnect_all; + } + else { + WARN("No memcached servers"); + } } else { TRACE("memcached feature is not enabled"); @@ -324,7 +338,7 @@ sub _get { my $enc_key = $self->_encode_key($key) or return; - my $val = $self->{memcached}->get($key); + my $val = $self->{memcached}->get($enc_key); TRACE("get $enc_key: " . (defined $val ? "HIT" : "MISS")); return $val; } diff --git a/Bugzilla/ModPerl.pm b/Bugzilla/ModPerl.pm index a5c840897..120dd8210 100644 --- a/Bugzilla/ModPerl.pm +++ b/Bugzilla/ModPerl.pm @@ -20,6 +20,7 @@ use Carp (); use Template (); use Bugzilla::ModPerl::BlockIP; +use Bugzilla::ModPerl::Hostage; sub apache_config { my ($class, $cgi_path) = @_; @@ -74,6 +75,7 @@ __DATA__ # the built-in rand(), even though we never use it in Bugzilla itself, # so we need to srand() both of them.) PerlChildInitHandler "sub { Bugzilla::RNG::srand(); srand(); }" +PerlInitHandler Bugzilla::ModPerl::Hostage PerlAccessHandler Bugzilla::ModPerl::BlockIP # It is important to specify ErrorDocuments outside of all directories. @@ -84,6 +86,12 @@ ErrorDocument 403 /errors/403.html ErrorDocument 404 /errors/404.html ErrorDocument 500 /errors/500.html +<Location /helper> + SetHandler perl-script + PerlResponseHandler Plack::Handler::Apache2 + PerlSetVar psgi_app [% cgi_path %]/helper.psgi +</Location> + <Directory "[% cgi_path %]"> AddHandler perl-script .cgi # No need to PerlModule these because they're already defined in mod_perl.pl diff --git a/Bugzilla/ModPerl/BasicAuth.pm b/Bugzilla/ModPerl/BasicAuth.pm index e93680e9d..7248a19f3 100644 --- a/Bugzilla/ModPerl/BasicAuth.pm +++ b/Bugzilla/ModPerl/BasicAuth.pm @@ -25,18 +25,22 @@ use warnings; # AUTH_VAR_NAME and AUTH_VAR_PASS are the names of variables defined in # `localconfig` which hold the authentication credentials. -use Apache2::Const -compile => qw(OK HTTP_UNAUTHORIZED); +use Apache2::Const -compile => qw(OK HTTP_UNAUTHORIZED); ## no critic (Freenode::ModPerl) +use Bugzilla::Logging; use Bugzilla (); sub handler { my $r = shift; my ($status, $password) = $r->get_basic_auth_pw; - return $status if $status != Apache2::Const::OK; + if ($status != Apache2::Const::OK) { + WARN("Got non-OK status: $status when trying to get password"); + return $status + } my $auth_var_name = $ENV{AUTH_VAR_NAME}; my $auth_var_pass = $ENV{AUTH_VAR_PASS}; unless ($auth_var_name && $auth_var_pass) { - warn "AUTH_VAR_NAME and AUTH_VAR_PASS environmental vars not set\n"; + ERROR('AUTH_VAR_NAME and AUTH_VAR_PASS environmental vars not set'); $r->note_basic_auth_failure; return Apache2::Const::HTTP_UNAUTHORIZED; } @@ -44,13 +48,14 @@ sub handler { my $auth_user = Bugzilla->localconfig->{$auth_var_name}; my $auth_pass = Bugzilla->localconfig->{$auth_var_pass}; unless ($auth_user && $auth_pass) { - warn "$auth_var_name and $auth_var_pass not configured\n"; + ERROR("$auth_var_name and $auth_var_pass not configured"); $r->note_basic_auth_failure; return Apache2::Const::HTTP_UNAUTHORIZED; } unless ($r->user eq $auth_user && $password eq $auth_pass) { $r->note_basic_auth_failure; + WARN('username and password do not match'); return Apache2::Const::HTTP_UNAUTHORIZED; } diff --git a/Bugzilla/ModPerl/Hostage.pm b/Bugzilla/ModPerl/Hostage.pm new file mode 100644 index 000000000..a3bdfac58 --- /dev/null +++ b/Bugzilla/ModPerl/Hostage.pm @@ -0,0 +1,71 @@ +package Bugzilla::ModPerl::Hostage; +use 5.10.1; +use strict; +use warnings; + +use Apache2::Const qw(:common); ## no critic (Freenode::ModPerl) + +sub _attachment_root { + my ($base) = @_; + return undef unless $base; + return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)} + ? $1 + : undef; +} + +sub _attachment_host_regex { + my ($base) = @_; + return undef unless $base; + my $val = $base; + $val =~ s{^https?://}{}s; + $val =~ s{/$}{}s; + my $regex = quotemeta $val; + $regex =~ s/\\\%bugid\\\%/\\d+/g; + return qr/^$regex$/s; +} + +sub handler { + my $r = shift; + state $urlbase = Bugzilla->localconfig->{urlbase}; + state $urlbase_uri = URI->new($urlbase); + state $urlbase_host = $urlbase_uri->host; + state $urlbase_host_regex = qr/^bug(\d+)\.\Q$urlbase_host\E$/; + state $attachment_base = Bugzilla->localconfig->{attachment_base}; + state $attachment_root = _attachment_root($attachment_base); + state $attachment_host_regex = _attachment_host_regex($attachment_base); + + my $hostname = $r->hostname; + return OK if $hostname eq $urlbase_host; + + my $path = $r->uri; + return OK if $path eq '/__lbheartbeat__'; + + if ($attachment_base && $hostname eq $attachment_root) { + $r->headers_out->set(Location => $urlbase); + return REDIRECT; + } + elsif ($attachment_base && $hostname =~ $attachment_host_regex) { + if ($path =~ m{^/attachment\.cgi}s) { + return OK; + } else { + my $new_uri = URI->new($r->unparsed_uri); + $new_uri->scheme($urlbase_uri->scheme); + $new_uri->host($urlbase_host); + $r->headers_out->set(Location => $new_uri); + return REDIRECT; + } + } + elsif (my ($id) = $hostname =~ $urlbase_host_regex) { + my $new_uri = $urlbase_uri->clone; + $new_uri->path('/show_bug.cgi'); + $new_uri->query_form(id => $id); + $r->headers_out->set(Location => $new_uri); + return REDIRECT; + } + else { + $r->headers_out->set(Location => $urlbase); + return REDIRECT; + } +} + +1;
\ No newline at end of file diff --git a/Bugzilla/WebService/Server/REST.pm b/Bugzilla/WebService/Server/REST.pm index 6fb86fdd4..b8884b753 100644 --- a/Bugzilla/WebService/Server/REST.pm +++ b/Bugzilla/WebService/Server/REST.pm @@ -132,7 +132,8 @@ sub response { if (exists $json_data->{error}) { $result = $json_data->{error}; $result->{error} = $self->type('boolean', 1); - $result->{documentation} = REST_DOC; + + $result->{documentation} = Bugzilla->params->{docs_urlbase} . "api/"; delete $result->{'name'}; # Remove JSONRPCError } elsif (exists $json_data->{result}) { |