summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan William Hardison <dylan@hardison.net>2018-04-04 05:05:04 +0200
committerDylan William Hardison <dylan@hardison.net>2018-07-31 18:57:16 +0200
commit6df945da5900da86203e0527816690cb1d52c574 (patch)
tree2bd1fe5aa1aac5f239c32328eece0e3af400feba
parent8b75f8e691309ec68e5de1cbdf77f6e8b2b305f8 (diff)
downloadbugzilla-6df945da5900da86203e0527816690cb1d52c574.tar.gz
bugzilla-6df945da5900da86203e0527816690cb1d52c574.tar.xz
Bug 1455495 - Replace apache with Mojolicious
-rw-r--r--Bugzilla.pm2
-rw-r--r--Bugzilla/Attachment/PatchReader.pm15
-rw-r--r--Bugzilla/CGI.pm32
-rw-r--r--Bugzilla/DaemonControl.pm26
-rw-r--r--Bugzilla/Error.pm4
-rw-r--r--Bugzilla/Install/Filesystem.pm127
-rw-r--r--Bugzilla/ModPerl.pm118
-rw-r--r--Bugzilla/ModPerl/BasicAuth.pm65
-rw-r--r--Bugzilla/ModPerl/BlockIP.pm65
-rw-r--r--Bugzilla/ModPerl/StartupFix.pm51
-rw-r--r--Bugzilla/Quantum.pm214
-rw-r--r--Bugzilla/Quantum/CGI.pm162
-rw-r--r--Bugzilla/Quantum/Plugin/BasicAuth.pm40
-rw-r--r--Bugzilla/Quantum/Plugin/BlockIP.pm43
-rw-r--r--Bugzilla/Quantum/Plugin/Glue.pm114
-rw-r--r--Bugzilla/Quantum/Plugin/Hostage.pm (renamed from Bugzilla/ModPerl/Hostage.pm)51
-rw-r--r--[-rwxr-xr-x]Bugzilla/Quantum/SES.pm (renamed from ses/index.cgi)89
-rw-r--r--Bugzilla/Quantum/Static.pm30
-rw-r--r--Bugzilla/Quantum/Stdout.pm59
-rw-r--r--Bugzilla/Quantum/Template.pm39
-rw-r--r--Bugzilla/Template.pm1
-rw-r--r--Bugzilla/WebService/Server/XMLRPC.pm6
-rw-r--r--Bugzilla/WebService/Util.pm8
-rw-r--r--Dockerfile9
-rw-r--r--Log/Log4perl/Layout/Mozilla.pm3
-rwxr-xr-xMakefile.PL15
-rw-r--r--README.rst35
-rwxr-xr-xbuglist.cgi26
-rwxr-xr-xbugzilla.pl20
-rwxr-xr-xchecksetup.pl3
-rwxr-xr-xcolchange.cgi16
-rw-r--r--conf/log4perl-test.conf4
-rw-r--r--docker-compose.yml1
-rwxr-xr-xheartbeat.cgi10
-rwxr-xr-x[-rw-r--r--]jobqueue-worker.pl0
-rw-r--r--qa/t/lib/QA/Util.pm28
-rw-r--r--qa/t/test_bug_edit.t117
-rw-r--r--qa/t/test_shutdown.t72
-rwxr-xr-xscripts/block-ip.pl10
-rwxr-xr-xscripts/entrypoint.pl1
-rwxr-xr-x[-rw-r--r--]scripts/undo.pl0
-rw-r--r--t/001compile.t14
-rw-r--r--t/002goodperl.t7
-rw-r--r--template/en/default/global/header.html.tmpl2
-rw-r--r--vagrant_support/apache.yml8
-rwxr-xr-xvagrant_support/hypnotoad122
-rw-r--r--vagrant_support/hypnotoad.yml27
-rw-r--r--vagrant_support/playbook.yml6
-rw-r--r--vagrant_support/update.yml5
49 files changed, 1136 insertions, 786 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm
index 73d080395..4795a3f3a 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -801,7 +801,7 @@ sub check_rate_limit {
my $limit = join("/", @$limit);
Bugzilla->audit("[rate_limit] action=$action, ip=$ip, limit=$limit, name=$name");
if ($action eq 'block') {
- Bugzilla::ModPerl::BlockIP->block_ip($ip);
+ $Bugzilla::Quantum::CGI::C->block_ip($ip);
ThrowUserError("rate_limit");
}
}
diff --git a/Bugzilla/Attachment/PatchReader.pm b/Bugzilla/Attachment/PatchReader.pm
index 2cfbf2c6b..8025f5b82 100644
--- a/Bugzilla/Attachment/PatchReader.pm
+++ b/Bugzilla/Attachment/PatchReader.pm
@@ -116,18 +116,9 @@ sub process_interdiff {
$ENV{'PATH'} = $lc->{diffpath};
my ($pid, $interdiff_stdout, $interdiff_stderr);
- if ($ENV{MOD_PERL}) {
- require Apache2::RequestUtil;
- require Apache2::SubProcess;
- my $request = Apache2::RequestUtil->request;
- (undef, $interdiff_stdout, $interdiff_stderr) = $request->spawn_proc_prog(
- $lc->{interdiffbin}, [$old_filename, $new_filename]
- );
- } else {
- $interdiff_stderr = gensym;
- my $pid = open3(gensym, $interdiff_stdout, $interdiff_stderr,
- $lc->{interdiffbin}, $old_filename, $new_filename);
- }
+ $interdiff_stderr = gensym;
+ $pid = open3(gensym, $interdiff_stdout, $interdiff_stderr,
+ $lc->{interdiffbin}, $old_filename, $new_filename);
binmode $interdiff_stdout;
# Check for errors
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm
index dbcb3ef68..01d610db1 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -123,7 +123,7 @@ sub new {
# Under mod_perl, CGI's global variables get reset on each request,
# so we need to set them up again every time.
- $class->_init_bz_cgi_globals() if $ENV{MOD_PERL};
+ $class->_init_bz_cgi_globals();
my $self = $class->SUPER::new(@args);
@@ -481,11 +481,6 @@ sub _prevent_unsafe_response {
print $self->SUPER::header(-type => 'text/html', -status => '403 Forbidden');
if ($content_type ne 'text/html') {
print "Untrusted Referer Header\n";
- if ($ENV{MOD_PERL}) {
- my $r = $self->r;
- $r->rflush;
- $r->status(200);
- }
}
exit;
}
@@ -603,8 +598,25 @@ sub header {
$headers{'-link'} .= ', <https://www.google-analytics.com>; rel="preconnect"; crossorigin';
}
}
-
- return $self->SUPER::header(%headers) || "";
+ my $headers = $self->SUPER::header(%headers) || '';
+ if ($self->server_software eq 'Bugzilla::Quantum::CGI') {
+ my $c = $Bugzilla::Quantum::CGI::C;
+ $c->res->headers->parse($headers);
+ my $status = $c->res->headers->status;
+ if ($status && $status =~ /^([0-9]+)/) {
+ $c->res->code($1);
+ }
+ elsif ($c->res->headers->location) {
+ $c->res->code(302);
+ }
+ else {
+ $c->res->code(200);
+ }
+ return '';
+ }
+ else {
+ LOGDIE("Bugzilla::CGI->header() should only be called from inside Bugzilla::Quantum::CGI!");
+ }
}
sub param {
@@ -721,6 +733,7 @@ sub redirect {
return $self->SUPER::redirect(@_);
}
+use Bugzilla::Logging;
# This helps implement Bugzilla::Search::Recent, and also shortens search
# URLs that get POSTed to buglist.cgi.
sub redirect_search_url {
@@ -791,9 +804,6 @@ sub redirect_to_https {
# and do not work with 302. Our redirect really is permanent anyhow, so
# it doesn't hurt to make it a 301.
print $self->redirect(-location => $url, -status => 301);
-
- # When using XML-RPC with mod_perl, we need the headers sent immediately.
- $self->r->rflush if $ENV{MOD_PERL};
exit;
}
diff --git a/Bugzilla/DaemonControl.pm b/Bugzilla/DaemonControl.pm
index 6ff883af0..5cb32973f 100644
--- a/Bugzilla/DaemonControl.pm
+++ b/Bugzilla/DaemonControl.pm
@@ -23,7 +23,8 @@ use IO::Async::Protocol::LineStream;
use IO::Async::Signal;
use IO::Socket;
use LWP::Simple qw(get);
-use POSIX qw(setsid WEXITSTATUS);
+use JSON::MaybeXS qw(encode_json);
+use POSIX qw(WEXITSTATUS);
use base qw(Exporter);
@@ -43,8 +44,14 @@ our %EXPORT_TAGS = (
my $BUGZILLA_DIR = bz_locations->{cgi_path};
my $JOBQUEUE_BIN = catfile( $BUGZILLA_DIR, 'jobqueue.pl' );
my $CEREAL_BIN = catfile( $BUGZILLA_DIR, 'scripts', 'cereal.pl' );
-my $HTTPD_BIN = '/usr/sbin/httpd';
-my $HTTPD_CONFIG = catfile( bz_locations->{confdir}, 'httpd.conf' );
+my $BUGZILLA_BIN = catfile( $BUGZILLA_DIR, 'bugzilla.pl' );
+my $HYPNOTOAD_BIN = catfile( $BUGZILLA_DIR, 'local', 'bin', 'hypnotoad' );
+my @PERL5LIB = ( $BUGZILLA_DIR, catdir($BUGZILLA_DIR, 'lib'), catdir($BUGZILLA_DIR, 'local', 'lib', 'perl5') );
+
+my %HTTP_BACKENDS = (
+ hypnotoad => [ $HYPNOTOAD_BIN, $BUGZILLA_BIN, '-f' ],
+ simple => [ $BUGZILLA_BIN, 'daemon' ],
+);
sub catch_signal {
my ($name, @done) = @_;
@@ -98,13 +105,12 @@ sub run_httpd {
my $exit_f = $loop->new_future;
my $httpd = IO::Async::Process->new(
code => sub {
-
- # we have to setsid() to make a new process group
- # or else apache will kill its parent.
- setsid();
- my @command = ( $HTTPD_BIN, '-DFOREGROUND', '-f' => $HTTPD_CONFIG, @args );
- exec @command
- or die "failed to exec $command[0] $!";
+ $ENV{BUGZILLA_HTTPD_ARGS} = encode_json(\@args);
+ $ENV{PERL5LIB} = join(':', @PERL5LIB);
+ my $backend = $ENV{HTTP_BACKEND} // 'hypnotoad';
+ my $command = $HTTP_BACKENDS{ $backend };
+ exec @$command
+ or die "failed to exec $command->[0] $!";
},
on_finish => on_finish($exit_f),
on_exception => on_exception( 'httpd', $exit_f ),
diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm
index 9fcd16386..f932294b0 100644
--- a/Bugzilla/Error.pm
+++ b/Bugzilla/Error.pm
@@ -31,7 +31,7 @@ use Scalar::Util qw(blessed);
sub _in_eval {
my $in_eval = 0;
for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
- last if $sub =~ /^ModPerl/;
+ last if $sub =~ /^Bugzilla::Quantum::CGI::try/;
$in_eval = 1 if $sub =~ /^\(eval\)/;
}
return $in_eval;
@@ -196,7 +196,7 @@ sub ThrowTemplateError {
# mod_perl overrides exit to call die with this string
# we never want to display this to the user
- exit if $template_err =~ /\bModPerl::Util::exit\b/;
+ die $template_err if ref($template_err) eq 'ARRAY' && $template_err->[0] eq "EXIT\n";
state $logger = Log::Log4perl->get_logger('Bugzilla.Error.Template');
$logger->error($template_err);
diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm
index 003be22e4..f520d3d56 100644
--- a/Bugzilla/Install/Filesystem.pm
+++ b/Bugzilla/Install/Filesystem.pm
@@ -41,56 +41,11 @@ use English qw(-no_match_vars $OSNAME);
use base qw(Exporter);
our @EXPORT = qw(
update_filesystem
- create_htaccess
fix_all_file_permissions
fix_dir_permissions
fix_file_permissions
);
-use constant HT_DEFAULT_DENY => <<'EOT';
-# nothing in this directory is retrievable unless overridden by an .htaccess
-# in a subdirectory
-deny from all
-EOT
-
-use constant HT_GRAPHS_DIR => <<'EOT';
-# Allow access to .png and .gif files.
-<FilesMatch (\.gif|\.png)$>
- Allow from all
-</FilesMatch>
-
-# And no directory listings, either.
-Deny from all
-EOT
-
-use constant HT_WEBDOT_DIR => <<'EOT';
-# Restrict access to .dot files to the public webdot server at research.att.com
-# if research.att.com ever changes their IP, or if you use a different
-# webdot server, you'll need to edit this
-<FilesMatch \.dot$>
- Allow from 192.20.225.0/24
- Deny from all
-</FilesMatch>
-
-# Allow access to .png files created by a local copy of 'dot'
-<FilesMatch \.png\$>
- Allow from all
-</FilesMatch>
-
-# And no directory listings, either.
-Deny from all
-EOT
-
-use constant HT_ASSETS_DIR => <<'EOT';
-# Allow access to .css and js files
-<FilesMatch \.(css|js)$>
- Allow from all
-</FilesMatch>
-
-# And no directory listings, either.
-Deny from all
-EOT
-
use constant INDEX_HTML => <<'EOT';
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
@@ -230,13 +185,13 @@ sub FILESYSTEM {
'jobqueue-worker.pl' => { perms => OWNER_EXECUTE },
'clean-bug-user-last-visit.pl' => { perms => WS_EXECUTE },
+ 'bugzilla.pl' => { perms => OWNER_EXECUTE },
'Bugzilla.pm' => { perms => CGI_READ },
"$localconfig*" => { perms => CGI_READ },
'META.*' => { perms => CGI_READ },
'MYMETA.*' => { perms => CGI_READ },
'bugzilla.dtd' => { perms => WS_SERVE },
'mod_perl.pl' => { perms => WS_SERVE },
- '.htaccess' => { perms => WS_SERVE },
'cvs-update.log' => { perms => WS_SERVE },
'scripts/sendunsentbugmail.pl' => { perms => WS_EXECUTE },
'docs/bugzilla.ent' => { perms => OWNER_WRITE },
@@ -438,54 +393,15 @@ sub FILESYSTEM {
'index.html' => { perms => WS_SERVE, contents => INDEX_HTML }
);
- # Because checksetup controls the .htaccess creation separately
- # by a localconfig variable, these go in a separate variable from
- # %create_files.
- #
- # Note that these get WS_SERVE as their permission
- # because they're *read* by the webserver, even though they're not
- # actually, themselves, served.
- my %htaccess = (
- "$attachdir/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$libdir/Bugzilla/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$extlib/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$templatedir/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- 'contrib/.htaccess' => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- 'scripts/.htaccess' => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- 't/.htaccess' => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- 'xt/.htaccess' => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- '.circleci/.htaccess' => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$confdir/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$datadir/.htaccess" => { perms => WS_SERVE,
- contents => HT_DEFAULT_DENY },
- "$graphsdir/.htaccess" => { perms => WS_SERVE,
- contents => HT_GRAPHS_DIR },
- "$webdotdir/.htaccess" => { perms => WS_SERVE,
- contents => HT_WEBDOT_DIR },
- "$assetsdir/.htaccess" => { perms => WS_SERVE,
- contents => HT_ASSETS_DIR },
- );
-
Bugzilla::Hook::process('install_filesystem', {
files => \%files,
create_dirs => \%create_dirs,
non_recurse_dirs => \%non_recurse_dirs,
recurse_dirs => \%recurse_dirs,
create_files => \%create_files,
- htaccess => \%htaccess,
});
- my %all_files = (%create_files, %htaccess, %index_html, %files);
+ my %all_files = (%create_files, %index_html, %files);
my %all_dirs = (%create_dirs, %non_recurse_dirs);
return {
@@ -494,7 +410,6 @@ sub FILESYSTEM {
all_dirs => \%all_dirs,
create_files => \%create_files,
- htaccess => \%htaccess,
index_html => \%index_html,
all_files => \%all_files,
};
@@ -542,13 +457,6 @@ sub update_filesystem {
_rename_file($oldparamsfile, "$datadir/$oldparamsfile");
}
- # Remove old assets htaccess file to force recreation with correct values.
- if (-e "$assetsdir/.htaccess") {
- if (read_file("$assetsdir/.htaccess") =~ /<FilesMatch \\\.css\$>/) {
- unlink("$assetsdir/.htaccess");
- }
- }
-
_create_files(%files);
if ($params->{index_html}) {
_create_files(%{$fs->{index_html}});
@@ -653,27 +561,6 @@ sub _convert_single_file_skins {
}
}
-sub create_htaccess {
- _create_files(%{FILESYSTEM()->{htaccess}});
-
- # Repair old .htaccess files
-
- my $webdot_dir = bz_locations()->{'webdotdir'};
- # The public webdot IP address changed.
- my $webdot = new IO::File("$webdot_dir/.htaccess", 'r')
- || die "$webdot_dir/.htaccess: $!";
- my $webdot_data;
- { local $/; $webdot_data = <$webdot>; }
- $webdot->close;
- if ($webdot_data =~ /192\.20\.225\.10/) {
- print "Repairing $webdot_dir/.htaccess...\n";
- $webdot_data =~ s/192\.20\.225\.10/192.20.225.0\/24/g;
- $webdot = new IO::File("$webdot_dir/.htaccess", 'w') || die $!;
- print $webdot $webdot_data;
- $webdot->close;
- }
-}
-
sub _rename_file {
my ($from, $to) = @_;
print install_string('file_rename', { from => $from, to => $to }), "\n";
@@ -984,16 +871,6 @@ Params: C<index_html> - Whether or not we should create
Returns: nothing
-=item C<create_htaccess()>
-
-Description: Creates all of the .htaccess files for Apache,
- in the various Bugzilla directories. Also updates
- the .htaccess files if they need updating.
-
-Params: none
-
-Returns: nothing
-
=item C<fix_all_file_permissions($output)>
Description: Sets all the file permissions on all of Bugzilla's files
diff --git a/Bugzilla/ModPerl.pm b/Bugzilla/ModPerl.pm
deleted file mode 100644
index 19cd1128f..000000000
--- a/Bugzilla/ModPerl.pm
+++ /dev/null
@@ -1,118 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# This Source Code Form is "Incompatible With Secondary Licenses", as
-# defined by the Mozilla Public License, v. 2.0.
-package Bugzilla::ModPerl;
-
-use 5.10.1;
-use strict;
-use warnings;
-
-use File::Find ();
-use Cwd ();
-use Carp ();
-
-# We don't need (or want) to use Bugzilla's template subclass.
-# it is easier to reason with the code without all the extra things Bugzilla::Template adds
-# (and there might be side-effects, since this code is loaded very early in the httpd startup)
-use Template ();
-
-use Bugzilla::ModPerl::BlockIP;
-use Bugzilla::ModPerl::Hostage;
-
-sub apache_config {
- my ($class, $cgi_path) = @_;
-
- Carp::croak "\$cgi_path is required" unless $cgi_path;
-
- my %htaccess;
- $cgi_path = Cwd::realpath($cgi_path);
- my $wanted = sub {
- package File::Find;
- our ($name, $dir);
-
- if ($name =~ m#/\.htaccess$#) {
- open my $fh, '<', $name or die "cannot open $name $!";
- my $contents = do {
- local $/ = undef;
- <$fh>;
- };
- close $fh;
- $htaccess{$dir} = { file => $name, contents => $contents, dir => $dir };
- }
- };
-
- File::Find::find( { wanted => $wanted, no_chdir => 1 }, $cgi_path );
- my $template = Template->new;
- my $conf;
- my %vars = (
- root_htaccess => delete $htaccess{$cgi_path},
- htaccess_files => [ map { $htaccess{$_} } sort { length $a <=> length $b } keys %htaccess ],
- cgi_path => $cgi_path,
- );
- $template->process(\*DATA, \%vars, \$conf);
- my $apache_version = Apache2::ServerUtil::get_server_version();
- if ($apache_version =~ m!Apache/(\d+)\.(\d+)\.(\d+)!) {
- my ($major, $minor, $patch) = ($1, $2, $3);
- if ($major > 2 || $major == 2 && $minor >= 4) {
- $conf =~ s{^\s+deny\s+from\s+all.*$}{Require all denied}gmi;
- $conf =~ s{^\s+allow\s+from\s+all.*$}{Require all granted}gmi;
- $conf =~ s{^\s+allow\s+from\s+(\S+).*$}{Require host $1}gmi;
- }
- }
-
- return $conf;
-}
-
-1;
-
-__DATA__
-# Make sure each httpd child receives a different random seed (bug 476622).
-# Bugzilla::RNG has one srand that needs to be called for
-# every process, and Perl has another. (Various Perl modules still use
-# 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(); eval { Bugzilla->dbh->ping } }"
-PerlInitHandler Bugzilla::ModPerl::Hostage
-PerlAccessHandler Bugzilla::ModPerl::BlockIP
-
-# It is important to specify ErrorDocuments outside of all directories.
-# These used to be in .htaccess, but then things like "AllowEncodedSlashes no"
-# mean that urls containing %2f are unstyled.
-ErrorDocument 401 /errors/401.html
-ErrorDocument 403 /errors/403.html
-ErrorDocument 404 /errors/404.html
-ErrorDocument 500 /errors/500.html
-
-<Directory "[% cgi_path %]">
- AddHandler perl-script .cgi
- # No need to PerlModule these because they're already defined in mod_perl.pl
- PerlResponseHandler Bugzilla::ModPerl::ResponseHandler
- PerlCleanupHandler Bugzilla::ModPerl::CleanupHandler Apache2::SizeLimit
- PerlOptions +ParseHeaders
- Options +ExecCGI +FollowSymLinks
- DirectoryIndex index.cgi index.html
- AllowOverride none
- # from [% root_htaccess.file %]
- [% root_htaccess.contents FILTER indent %]
-</Directory>
-
-# AWS SES endpoint for handling mail bounces/complaints
-<Location "/ses">
- PerlSetEnv AUTH_VAR_NAME ses_username
- PerlSetEnv AUTH_VAR_PASS ses_password
- PerlAuthenHandler Bugzilla::ModPerl::BasicAuth
- AuthName SES
- AuthType Basic
- require valid-user
-</Location>
-
-# directory rules for all the other places we have .htaccess files
-[% FOREACH htaccess IN htaccess_files %]
-# from [% htaccess.file %]
-<Directory "[% htaccess.dir %]">
- [% htaccess.contents FILTER indent %]
-</Directory>
-[% END %]
diff --git a/Bugzilla/ModPerl/BasicAuth.pm b/Bugzilla/ModPerl/BasicAuth.pm
deleted file mode 100644
index 7248a19f3..000000000
--- a/Bugzilla/ModPerl/BasicAuth.pm
+++ /dev/null
@@ -1,65 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# This Source Code Form is "Incompatible With Secondary Licenses", as
-# defined by the Mozilla Public License, v. 2.0.
-package Bugzilla::ModPerl::BasicAuth;
-use 5.10.1;
-use strict;
-use warnings;
-
-# Protects a mod_perl <Location> with Basic HTTP authentication.
-#
-# Example use:
-#
-# <Location "/ses">
-# PerlAuthenHandler Bugzilla::ModPerl::BasicAuth
-# PerlSetEnv AUTH_VAR_NAME ses_username
-# PerlSetEnv AUTH_VAR_PASS ses_password
-# AuthName SES
-# AuthType Basic
-# require valid-user
-# </Location>
-#
-# 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); ## no critic (Freenode::ModPerl)
-use Bugzilla::Logging;
-use Bugzilla ();
-
-sub handler {
- my $r = shift;
- my ($status, $password) = $r->get_basic_auth_pw;
- 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) {
- ERROR('AUTH_VAR_NAME and AUTH_VAR_PASS environmental vars not set');
- $r->note_basic_auth_failure;
- return Apache2::Const::HTTP_UNAUTHORIZED;
- }
-
- my $auth_user = Bugzilla->localconfig->{$auth_var_name};
- my $auth_pass = Bugzilla->localconfig->{$auth_var_pass};
- unless ($auth_user && $auth_pass) {
- 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;
- }
-
- return Apache2::Const::OK;
-}
-
-1;
diff --git a/Bugzilla/ModPerl/BlockIP.pm b/Bugzilla/ModPerl/BlockIP.pm
deleted file mode 100644
index 4e9a4be5c..000000000
--- a/Bugzilla/ModPerl/BlockIP.pm
+++ /dev/null
@@ -1,65 +0,0 @@
-package Bugzilla::ModPerl::BlockIP;
-use 5.10.1;
-use strict;
-use warnings;
-
-use Apache2::RequestRec ();
-use Apache2::Connection ();
-
-use Apache2::Const -compile => qw(OK);
-use Cache::Memcached::Fast;
-
-use constant BLOCK_TIMEOUT => 60*60;
-
-my $MEMCACHED = Bugzilla::Memcached->_new()->{memcached};
-my $STATIC_URI = qr{
- ^/
- (?: extensions/[^/]+/web
- | robots\.txt
- | __heartbeat__
- | __lbheartbeat__
- | __version__
- | images
- | skins
- | js
- | errors
- )
-}xms;
-
-sub block_ip {
- my ($class, $ip) = @_;
- $MEMCACHED->set("block_ip:$ip" => 1, BLOCK_TIMEOUT) if $MEMCACHED;
-}
-
-sub unblock_ip {
- my ($class, $ip) = @_;
- $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED;
-}
-
-sub handler {
- my $r = shift;
- return Apache2::Const::OK if $r->uri =~ $STATIC_URI;
-
- my $ip = $r->headers_in->{'X-Forwarded-For'};
- if ($ip) {
- $ip = (split(/\s*,\s*/ms, $ip))[-1];
- }
- else {
- $ip = $r->connection->remote_ip;
- }
-
- if ($MEMCACHED && $MEMCACHED->get("block_ip:$ip")) {
- __PACKAGE__->block_ip($ip);
- $r->status_line("429 Too Many Requests");
- # 500 is used here because apache 2.2 doesn't understand 429.
- # the above line and the return value together mean we produce 429.
- # Any other variation doesn't work.
- $r->custom_response(500, "Too Many Requests");
- return 429;
- }
- else {
- return Apache2::Const::OK;
- }
-}
-
-1;
diff --git a/Bugzilla/ModPerl/StartupFix.pm b/Bugzilla/ModPerl/StartupFix.pm
deleted file mode 100644
index bcc467e9f..000000000
--- a/Bugzilla/ModPerl/StartupFix.pm
+++ /dev/null
@@ -1,51 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# This Source Code Form is "Incompatible With Secondary Licenses", as
-# defined by the Mozilla Public License, v. 2.0.
-package Bugzilla::ModPerl::StartupFix;
-use 5.10.1;
-use strict;
-use warnings;
-
-use Filter::Util::Call;
-use Apache2::ServerUtil ();
-
-# This module is a source filter that removes every subsequent line
-# if this is the first time apache has started,
-# as reported by Apache2::ServerUtil::restart_count(), which is 1
-# on the first start.
-
-my $FIRST_STARTUP = <<'CODE';
-warn "Bugzilla::ModPerl::StartupFix: Skipping first startup using source filter\n";
-1;
-CODE
-
-sub import {
- my ($class) = @_;
- my ($ref) = {};
- filter_add( bless $ref, $class );
-}
-
-# this will be called for each line.
-# For the first line replaced, we insert $FIRST_STARTUP.
-# Every subsequent line is replaced with an empty string.
-sub filter {
- my ($self) = @_;
- my ($status);
- if ($status = filter_read() > 0) {
- if (Apache2::ServerUtil::restart_count() < 2) {
- if (!$self->{did_it}) {
- $self->{did_it} = 1;
- $_ = $FIRST_STARTUP;
- }
- else {
- $_ = "";
- }
- }
- }
- return $status;
-}
-
-1; \ No newline at end of file
diff --git a/Bugzilla/Quantum.pm b/Bugzilla/Quantum.pm
new file mode 100644
index 000000000..e4c75726c
--- /dev/null
+++ b/Bugzilla/Quantum.pm
@@ -0,0 +1,214 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum;
+use Mojo::Base 'Mojolicious';
+
+use CGI::Compile; # Needed for its exit() overload
+use Bugzilla::Logging;
+use Bugzilla::Quantum::Template;
+use Bugzilla::Quantum::CGI;
+use Bugzilla::Quantum::SES;
+use Bugzilla::Quantum::Static;
+
+use Bugzilla ();
+use Bugzilla::Constants qw(bz_locations);
+use Bugzilla::BugMail ();
+use Bugzilla::CGI ();
+use Bugzilla::Extension ();
+use Bugzilla::Install::Requirements ();
+use Bugzilla::Util ();
+use Cwd qw(realpath);
+
+use MojoX::Log::Log4perl::Tiny;
+
+has 'static' => sub { Bugzilla::Quantum::Static->new };
+
+sub startup {
+ my ($self) = @_;
+
+ DEBUG("Starting up");
+ $self->plugin('Bugzilla::Quantum::Plugin::Glue');
+ $self->plugin('Bugzilla::Quantum::Plugin::Hostage');
+ $self->plugin('Bugzilla::Quantum::Plugin::BlockIP');
+ $self->plugin('Bugzilla::Quantum::Plugin::BasicAuth');
+
+ if ( $self->mode ne 'development' ) {
+ $self->hook(
+ after_static => sub {
+ my ($c) = @_;
+ $c->res->headers->cache_control('public, max-age=31536000');
+ }
+ );
+ }
+
+ my $r = $self->routes;
+ Bugzilla::Quantum::CGI->load_all($r);
+ Bugzilla::Quantum::CGI->load_one('bzapi_cgi', 'extensions/BzAPI/bin/rest.cgi');
+
+ $r->any('/')->to('CGI#index_cgi');
+ $r->any('/rest')->to('CGI#rest_cgi');
+ $r->any('/rest.cgi/*PATH_INFP')->to('CGI#rest_cgi' => { PATH_INFO => '' });
+ $r->any('/rest/*PATH_INFO')->to( 'CGI#rest_cgi' => { PATH_INFO => '' });
+ $r->any('/bug/:id')->to('CGI#show_bug_cgi');
+ $r->any('/extensions/BzAPI/bin/rest.cgi/*PATH_INFO')->to('CGI#bzapi_cgi');
+
+ $r->get(
+ '/__lbheartbeat__' => sub {
+ my $c = shift;
+ $c->reply->file( $c->app->home->child('__lbheartbeat__') );
+ },
+ );
+
+ $r->get('/__heartbeat__')->to( 'CGI#heartbeat_cgi');
+ $r->get('/robots.txt')->to( 'CGI#robots_cgi' );
+
+ $r->any('/review')->to( 'CGI#page_cgi' => {'id' => 'splinter.html'});
+ $r->any('/user_profile')->to( 'CGI#page_cgi' => {'id' => 'user_profile.html'});
+ $r->any('/userprofile')->to( 'CGI#page_cgi' => {'id' => 'user_profile.html'});
+ $r->any('/request_defer')->to( 'CGI#page_cgi' => {'id' => 'request_defer.html'});
+ $r->any('/login')->to( 'CGI#index_cgi' => { 'GoAheadAndLogIn' => '1' });
+
+ $r->any('/:new_bug' => [new_bug => qr{new[-_]bug}])->to( 'CGI#new_bug_cgi');
+
+ my $ses_auth = $r->under(
+ '/ses' => sub {
+ my ($c) = @_;
+ my $lc = Bugzilla->localconfig;
+
+ return $c->basic_auth( 'SES', $lc->{ses_username}, $lc->{ses_password} );
+ }
+ );
+ $ses_auth->any('/index.cgi')->to('SES#main');
+
+ $r->any('/:REWRITE_itrequest' => [REWRITE_itrequest => qr{form[\.:]itrequest}])->to(
+ 'CGI#enter_bug_cgi' => { 'product' => 'Infrastructure & Operations', 'format' => 'itrequest' }
+ );
+ $r->any('/:REWRITE_mozlist' => [REWRITE_mozlist => qr{form[\.:]mozlist}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'mozlist'}
+ );
+ $r->any('/:REWRITE_poweredby' => [REWRITE_poweredby => qr{form[\.:]poweredby}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'poweredby'}
+ );
+ $r->any('/:REWRITE_presentation' => [REWRITE_presentation => qr{form[\.:]presentation}])->to(
+ 'cgi#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'presentation'}
+ );
+ $r->any('/:REWRITE_trademark' => [REWRITE_trademark => qr{form[\.:]trademark}])->to(
+ 'cgi#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'trademark'}
+ );
+ $r->any('/:REWRITE_recoverykey' => [REWRITE_recoverykey => qr{form[\.:]recoverykey}])->to(
+ 'cgi#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'recoverykey'}
+ );
+ $r->any('/:REWRITE_legal' => [REWRITE_legal => qr{form[\.:]legal}])->to(
+ 'CGI#enter_bug_cgi' => { 'product' => 'Legal', 'format' => 'legal' },
+ );
+ $r->any('/:REWRITE_recruiting' => [REWRITE_recruiting => qr{form[\.:]recruiting}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Recruiting', 'format' => 'recruiting'}
+ );
+ $r->any('/:REWRITE_intern' => [REWRITE_intern => qr{form[\.:]intern}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Recruiting', 'format' => 'intern'}
+ );
+ $r->any('/:REWRITE_mozpr' => [REWRITE_mozpr => qr{form[\.:]mozpr}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Mozilla PR', 'format' => 'mozpr' },
+ );
+ $r->any('/:REWRITE_reps_mentorship' => [REWRITE_reps_mentorship => qr{form[\.:]reps[\.:]mentorship}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Mozilla Reps','format' => 'mozreps' },
+ );
+ $r->any('/:REWRITE_reps_budget' => [REWRITE_reps_budget => qr{form[\.:]reps[\.:]budget}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Mozilla Reps','format' => 'remo-budget'}
+ );
+ $r->any('/:REWRITE_reps_swag' => [REWRITE_reps_swag => qr{form[\.:]reps[\.:]swag}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Mozilla Reps','format' => 'remo-swag'}
+ );
+ $r->any('/:REWRITE_reps_it' => [REWRITE_reps_it => qr{form[\.:]reps[\.:]it}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Mozilla Reps','format' => 'remo-it'}
+ );
+ $r->any('/:REWRITE_reps_payment' => [REWRITE_reps_payment => qr{form[\.:]reps[\.:]payment}])->to(
+ 'CGI#page_cgi' => {'id' => 'remo-form-payment.html'}
+ );
+ $r->any('/:REWRITE_csa_discourse' => [REWRITE_csa_discourse => qr{form[\.:]csa[\.:]discourse}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Infrastructure & Operations', 'format' => 'csa-discourse'}
+ );
+ $r->any('/:REWRITE_employee_incident' => [REWRITE_employee_incident => qr{form[\.:]employee[\.\-:]incident}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'mozilla.org', 'format' => 'employee-incident'}
+ );
+ $r->any('/:REWRITE_brownbag' => [REWRITE_brownbag => qr{form[\.:]brownbag}])->to(
+ 'CGI#https_air_mozilla_org_requests' => {}
+ );
+ $r->any('/:REWRITE_finance' => [REWRITE_finance => qr{form[\.:]finance}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Finance','format' => 'finance'}
+ );
+ $r->any('/:REWRITE_moz_project_review' => [REWRITE_moz_project_review => qr{form[\.:]moz[\.\-:]project[\.\-:]review}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'mozilla.org','format' => 'moz-project-review'}
+ );
+ $r->any('/:REWRITE_docs' => [REWRITE_docs => qr{form[\.:]docs?}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Developer Documentation','format' => 'doc'}
+ );
+ $r->any('/:REWRITE_mdn' => [REWRITE_mdn => qr{form[\.:]mdn?}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'mdn','product' => 'developer.mozilla.org'}
+ );
+ $r->any('/:REWRITE_swag_gear' => [REWRITE_swag_gear => qr{form[\.:](swag|gear)}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'swag','product' => 'Marketing'}
+ );
+ $r->any('/:REWRITE_costume' => [REWRITE_costume => qr{form[\.:]costume}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Marketing','format' => 'costume'}
+ );
+ $r->any('/:REWRITE_ipp' => [REWRITE_ipp => qr{form[\.:]ipp}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Internet Public Policy','format' => 'ipp'}
+ );
+ $r->any('/:REWRITE_creative' => [REWRITE_creative => qr{form[\.:]creative}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'creative','product' => 'Marketing'}
+ );
+ $r->any('/:REWRITE_user_engagement' => [REWRITE_user_engagement => qr{form[\.:]user[\.\-:]engagement}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'user-engagement','product' => 'Marketing'}
+ );
+ $r->any('/:REWRITE_dev_engagement_event' => [REWRITE_dev_engagement_event => qr{form[\.:]dev[\.\-:]engagement[\.\-\:]event}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Developer Engagement','format' => 'dev-engagement-event'}
+ );
+ $r->any('/:REWRITE_mobile_compat' => [REWRITE_mobile_compat => qr{form[\.:]mobile[\.\-:]compat}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Tech Evangelism','format' => 'mobile-compat'}
+ );
+ $r->any('/:REWRITE_web_bounty' => [REWRITE_web_bounty => qr{form[\.:]web[\.:]bounty}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'web-bounty','product' => 'mozilla.org'}
+ );
+ $r->any('/:REWRITE_automative' => [REWRITE_automative => qr{form[\.:]automative}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Testing','format' => 'automative'}
+ );
+ $r->any('/:REWRITE_comm_newsletter' => [REWRITE_comm_newsletter => qr{form[\.:]comm[\.:]newsletter}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'comm-newsletter','product' => 'Marketing'}
+ );
+ $r->any('/:REWRITE_screen_share_whitelist' => [REWRITE_screen_share_whitelist => qr{form[\.:]screen[\.:]share[\.:]whitelist}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'screen-share-whitelist','product' => 'Firefox'}
+ );
+ $r->any('/:REWRITE_data_compliance' => [REWRITE_data_compliance => qr{form[\.:]data[\.\-:]compliance}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Data Compliance','format' => 'data-compliance'}
+ );
+ $r->any('/:REWRITE_fsa_budget' => [REWRITE_fsa_budget => qr{form[\.:]fsa[\.:]budget}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'FSA','format' => 'fsa-budget'}
+ );
+ $r->any('/:REWRITE_triage_request' => [REWRITE_triage_request => qr{form[\.:]triage[\.\-]request}])->to(
+ 'CGI#page_cgi' => {'id' => 'triage_request.html'}
+ );
+ $r->any('/:REWRITE_crm_CRM' => [REWRITE_crm_CRM => qr{form[\.:](crm|CRM)}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'crm','product' => 'Marketing'}
+ );
+ $r->any('/:REWRITE_nda' => [REWRITE_nda => qr{form[\.:]nda}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Legal','format' => 'nda'}
+ );
+ $r->any('/:REWRITE_name_clearance' => [REWRITE_name_clearance => qr{form[\.:]name[\.:]clearance}])->to(
+ 'CGI#enter_bug_cgi' => {'format' => 'name-clearance','product' => 'Legal'}
+ );
+ $r->any('/:REWRITE_shield_studies' => [REWRITE_shield_studies => qr{form[\.:]shield[\.:]studies}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Shield','format' => 'shield-studies'}
+ );
+ $r->any('/:REWRITE_client_bounty' => [REWRITE_client_bounty => qr{form[\.:]client[\.:]bounty}])->to(
+ 'CGI#enter_bug_cgi' => {'product' => 'Firefox','format' => 'client-bounty'}
+ );
+
+}
+
+1;
diff --git a/Bugzilla/Quantum/CGI.pm b/Bugzilla/Quantum/CGI.pm
new file mode 100644
index 000000000..85f14cf83
--- /dev/null
+++ b/Bugzilla/Quantum/CGI.pm
@@ -0,0 +1,162 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum::CGI;
+use Mojo::Base 'Mojolicious::Controller';
+
+use CGI::Compile;
+use Bugzilla::Constants qw(bz_locations);
+use Bugzilla::Quantum::Stdout;
+use File::Slurper qw(read_text);
+use File::Spec::Functions qw(catfile);
+use Sub::Name;
+use Sub::Quote 2.005000;
+use Try::Tiny;
+use Taint::Util qw(untaint);
+use Socket qw(AF_INET inet_aton);
+use Sys::Hostname;
+use English qw(-no_match_vars);
+
+our $C;
+my %SEEN;
+
+sub load_all {
+ my ($class, $r) = @_;
+
+ foreach my $file (glob '*.cgi') {
+ my $name = _file_to_method($file);
+ $class->load_one($name, $file);
+ $r->any("/$file")->to("CGI#$name");
+ }
+}
+
+sub load_one {
+ my ($class, $name, $file) = @_;
+ my $package = __PACKAGE__ . "::$name",
+ my $inner_name = "_$name";
+ my $content = read_text( catfile( bz_locations->{cgi_path}, $file ) );
+ $content = "package $package; $content";
+ untaint($content);
+ my %options = (
+ package => $package,
+ file => $file,
+ line => 1,
+ no_defer => 1,
+ );
+ die "Tried to load $file more than once" if $SEEN{$file}++;
+ my $inner = quote_sub $inner_name, $content, {}, \%options;
+ my $wrapper = sub {
+ my ($c) = @_;
+ my $stdin = $c->_STDIN;
+ my $stdout = '';
+ local $C = $c;
+ local %ENV = $c->_ENV($file);
+ local *STDIN; ## no critic (local)
+ local $CGI::Compile::USE_REAL_EXIT = 0;
+ local $PROGRAM_NAME = $file;
+ open STDIN, '<', $stdin->path or die "STDIN @{[$stdin->path]}: $!" if -s $stdin->path;
+ tie *STDOUT, 'Bugzilla::Quantum::Stdout', controller => $c; ## no critic (tie)
+ try {
+ Bugzilla->init_page();
+ $inner->();
+ }
+ catch {
+ die $_ unless ref $_ eq 'ARRAY' && $_->[0] eq "EXIT\n";
+ }
+ finally {
+ untie *STDOUT;
+ $c->finish;
+ Bugzilla->_cleanup; ## no critic (private)
+ CGI::initialize_globals();
+ };
+ };
+
+ no strict 'refs'; ## no critic (strict)
+ *{$name} = subname($name, $wrapper);
+ return 1;
+}
+
+sub _ENV {
+ my ($c, $script_name) = @_;
+ my $tx = $c->tx;
+ my $req = $tx->req;
+ my $headers = $req->headers;
+ my $content_length = $req->content->is_multipart ? $req->body_size : $headers->content_length;
+ my %env_headers = ( HTTP_COOKIE => '', HTTP_REFERER => '' );
+
+ for my $name ( @{ $headers->names } ) {
+ my $key = uc "http_$name";
+ $key =~ s!\W!_!g;
+ $env_headers{$key} = $headers->header($name);
+ }
+
+ my $remote_user;
+ if ( my $userinfo = $c->req->url->to_abs->userinfo ) {
+ $remote_user = $userinfo =~ /([^:]+)/ ? $1 : '';
+ }
+ elsif ( my $authenticate = $headers->authorization ) {
+ $remote_user = $authenticate =~ /Basic\s+(.*)/ ? b64_decode $1 : '';
+ $remote_user = $remote_user =~ /([^:]+)/ ? $1 : '';
+ }
+ my $path_info = $c->param('PATH_INFO');
+ my %captures = %{ $c->stash->{'mojo.captures'} // {} };
+ foreach my $key (keys %captures) {
+ if ($key eq 'controller' || $key eq 'action' || $key eq 'PATH_INFO' || $key =~ /^REWRITE_/) {
+ delete $captures{$key};
+ }
+ }
+ my $cgi_query = Mojo::Parameters->new(%captures);
+ $cgi_query->append($req->url->query);
+ my $prefix = $c->stash->{bmo_prefix} ? '/bmo/' : '/';
+
+ return (
+ %ENV,
+ CONTENT_LENGTH => $content_length || 0,
+ CONTENT_TYPE => $headers->content_type || '',
+ GATEWAY_INTERFACE => 'CGI/1.1',
+ HTTPS => $req->is_secure ? 'YES' : 'NO',
+ %env_headers,
+ QUERY_STRING => $cgi_query->to_string,
+ PATH_INFO => $path_info ? "/$path_info" : '',
+ REMOTE_ADDR => $tx->original_remote_address,
+ REMOTE_HOST => $tx->original_remote_address,
+ REMOTE_PORT => $tx->remote_port,
+ REMOTE_USER => $remote_user || '',
+ REQUEST_METHOD => $req->method,
+ SCRIPT_NAME => "$prefix$script_name",
+ SERVER_NAME => hostname,
+ SERVER_PORT => $tx->local_port,
+ SERVER_PROTOCOL => $req->is_secure ? 'HTTPS' : 'HTTP', # TODO: Version is missing
+ SERVER_SOFTWARE => __PACKAGE__,
+ );
+}
+
+sub _STDIN {
+ my $c = shift;
+ my $stdin;
+
+ if ( $c->req->content->is_multipart ) {
+ $stdin = Mojo::Asset::File->new;
+ $stdin->add_chunk( $c->req->build_body );
+ }
+ else {
+ $stdin = $c->req->content->asset;
+ }
+
+ return $stdin if $stdin->isa('Mojo::Asset::File');
+ return Mojo::Asset::File->new->add_chunk( $stdin->slurp );
+}
+
+sub _file_to_method {
+ my ($name) = @_;
+ $name =~ s/\./_/s;
+ $name =~ s/\W+/_/gs;
+ return $name;
+}
+
+
+1;
diff --git a/Bugzilla/Quantum/Plugin/BasicAuth.pm b/Bugzilla/Quantum/Plugin/BasicAuth.pm
new file mode 100644
index 000000000..bc79c89ef
--- /dev/null
+++ b/Bugzilla/Quantum/Plugin/BasicAuth.pm
@@ -0,0 +1,40 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+package Bugzilla::Quantum::Plugin::BasicAuth;
+use 5.10.1;
+use Mojo::Base qw(Mojolicious::Plugin);
+
+use Bugzilla::Logging;
+use Carp;
+
+sub register {
+ my ( $self, $app, $conf ) = @_;
+
+ $app->renderer->add_helper(
+ basic_auth => sub {
+ my ($c, $realm, $auth_user, $auth_pass) = @_;
+ my $req = $c->req;
+ my ($user, $password) = $req->url->to_abs->userinfo =~ /^([^:]+):(.*)/;
+
+ unless ($realm && $auth_user && $auth_pass) {
+ croak 'basic_auth() called with missing parameters.';
+ }
+
+ unless ($user eq $auth_user && $password eq $auth_pass) {
+ WARN('username and password do not match');
+ $c->res->headers->www_authenticate("Basic realm=\"$realm\"");
+ $c->res->code(401);
+ $c->rendered;
+ return 0;
+ }
+
+ return 1;
+ }
+ );
+}
+
+1;
diff --git a/Bugzilla/Quantum/Plugin/BlockIP.pm b/Bugzilla/Quantum/Plugin/BlockIP.pm
new file mode 100644
index 000000000..fbfffad66
--- /dev/null
+++ b/Bugzilla/Quantum/Plugin/BlockIP.pm
@@ -0,0 +1,43 @@
+package Bugzilla::Quantum::Plugin::BlockIP;
+use 5.10.1;
+use Mojo::Base 'Mojolicious::Plugin';
+
+use Bugzilla::Memcached;
+
+use constant BLOCK_TIMEOUT => 60*60;
+
+my $MEMCACHED = Bugzilla::Memcached->_new()->{memcached};
+
+sub register {
+ my ( $self, $app, $conf ) = @_;
+
+ $app->hook(before_routes => \&_before_routes);
+ $app->helper(block_ip => \&_block_ip);
+ $app->helper(unblock_ip => \&_unblock_ip);
+}
+
+sub _block_ip {
+ my ($class, $ip) = @_;
+ $MEMCACHED->set("block_ip:$ip" => 1, BLOCK_TIMEOUT) if $MEMCACHED;
+}
+
+sub _unblock_ip {
+ my ($class, $ip) = @_;
+ $MEMCACHED->delete("block_ip:$ip") if $MEMCACHED;
+}
+
+sub _before_routes {
+ my ( $c ) = @_;
+ return if $c->stash->{'mojo.static'};
+
+ my $ip = $c->tx->remote_address;
+ if ($MEMCACHED && $MEMCACHED->get("block_ip:$ip")) {
+ $c->block_ip($ip);
+ $c->res->code(429);
+ $c->res->message("Too Many Requests");
+ $c->res->body("Too Many Requests");
+ $c->finish;
+ }
+}
+
+1;
diff --git a/Bugzilla/Quantum/Plugin/Glue.pm b/Bugzilla/Quantum/Plugin/Glue.pm
new file mode 100644
index 000000000..4261d6729
--- /dev/null
+++ b/Bugzilla/Quantum/Plugin/Glue.pm
@@ -0,0 +1,114 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum::Plugin::Glue;
+use 5.10.1;
+use Mojo::Base 'Mojolicious::Plugin';
+
+use Try::Tiny;
+use Bugzilla::Constants;
+use Bugzilla::Quantum::Template;
+use Bugzilla::Logging;
+use Bugzilla::RNG ();
+use JSON::MaybeXS qw(decode_json);
+
+sub register {
+ my ( $self, $app, $conf ) = @_;
+
+ my %D;
+ if ($ENV{BUGZILLA_HTTPD_ARGS}) {
+ my $args = decode_json($ENV{BUGZILLA_HTTPD_ARGS});
+ foreach my $arg (@$args) {
+ if ($arg =~ /^-D(\w+)$/) {
+ $D{$1} = 1;
+ }
+ else {
+ die "Unknown httpd arg: $arg";
+ }
+ }
+ }
+
+ # hypnotoad is weird and doesn't look for MOJO_LISTEN itself.
+ $app->config(
+ hypnotoad => {
+ listen => [ $ENV{MOJO_LISTEN} ],
+ },
+ );
+
+ # Make sure each httpd child receives a different random seed (bug 476622).
+ # Bugzilla::RNG has one srand that needs to be called for
+ # every process, and Perl has another. (Various Perl modules still use
+ # the built-in rand(), even though we never use it in Bugzilla itself,
+ # so we need to srand() both of them.)
+ # Also, ping the dbh to force a reconnection.
+ Mojo::IOLoop->next_tick(
+ sub {
+ Bugzilla::RNG::srand();
+ srand();
+ eval { Bugzilla->dbh->ping };
+ }
+ );
+
+ $app->hook(
+ before_dispatch => sub {
+ my ($c) = @_;
+ if ($D{HTTPD_IN_SUBDIR}) {
+ my $path = $c->req->url->path;
+ if ($path =~ s{^/bmo}{}s) {
+ $c->stash->{bmo_prefix} = 1;
+ $c->req->url->path($path);
+ }
+ }
+ Log::Log4perl::MDC->put(request_id => $c->req->request_id);
+ }
+ );
+
+ Bugzilla::Extension->load_all();
+ if ($app->mode ne 'development') {
+ Bugzilla->preload_features();
+ DEBUG("preloading templates");
+ Bugzilla->preload_templates();
+ DEBUG("done preloading templates");
+ }
+ $app->secrets([Bugzilla->localconfig->{side_wide_secret}]);
+
+ $app->renderer->add_handler(
+ 'bugzilla' => sub {
+ my ( $renderer, $c, $output, $options ) = @_;
+ my $vars = delete $c->stash->{vars};
+
+ # Helpers
+ my %helper;
+ foreach my $method ( grep {m/^\w+\z/} keys %{ $renderer->helpers } ) {
+ my $sub = $renderer->helpers->{$method};
+ $helper{$method} = sub { $c->$sub(@_) };
+ }
+ $vars->{helper} = \%helper;
+
+ # The controller
+ $vars->{c} = $c;
+ my $name = $options->{template};
+ unless ($name =~ /\./) {
+ $name = sprintf '%s.%s.tmpl', $options->{template}, $options->{format};
+ }
+ my $template = Bugzilla->template;
+ $template->process( $name, $vars, $output )
+ or die $template->error;
+ }
+ );
+
+ $app->log(
+ MojoX::Log::Log4perl::Tiny->new(
+ logger => Log::Log4perl->get_logger(ref $app)
+ )
+ );
+}
+
+
+
+
+1;
diff --git a/Bugzilla/ModPerl/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm
index a3bdfac58..42a05a910 100644
--- a/Bugzilla/ModPerl/Hostage.pm
+++ b/Bugzilla/Quantum/Plugin/Hostage.pm
@@ -1,9 +1,6 @@
-package Bugzilla::ModPerl::Hostage;
+package Bugzilla::Quantum::Plugin::Hostage;
use 5.10.1;
-use strict;
-use warnings;
-
-use Apache2::Const qw(:common); ## no critic (Freenode::ModPerl)
+use Mojo::Base 'Mojolicious::Plugin';
sub _attachment_root {
my ($base) = @_;
@@ -24,8 +21,14 @@ sub _attachment_host_regex {
return qr/^$regex$/s;
}
-sub handler {
- my $r = shift;
+sub register {
+ my ( $self, $app, $conf ) = @_;
+
+ $app->hook(before_routes => \&_before_routes);
+}
+
+sub _before_routes {
+ my ( $c ) = @_;
state $urlbase = Bugzilla->localconfig->{urlbase};
state $urlbase_uri = URI->new($urlbase);
state $urlbase_host = $urlbase_uri->host;
@@ -34,37 +37,43 @@ sub handler {
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 $stash = $c->stash;
+ my $req = $c->req;
+ my $url = $req->url->to_abs;
+
+ return if $stash->{'mojo.static'};
+
+ my $hostname = $url->host;
+ return if $hostname eq $urlbase_host;
- my $path = $r->uri;
- return OK if $path eq '/__lbheartbeat__';
+ my $path = $url->path;
+ return if $path eq '/__lbheartbeat__';
if ($attachment_base && $hostname eq $attachment_root) {
- $r->headers_out->set(Location => $urlbase);
- return REDIRECT;
+ $c->redirect_to($urlbase);
+ return;
}
elsif ($attachment_base && $hostname =~ $attachment_host_regex) {
if ($path =~ m{^/attachment\.cgi}s) {
- return OK;
+ return;
} else {
- my $new_uri = URI->new($r->unparsed_uri);
+ my $new_uri = $url->clone;
$new_uri->scheme($urlbase_uri->scheme);
$new_uri->host($urlbase_host);
- $r->headers_out->set(Location => $new_uri);
- return REDIRECT;
+ $c->redirect_to($new_uri);
+ return;
}
}
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;
+ $c->redirect_to($new_uri);
+ return;
}
else {
- $r->headers_out->set(Location => $urlbase);
- return REDIRECT;
+ $c->redirect_to($urlbase);
+ return;
}
}
diff --git a/ses/index.cgi b/Bugzilla/Quantum/SES.pm
index e36956b1d..47c591fb5 100755..100644
--- a/ses/index.cgi
+++ b/Bugzilla/Quantum/SES.pm
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+package Bugzilla::Quantum::SES;
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -7,12 +7,8 @@
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
-use strict;
-use warnings;
+use Mojo::Base qw( Mojolicious::Controller );
-use lib qw(.. ../lib ../local/lib/perl5);
-
-use Bugzilla ();
use Bugzilla::Constants qw(ERROR_MODE_DIE);
use Bugzilla::Logging;
use Bugzilla::Mailer qw(MessageToMTA);
@@ -22,51 +18,44 @@ use JSON::MaybeXS qw(decode_json);
use LWP::UserAgent ();
use Try::Tiny qw(catch try);
-Bugzilla->error_mode(ERROR_MODE_DIE);
-try {
- main();
-}
-catch {
- FATAL("Fatal error: $_");
- respond( 500 => 'Internal Server Error' );
-};
-
sub main {
- my $message = decode_json_wrapper( Bugzilla->cgi->param('POSTDATA') ) // return;
- my $message_type = $ENV{HTTP_X_AMZ_SNS_MESSAGE_TYPE} // '(missing)';
+ my ($self) = @_;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+ my $message = $self->_decode_json_wrapper( $self->req->body ) // return;
+ my $message_type = $self->req->headers->header('X-Amz-SNS-Message-Type') // '(missing)';
if ( $message_type eq 'SubscriptionConfirmation' ) {
- confirm_subscription($message);
+ $self->_confirm_subscription($message);
}
elsif ( $message_type eq 'Notification' ) {
- my $notification = decode_json_wrapper( $message->{Message} ) // return;
+ my $notification = $self->_decode_json_wrapper( $message->{Message} ) // return;
unless (
# https://docs.aws.amazon.com/ses/latest/DeveloperGuide/event-publishing-retrieving-sns-contents.html
- handle_notification( $notification, 'eventType' )
+ $self->_handle_notification( $notification, 'eventType' )
# https://docs.aws.amazon.com/ses/latest/DeveloperGuide/notification-contents.html
- || handle_notification( $notification, 'notificationType' )
+ || $self->_handle_notification( $notification, 'notificationType' )
)
{
WARN('Failed to find notification type');
- respond( 400 => 'Bad Request' );
+ $self->_respond( 400 => 'Bad Request' );
}
}
else {
WARN("Unsupported message-type: $message_type");
- respond( 200 => 'OK' );
+ $self->_respond( 200 => 'OK' );
}
}
-sub confirm_subscription {
- my ($message) = @_;
+sub _confirm_subscription {
+ my ($self, $message) = @_;
my $subscribe_url = $message->{SubscribeURL};
if ( !$subscribe_url ) {
WARN('Bad SubscriptionConfirmation request: missing SubscribeURL');
- respond( 400 => 'Bad Request' );
+ $self->_respond( 400 => 'Bad Request' );
return;
}
@@ -74,15 +63,15 @@ sub confirm_subscription {
my $res = $ua->get( $message->{SubscribeURL} );
if ( !$res->is_success ) {
WARN( 'Bad response from SubscribeURL: ' . $res->status_line );
- respond( 400 => 'Bad Request' );
+ $self->_respond( 400 => 'Bad Request' );
return;
}
- respond( 200 => 'OK' );
+ $self->_respond( 200 => 'OK' );
}
-sub handle_notification {
- my ( $notification, $type_field ) = @_;
+sub _handle_notification {
+ my ( $self, $notification, $type_field ) = @_;
if ( !exists $notification->{$type_field} ) {
return 0;
@@ -90,20 +79,20 @@ sub handle_notification {
my $type = $notification->{$type_field};
if ( $type eq 'Bounce' ) {
- process_bounce($notification);
+ $self->_process_bounce($notification);
}
elsif ( $type eq 'Complaint' ) {
- process_complaint($notification);
+ $self->_process_complaint($notification);
}
else {
WARN("Unsupported notification-type: $type");
- respond( 200 => 'OK' );
+ $self->_respond( 200 => 'OK' );
}
return 1;
}
-sub process_bounce {
- my ($notification) = @_;
+sub _process_bounce {
+ my ($self, $notification) = @_;
# disable each account that is bouncing
foreach my $recipient ( @{ $notification->{bounce}->{bouncedRecipients} } ) {
@@ -140,10 +129,11 @@ sub process_bounce {
}
}
- respond( 200 => 'OK' );
+ $self->_respond( 200 => 'OK' );
}
-sub process_complaint {
+sub _process_complaint {
+ my ($self) = @_;
# email notification to bugzilla admin
my ($notification) = @_;
@@ -170,31 +160,28 @@ sub process_complaint {
MessageToMTA($message);
}
- respond( 200 => 'OK' );
+ $self->_respond( 200 => 'OK' );
}
-sub respond {
- my ( $code, $message ) = @_;
- print Bugzilla->cgi->header( -status => "$code $message" );
-
- # apache will generate non-200 response pages for us
- say html_quote($message) if $code == 200;
+sub _respond {
+ my ( $self, $code, $message ) = @_;
+ $self->render(text => "$message\n", status => $code);
}
-sub decode_json_wrapper {
- my ($json) = @_;
+sub _decode_json_wrapper {
+ my ($self, $json) = @_;
my $result;
if ( !defined $json ) {
- WARN( 'Missing JSON from ' . remote_ip() );
- respond( 400 => 'Bad Request' );
+ WARN( 'Missing JSON from ' . $self->tx->remote_address );
+ $self->_respond( 400 => 'Bad Request' );
return undef;
}
my $ok = try {
$result = decode_json($json);
}
catch {
- WARN( 'Malformed JSON from ' . remote_ip() );
- respond( 400 => 'Bad Request' );
+ WARN( 'Malformed JSON from ' . $self->tx->remote_address );
+ $self->_respond( 400 => 'Bad Request' );
return undef;
};
return $ok ? $result : undef;
@@ -212,3 +199,5 @@ sub ua {
}
return $ua;
}
+
+1; \ No newline at end of file
diff --git a/Bugzilla/Quantum/Static.pm b/Bugzilla/Quantum/Static.pm
new file mode 100644
index 000000000..2bb54990e
--- /dev/null
+++ b/Bugzilla/Quantum/Static.pm
@@ -0,0 +1,30 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum::Static;
+use Mojo::Base 'Mojolicious::Static';
+use Bugzilla::Constants qw(bz_locations);
+
+my $LEGACY_RE = qr{
+ ^ (?:static/v[0-9]+\.[0-9]+/) ?
+ ( (?:extensions/[^/]+/web|(?:image|skin|j)s)/.+)
+ $
+}xs;
+
+sub file {
+ my ($self, $rel) = @_;
+
+ if (my ($legacy_rel) = $rel =~ $LEGACY_RE) {
+ local $self->{paths} = [ bz_locations->{cgi_path} ];
+ return $self->SUPER::file($legacy_rel);
+ }
+ else {
+ return $self->SUPER::file($rel);
+ }
+}
+
+1;
diff --git a/Bugzilla/Quantum/Stdout.pm b/Bugzilla/Quantum/Stdout.pm
new file mode 100644
index 000000000..2cdba9160
--- /dev/null
+++ b/Bugzilla/Quantum/Stdout.pm
@@ -0,0 +1,59 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum::Stdout;
+use 5.10.1;
+use Moo;
+
+use Bugzilla::Logging;
+use Encode;
+
+has 'controller' => (
+ is => 'ro',
+ required => 1,
+);
+
+has '_encoding' => (
+ is => 'rw',
+ default => '',
+);
+
+sub TIEHANDLE { ## no critic (unpack)
+ my $class = shift;
+
+ return $class->new(@_);
+}
+
+sub PRINTF { ## no critic (unpack)
+ my $self = shift;
+ $self->PRINT(sprintf @_);
+}
+
+sub PRINT { ## no critic (unpack)
+ my $self = shift;
+ my $c = $self->controller;
+ my $bytes = join '', @_;
+ return unless $bytes;
+ if ($self->_encoding) {
+ $bytes = encode($self->_encoding, $bytes);
+ }
+ $c->write($bytes);
+}
+
+sub BINMODE {
+ my ($self, $mode) = @_;
+ if ($mode) {
+ if ($mode eq ':bytes' or $mode eq ':raw') {
+ $self->_encoding('');
+ }
+ elsif ($mode eq ':utf8') {
+ $self->_encoding('utf8');
+ }
+ }
+}
+
+1;
diff --git a/Bugzilla/Quantum/Template.pm b/Bugzilla/Quantum/Template.pm
new file mode 100644
index 000000000..2442f1134
--- /dev/null
+++ b/Bugzilla/Quantum/Template.pm
@@ -0,0 +1,39 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Quantum::Template;
+use 5.10.1;
+use Moo;
+
+has 'controller' => (
+ is => 'ro',
+ required => 1,
+);
+
+has 'template' => (
+ is => 'ro',
+ required => 1,
+ handles => ['error', 'get_format'],
+);
+
+sub process {
+ my ($self, $file, $vars, $output) = @_;
+
+ if (@_ < 4) {
+ $self->controller->stash->{vars} = $vars;
+ $self->controller->render(template => $file, handler => 'bugzilla');
+ return 1;
+ }
+ elsif (@_ == 4) {
+ return $self->template->process($file, $vars, $output);
+ }
+ else {
+ die __PACKAGE__ . '->process() called with too many arguments';
+ }
+}
+
+1; \ No newline at end of file
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index 299734d64..39272a538 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -12,6 +12,7 @@ use 5.10.1;
use strict;
use warnings;
+use Bugzilla::Logging;
use Bugzilla::Template::PreloadProvider;
use Bugzilla::Bug;
use Bugzilla::Constants;
diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm
index 6bb73af01..5ad50e91c 100644
--- a/Bugzilla/WebService/Server/XMLRPC.pm
+++ b/Bugzilla/WebService/Server/XMLRPC.pm
@@ -14,11 +14,7 @@ use warnings;
use Bugzilla::Logging;
use XMLRPC::Transport::HTTP;
use Bugzilla::WebService::Server;
-if ($ENV{MOD_PERL}) {
- our @ISA = qw(XMLRPC::Transport::HTTP::Apache Bugzilla::WebService::Server);
-} else {
- our @ISA = qw(XMLRPC::Transport::HTTP::CGI Bugzilla::WebService::Server);
-}
+our @ISA = qw(XMLRPC::Transport::HTTP::CGI Bugzilla::WebService::Server);
use Bugzilla::WebService::Constants;
use Bugzilla::Error;
diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm
index 29ff05448..d462c884a 100644
--- a/Bugzilla/WebService/Util.pm
+++ b/Bugzilla/WebService/Util.pm
@@ -23,7 +23,7 @@ use base qw(Exporter);
# We have to "require", not "use" this, because otherwise it tries to
# use features of Test::More during import().
-require Test::Taint;
+require Test::Taint if ${^TAINT};
our @EXPORT_OK = qw(
extract_flags
@@ -193,8 +193,10 @@ sub taint_data {
# Though this is a private function, it hasn't changed since 2004 and
# should be safe to use, and prevents us from having to write it ourselves
# or require another module to do it.
- Test::Taint::_deeply_traverse(\&_delete_bad_keys, \@params);
- Test::Taint::taint_deeply(\@params);
+ if (${^TAINT}) {
+ Test::Taint::_deeply_traverse(\&_delete_bad_keys, \@params);
+ Test::Taint::taint_deeply(\@params);
+ }
}
sub _delete_bad_keys {
diff --git a/Dockerfile b/Dockerfile
index c86a92b0f..f9baf009d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,12 +9,6 @@ ENV CIRCLE_BUILD_URL=${CIRCLE_BUILD_URL}
ENV CIRCLE_SHA1=${CIRCLE_SHA1}
ENV LOG4PERL_CONFIG_FILE=log4perl-json.conf
-ENV HTTPD_StartServers=8
-ENV HTTPD_MinSpareServers=5
-ENV HTTPD_MaxSpareServers=20
-ENV HTTPD_ServerLimit=256
-ENV HTTPD_MaxClients=256
-ENV HTTPD_MaxRequestsPerChild=4000
ENV PORT=8000
@@ -28,7 +22,8 @@ RUN mv /opt/bmo/local /app && \
chown -R app:app /app && \
perl -I/app -I/app/local/lib/perl5 -c -E 'use Bugzilla; BEGIN { Bugzilla->extensions }' && \
perl -c /app/scripts/entrypoint.pl && \
- setcap 'cap_net_bind_service=+ep' /usr/sbin/httpd
+ setcap 'cap_net_bind_service=+ep' /usr/sbin/httpd && \
+ setcap 'cap_net_bind_service=+ep' /usr/bin/perl
USER app
diff --git a/Log/Log4perl/Layout/Mozilla.pm b/Log/Log4perl/Layout/Mozilla.pm
index b625c54f4..4aedd9843 100644
--- a/Log/Log4perl/Layout/Mozilla.pm
+++ b/Log/Log4perl/Layout/Mozilla.pm
@@ -53,6 +53,9 @@ sub render {
my $mdc = Log::Log4perl::MDC->get_context;
my $fields = $mdc->{fields} // {};
+ if ($mdc->{request_id}) {
+ $fields->{request_id} = $mdc->{request_id}
+ }
my %out = (
EnvVersion => LOGGING_FORMAT_VERSION,
Hostname => $HOSTNAME,
diff --git a/Makefile.PL b/Makefile.PL
index 46228ab56..51a2507e1 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -69,6 +69,7 @@ my %requires = (
'Module::Metadata' => '1.000033',
'Module::Runtime' => '0.014',
'Mojolicious' => '7.71',
+ 'MojoX::Log::Log4perl::Tiny' => '0.01',
'Moo' => '2.002004',
'MooX::StrictConstructor' => '0.008',
'Mozilla::CA' => '20160104',
@@ -79,6 +80,7 @@ my %requires = (
'Template' => '2.24',
'Text::CSV_XS' => '1.26',
'Throwable' => '0.200013',
+ 'Sub::Quote' => '2.005000',
'Type::Tiny' => '1.000005',
'URI' => '1.55',
'URI::Escape::XS' => '0.14',
@@ -282,18 +284,6 @@ my %optional_features = (
}
},
},
- mod_perl => {
- description => 'mod_perl support under Apache',
- prereqs => {
- runtime => {
- requires => {
- 'mod_perl2' => '1.999022',
- 'Apache2::SizeLimit' => '0.96',
- 'Plack::Handler::Apache2' => 0,
- }
- }
- }
- },
inbound_email => {
description => 'Inbound Email',
prereqs => {
@@ -449,7 +439,6 @@ sub is_bmo_feature {
^
(?: pg
| oracle
- | mod_perl
| sqlite
| auth_ldap
| auth_radius
diff --git a/README.rst b/README.rst
index 985be314e..0d8d03f38 100644
--- a/README.rst
+++ b/README.rst
@@ -330,41 +330,6 @@ BMO_use_mailer_queue
Usually configured on the MTA section of the admin interface, you may change this here for testing purposes.
Should be 1 or 0. If 1, the job queue will be used. For testing, only set to 0 if the BMO_mail_delivery_method is None or Test.
-HTTPD_StartServers
- Sets the number of child server processes created on startup.
- As the number of processes is dynamically controlled depending on the load,
- there is usually little reason to adjust this parameter.
- Default: 8
-
-HTTPD_MinSpareServers
- Sets the desired minimum number of idle child server processes. An idle
- process is one which is not handling a request. If there are fewer than
- MinSpareServers idle, then the parent process creates new children at a
- maximum rate of 1 per second.
- Default: 5
-
-HTTPD_MaxSpareServers
- Sets the desired maximum number of idle child server processes. An idle
- process is one which is not handling a request. If there are more than
- MaxSpareServers idle, then the parent process will kill off the excess
- processes.
- Default: 20
-
-HTTPD_MaxClients
- Sets the maximum number of child processes that will be launched to serve requests.
- Default: 256
-
-HTTPD_ServerLimit
- Sets the maximum configured value for MaxClients for the lifetime of the
- Apache process.
- Default: 256
-
-HTTPD_MaxRequestsPerChild
- Sets the limit on the number of requests that an individual child server
- process will handle. After MaxRequestsPerChild requests, the child process
- will die. If MaxRequestsPerChild is 0, then the process will never expire.
- Default: 4000
-
USE_NYTPROF
Write `Devel::NYTProf`_ profiles out for each requests.
These will be named /app/data/nytprof.$host.$script.$n.$pid, where $host is
diff --git a/buglist.cgi b/buglist.cgi
index 4d3ad1a86..fee259a2b 100755
--- a/buglist.cgi
+++ b/buglist.cgi
@@ -41,6 +41,8 @@ my $vars = {};
my $user = Bugzilla->login();
$cgi->redirect_search_url();
+use Bugzilla::Logging;
+DEBUG("After the redirect.");
my $buffer = $cgi->query_string();
if (length($buffer) == 0) {
@@ -114,15 +116,15 @@ my $format = $template->get_format("list/list", scalar $cgi->param('format'),
# Safari (WebKit) does not support it, despite a UA that says otherwise (bug 188712)
# MSIE 5+ supports it on Mac (but not on Windows) (bug 190370)
#
-my $serverpush =
- $format->{'extension'} eq "html"
- && exists $ENV{'HTTP_USER_AGENT'}
- && $ENV{'HTTP_USER_AGENT'} =~ /Mozilla.[3-9]/
- && (($ENV{'HTTP_USER_AGENT'} !~ /[Cc]ompatible/) || ($ENV{'HTTP_USER_AGENT'} =~ /MSIE 5.*Mac_PowerPC/))
- && $ENV{'HTTP_USER_AGENT'} !~ /(?:WebKit|Trident|KHTML)/
- && !$agent
- && !defined($cgi->param('serverpush'))
- || $cgi->param('serverpush');
+my $serverpush = 0;
+ # $format->{'extension'} eq "html"
+ # && exists $ENV{'HTTP_USER_AGENT'}
+ # && $ENV{'HTTP_USER_AGENT'} =~ /Mozilla.[3-9]/
+ # && (($ENV{'HTTP_USER_AGENT'} !~ /[Cc]ompatible/) || ($ENV{'HTTP_USER_AGENT'} =~ /MSIE 5.*Mac_PowerPC/))
+ # && $ENV{'HTTP_USER_AGENT'} !~ /(?:WebKit|Trident|KHTML)/
+ # && !$agent
+ # && !defined($cgi->param('serverpush'))
+ # || $cgi->param('serverpush');
my $order = $cgi->param('order') || "";
@@ -752,12 +754,6 @@ if ($serverpush) {
$template->process("list/server-push.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
- # Under mod_perl, flush stdout so that the page actually shows up.
- if ($ENV{MOD_PERL}) {
- require Apache2::RequestUtil;
- Apache2::RequestUtil->request->rflush();
- }
-
# Don't do multipart_end() until we're ready to display the replacement
# page, otherwise any errors that happen before then (like SQL errors)
# will result in a blank page being shown to the user instead of the error.
diff --git a/bugzilla.pl b/bugzilla.pl
new file mode 100755
index 000000000..efcea293b
--- /dev/null
+++ b/bugzilla.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+use 5.10.1;
+use strict;
+use warnings;
+
+use File::Basename qw(basename dirname);
+use File::Spec::Functions qw(catdir);
+use Cwd qw(realpath);
+
+BEGIN {
+ require lib;
+ my $dir = realpath( dirname(__FILE__) );
+ lib->import( $dir, catdir( $dir, 'lib' ), catdir( $dir, qw(local lib perl5) ) );
+}
+use Mojolicious::Commands;
+
+$ENV{MOJO_LISTEN} ||= $ENV{PORT} ? "http://*:$ENV{PORT}" : "http://*:3001";
+
+# Start command line interface for application
+Mojolicious::Commands->start_app('Bugzilla::Quantum');
diff --git a/checksetup.pl b/checksetup.pl
index d3f08e024..7c9826ee3 100755
--- a/checksetup.pl
+++ b/checksetup.pl
@@ -135,7 +135,7 @@ require Bugzilla::Install::Localconfig;
import Bugzilla::Install::Localconfig qw(update_localconfig);
require Bugzilla::Install::Filesystem;
-import Bugzilla::Install::Filesystem qw(update_filesystem create_htaccess
+import Bugzilla::Install::Filesystem qw(update_filesystem
fix_all_file_permissions);
require Bugzilla::Install::DB;
require Bugzilla::DB;
@@ -201,7 +201,6 @@ unless ($switch{'no-database'}) {
###########################################################################
update_filesystem({ index_html => $lc_hash->{'index_html'} });
-create_htaccess() if $lc_hash->{'create_htaccess'};
# Remove parameters from the params file that no longer exist in Bugzilla,
# and set the defaults for new ones
diff --git a/colchange.cgi b/colchange.cgi
index d77782bec..46d25ecdf 100755
--- a/colchange.cgi
+++ b/colchange.cgi
@@ -136,26 +136,12 @@ if (defined $cgi->param('rememberedquery')) {
$params->param('columnlist', join(",", @collist));
$vars->{'redirect_url'} = "buglist.cgi?".$params->query_string();
-
# If we're running on Microsoft IIS, $cgi->redirect discards
# the Set-Cookie lines. In mod_perl, $cgi->redirect with cookies
# causes the page to be rendered as text/plain.
# Workaround is to use the old-fashioned redirection mechanism.
# See bug 214466 and bug 376044 for details.
- if ($ENV{'MOD_PERL'}
- || $ENV{'SERVER_SOFTWARE'} =~ /Microsoft-IIS/
- || $ENV{'SERVER_SOFTWARE'} =~ /Sun ONE Web/)
- {
- print $cgi->header(-type => "text/html",
- -refresh => "0; URL=$vars->{'redirect_url'}");
- }
- else {
- print $cgi->redirect($vars->{'redirect_url'});
- exit;
- }
-
- $template->process("global/message.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
+ print $cgi->redirect($vars->{'redirect_url'});
exit;
}
diff --git a/conf/log4perl-test.conf b/conf/log4perl-test.conf
index 77fc00af8..1760279db 100644
--- a/conf/log4perl-test.conf
+++ b/conf/log4perl-test.conf
@@ -4,14 +4,14 @@ log4perl.appender.Cereal.PeerAddr=127.0.0.1
log4perl.appender.Cereal.PeerPort=5880
log4perl.appender.Cereal.defer_connection=1
log4perl.appender.Cereal.layout = Log::Log4perl::Layout::PatternLayout
-log4perl.appender.Cereal.layout.ConversionPattern = %d %6p | %c | %m{chomp}%n
+log4perl.appender.Cereal.layout.ConversionPattern = %X{request_id} %d %6p | %c | %m{chomp}%n
log4perl.filter.LOG_TO_STDERR = sub { not $ENV{LOG4PERL_STDERR_DISABLE} }
log4perl.appender.Screen = Log::Log4perl::Appender::Screen
log4perl.appender.Screen.Filter = LOG_TO_STDERR
log4perl.appender.Screen.stderr = 1
log4perl.appender.Screen.layout = Log::Log4perl::Layout::PatternLayout
-log4perl.appender.Screen.layout.ConversionPattern = %d %6p | %c | %m{chomp}%n
+log4perl.appender.Screen.layout.ConversionPattern = STDERR: %X{request_id} %d %6p | %c | %m{chomp}%n
log4perl.appender.File = Log::Log4perl::Appender::File
log4perl.appender.File.layout = Log::Log4perl::Layout::Mozilla
diff --git a/docker-compose.yml b/docker-compose.yml
index 1ca6f5c90..b00c6bc03 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -19,6 +19,7 @@ services:
- LOCALCONFIG_ENV=1
- LOG4PERL_CONFIG_FILE=log4perl-docker.conf
- BUGZILLA_UNSAFE_AUTH_DELEGATION=1
+ - HTTP_BACKEND=simple
- PORT=80
- BMO_db_host=bmo-db.vm
- BMO_db_name=bugs
diff --git a/heartbeat.cgi b/heartbeat.cgi
index 3edbed371..493674c16 100755
--- a/heartbeat.cgi
+++ b/heartbeat.cgi
@@ -29,7 +29,6 @@ my $ok = eval {
die "database not available" unless $database_ok;
die "memcached server(s) not available" unless $memcached_ok;
- die "mod_perl not configured?" unless $ENV{MOD_PERL};
if ($dbh->isa('Bugzilla::DB::Mysql') && Bugzilla->params->{utf8} eq 'utf8mb4') {
my $mysql_var = $dbh->selectall_hashref(q{SHOW VARIABLES LIKE 'character_set%'}, 'Variable_name');
foreach my $name (qw( character_set_client character_set_connection character_set_database )) {
@@ -45,11 +44,4 @@ FATAL("heartbeat error: $@") if !$ok && $@;
my $cgi = Bugzilla->cgi;
print $cgi->header(-type => 'text/plain', -status => $ok ? '200 OK' : '500 Internal Server Error');
-print $ok ? "Bugzilla OK\n" : "Bugzilla NOT OK\n";
-
-if ($ENV{MOD_PERL}) {
- my $r = $cgi->r;
- # doing this supresses the error document, but does not change the http response code.
- $r->rflush;
- $r->status(200);
-}
+print $ok ? "Bugzilla OK\n" : "Bugzilla NOT OK\n"; \ No newline at end of file
diff --git a/jobqueue-worker.pl b/jobqueue-worker.pl
index b26aacdba..b26aacdba 100644..100755
--- a/jobqueue-worker.pl
+++ b/jobqueue-worker.pl
diff --git a/qa/t/lib/QA/Util.pm b/qa/t/lib/QA/Util.pm
index 5d041d560..bf9151fee 100644
--- a/qa/t/lib/QA/Util.pm
+++ b/qa/t/lib/QA/Util.pm
@@ -18,6 +18,7 @@ use Sys::Hostname qw(hostname);
use Socket qw(inet_ntoa);
use WWW::Selenium::Util qw(server_is_running);
use URI;
+use URI::QueryParam;
# Fixes wide character warnings
BEGIN {
@@ -50,6 +51,7 @@ use base qw(Exporter);
get_selenium
get_rpc_clients
+ check_page_load
WAIT_TIME
CHROME_MODE
@@ -396,6 +398,32 @@ sub set_parameters {
}
}
+my @ANY_KEYS = qw( t token );
+
+sub check_page_load {
+ my ($sel, $wait, $expected) = @_;
+ my $expected_uri = URI->new($expected);
+ $sel->wait_for_page_to_load_ok($wait);
+ my $uri = URI->new($sel->get_location);
+
+ foreach my $u ($expected_uri, $uri) {
+ $u->host('HOSTNAME');
+ foreach my $any_key (@ANY_KEYS) {
+ if ($u->query_param($any_key)) {
+ $u->query_param($any_key => '__ANYTHING__');
+ }
+ }
+ }
+
+ if ($expected_uri->query_param('id')) {
+ if ($expected_uri->query_param('id') eq '__BUG_ID__') {
+ $uri->query_param('id' => '__BUG_ID__');
+ }
+ }
+ my ($pkg, $file, $line) = caller;
+ is($uri, $expected_uri, "checking location on $file line $line");
+}
+
1;
__END__
diff --git a/qa/t/test_bug_edit.t b/qa/t/test_bug_edit.t
index 07a64876b..01037aa1e 100644
--- a/qa/t/test_bug_edit.t
+++ b/qa/t/test_bug_edit.t
@@ -32,10 +32,10 @@ if ($sel->is_text_present("My bugs from QA_Selenium")) {
# Just in case the test failed before completion previously, reset the CANEDIT bit.
go_to_admin($sel);
$sel->click_ok("link=Groups");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editgroups.cgi});
$sel->title_is("Edit Groups");
$sel->click_ok("link=Master");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editgroups.cgi?action=changeform&group=26});
$sel->title_is("Change Group: Master");
my $group_url = $sel->get_location();
$group_url =~ /group=(\d+)$/;
@@ -52,7 +52,7 @@ $sel->select_ok("bug_severity", "label=critical");
$sel->type_ok("short_desc", "Test bug editing");
$sel->type_ok("comment", "ploc");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=__BUG_ID__});
my $bug1_id = $sel->get_value('//input[@name="id" and @type="hidden"]');
$sel->is_text_present_ok('has been added to the database', "Bug $bug1_id created");
@@ -67,28 +67,28 @@ $sel->type_ok("status_whiteboard", "[Selenium was here]");
$sel->type_ok("comment", "new comment from me :)");
$sel->select_ok("bug_status", "label=RESOLVED");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
# Now move the bug into another product, which has a mandatory group.
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->select_ok("product", "label=QA-Selenium-TEST");
$sel->type_ok("comment", "moving to QA-Selenium-TEST");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Verify New Product Details...");
$sel->select_ok("component", "label=QA-Selenium-TEST");
$sel->is_element_present_ok('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]');
ok(!$sel->is_editable('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]'), "QA-Selenium-TEST group not editable");
$sel->is_checked_ok('//input[@type="checkbox" and @name="groups" and @value="QA-Selenium-TEST"]', "QA-Selenium-TEST group is selected");
$sel->click_ok("change_product");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->select_ok("bug_severity", "label=normal");
$sel->select_ok("priority", "label=High");
@@ -101,14 +101,14 @@ $sel->type_ok("comment", "Unchecking the reporter_accessible checkbox");
$sel->click_ok("reporter_accessible");
$sel->select_ok("bug_status", "label=VERIFIED");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->type_ok("comment", "I am the reporter, but I can see the bug anyway as I belong to the mandatory group");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -125,16 +125,16 @@ $sel->click_ok("bz_assignee_edit_action");
$sel->type_ok("assigned_to", $config->{admin_user_login});
$sel->type_ok("comment", "I have editbugs privs. Taking!");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->click_ok("cc_edit_area_showhide");
$sel->type_ok("newcc", $config->{unprivileged_user_login});
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -153,7 +153,7 @@ go_to_bug($sel, $bug1_id);
$sel->click_ok("cclist_accessible");
$sel->type_ok("comment", "I am allowed to turn off cclist_accessible despite not being in the mandatory group");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -162,7 +162,7 @@ logout($sel);
log_in($sel, $config, 'unprivileged');
$sel->type_ok("quicksearch_top", $bug1_id);
$sel->submit("header-search");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_is("Access Denied");
$sel->is_text_present_ok("You are not authorized to access bug $bug1_id");
logout($sel);
@@ -178,7 +178,7 @@ $sel->click_ok("set_default_assignee");
$sel->uncheck_ok("set_default_assignee");
$sel->type_ok("comment", "-> Moving back to Testproduct.");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Verify New Product Details...");
$sel->select_ok("component", "label=TestComponent");
$sel->is_text_present_ok("These groups are not legal for the 'TestProduct' product or you are not allowed to restrict bugs to these groups");
@@ -189,15 +189,15 @@ $sel->is_element_present_ok('//input[@type="checkbox" and @name="groups" and @va
$sel->is_editable_ok('//input[@type="checkbox" and @name="groups" and @value="Master"]', "Master group is editable");
ok(!$sel->is_checked('//input[@type="checkbox" and @name="groups" and @value="Master"]'), "Master group not selected by default");
$sel->click_ok("change_product");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->click_ok("cclist_accessible");
$sel->type_ok("comment", "I am allowed to turn off cclist_accessible despite not being in the mandatory group");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -216,7 +216,7 @@ $sel->click_ok("cc_edit_area_showhide");
$sel->add_selection_ok("cc", "label=" . $config->{admin_user_login});
$sel->click_ok("removecc");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -225,11 +225,11 @@ logout($sel);
log_in($sel, $config, 'admin');
edit_product($sel, "TestProduct");
$sel->click_ok("link=Edit Group Access Controls:");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editproducts.cgi?action=editgroupcontrols&product=TestProduct});
$sel->title_is("Edit Group Controls for TestProduct");
$sel->check_ok("canedit_$master_gid");
$sel->click_ok("submit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editproducts.cgi});
$sel->title_is("Update group access controls for TestProduct");
# The user is in the master group, so he can comment.
@@ -237,7 +237,7 @@ $sel->title_is("Update group access controls for TestProduct");
go_to_bug($sel, $bug1_id);
$sel->type_ok("comment", "Do nothing except adding a comment...");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
logout($sel);
@@ -247,7 +247,7 @@ log_in($sel, $config, 'QA_Selenium_TEST');
go_to_bug($sel, $bug1_id);
$sel->type_ok("comment", "Just a comment too...");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Product Edit Access Denied");
$sel->is_text_present_ok("You are not permitted to edit bugs in product TestProduct.");
logout($sel);
@@ -256,10 +256,12 @@ logout($sel);
log_in($sel, $config, 'admin');
open_advanced_search_page($sel);
+screenshot_page($sel, '/app/artifacts/line259.png');
$sel->remove_all_selections_ok("product");
$sel->add_selection_ok("product", "TestProduct");
$sel->remove_all_selections_ok("bug_status");
$sel->remove_all_selections_ok("resolution");
+screenshot_page($sel, '/app/artifacts/line264.png');
$sel->is_checked_ok("emailassigned_to1");
$sel->select_ok("emailtype1", "label=is");
$sel->type_ok("email1", $config->{admin_user_login});
@@ -268,21 +270,22 @@ $sel->check_ok("emailqa_contact2");
$sel->check_ok("emailcc2");
$sel->select_ok("emailtype2", "label=is");
$sel->type_ok("email2", $config->{QA_Selenium_TEST_user_login});
+screenshot_page($sel, '/app/artifacts/line271.png');
$sel->click_ok("Search");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?emailreporter2=1&emailtype2=exact&order=Importance&list_id=15&emailtype1=exact&emailcc2=1&query_format=advanced&emailassigned_to1=1&emailqa_contact2=1&email2=QA-Selenium-TEST%40mozilla.test&email1=admin%40mozilla.test&emailassigned_to2=1&product=TestProduct});
$sel->title_is("Bug List");
-
+screenshot_page($sel, '/app/artifacts/line275.png');
$sel->is_text_present_ok("One bug found.");
$sel->type_ok("save_newqueryname", "My bugs from QA_Selenium");
$sel->click_ok("remember");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?newquery=email1%3Dadmin%2540mozilla.test%26email2%3DQA-Selenium-TEST%2540mozilla.test%26emailassigned_to1%3D1%26emailassigned_to2%3D1%26emailcc2%3D1%26emailqa_contact2%3D1%26emailreporter2%3D1%26emailtype1%3Dexact%26emailtype2%3Dexact%26list_id%3D15%26product%3DTestProduct%26query_format%3Dadvanced%26order%3Dpriority%252Cbug_severity&cmdtype=doit&remtype=asnamed&token=1531926552-dc69995d79c786af046436ec6717000b&newqueryname=My%20bugs%20from%20QA_Selenium&list_id=16});
$sel->title_is("Search created");
$sel->is_text_present_ok("OK, you have a new search named My bugs from QA_Selenium.");
$sel->click_ok("link=My bugs from QA_Selenium");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?cmdtype=runnamed&namedcmd=My%20bugs%20from%20QA_Selenium&list_id=17});
$sel->title_is("Bug List: My bugs from QA_Selenium");
$sel->click_ok("long_format");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/show_bug.cgi});
$sel->title_is("Full Text Bug Listing");
$sel->is_text_present_ok("Bug $bug1_id");
$sel->is_text_present_ok("Status: CONFIRMED");
@@ -303,25 +306,25 @@ $sel->type_ok("short_desc", "New bug from me");
# We turned on the CANEDIT bit for TestProduct.
$sel->type_ok("comment", "I can enter a new bug, but not edit it, right?");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=__BUG_ID__});
my $bug2_id = $sel->get_value('//input[@name="id" and @type="hidden"]');
$sel->is_text_present_ok('has been added to the database', "Bug $bug2_id created");
# Clicking the "Back" button and resubmitting the form again should trigger a suspicous action error.
$sel->go_back_ok();
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/enter_bug.cgi?product=TestProduct&format=__default__});
$sel->title_is("Enter Bug: TestProduct");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/post_bug.cgi});
$sel->title_is("Suspicious Action");
$sel->is_text_present_ok("you have no valid token for the create_bug action");
$sel->click_ok('//input[@value="Confirm Changes"]');
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/show_bug.cgi?id=15});
$sel->is_text_present_ok('has been added to the database', 'Bug created');
$sel->type_ok("comment", "New comment not allowed");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Product Edit Access Denied");
$sel->is_text_present_ok("You are not permitted to edit bugs in product TestProduct.");
logout($sel);
@@ -334,42 +337,46 @@ $sel->click_ok("bz_assignee_edit_action");
$sel->type_ok("assigned_to", $config->{admin_user_login});
$sel->type_ok("comment", "Taking!");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug2_id});
$sel->is_text_present_ok("Changes submitted for bug $bug2_id");
# Test mass-change.
$sel->click_ok("link=My bugs from QA_Selenium");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+screenshot_page($sel, '/app/artifacts/line344.png');
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?cmdtype=runnamed&namedcmd=My%20bugs%20from%20QA_Selenium&list_id=19});
+screenshot_page($sel, '/app/artifacts/line346.png');
$sel->title_is("Bug List: My bugs from QA_Selenium");
+screenshot_page($sel, '/app/artifacts/line348.png');
$sel->is_text_present_ok("2 bugs found");
+screenshot_page($sel, '/app/artifacts/line350.png');
$sel->click_ok("link=Change Several Bugs at Once");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?email1=admin%40mozilla.test&email2=QA-Selenium-TEST%40mozilla.test&emailassigned_to1=1&emailassigned_to2=1&emailcc2=1&emailqa_contact2=1&emailreporter2=1&emailtype1=exact&emailtype2=exact&product=TestProduct&query_format=advanced&order=priority%2Cbug_severity&tweak=1&list_id=20});
$sel->title_is("Bug List");
$sel->click_ok("check_all");
$sel->type_ok("comment", 'Mass change"');
$sel->select_ok("bug_status", "label=RESOLVED");
$sel->select_ok("resolution", "label=WORKSFORME");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Bugs processed");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/$bug1_id /);
$sel->selected_label_is("resolution", "WORKSFORME");
$sel->select_ok("resolution", "label=INVALID");
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/$bug1_id /);
$sel->selected_label_is("resolution", "INVALID");
$sel->click_ok("link=History");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_activity.cgi?id=$bug1_id});
$sel->title_is("Changes made to bug $bug1_id");
$sel->is_text_present_ok("URL foo.cgi?action=bar");
$sel->is_text_present_ok("Severity critical blocker");
@@ -431,10 +438,10 @@ foreach my $params (["no_token_single_bug", ""], ["invalid_token_single_bug", "&
$sel->title_is("Suspicious Action");
$sel->is_text_present_ok($token ? "an invalid token" : "web browser directly");
$sel->click_ok("confirm");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+ check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->is_text_present_ok("Changes submitted for bug $bug1_id");
$sel->click_ok("link=bug $bug1_id");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+ check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug1_id});
$sel->title_like(qr/^$bug1_id /);
$sel->is_text_present_ok($comment);
}
@@ -446,16 +453,16 @@ foreach my $params (["no_token_mass_change", ""], ["invalid_token_mass_change",
$sel->title_is("Suspicious Action");
$sel->is_text_present_ok("no valid token for the buglist_mass_change action");
$sel->click_ok("confirm");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+ check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Bugs processed");
foreach my $bug_id ($bug1_id, $bug2_id) {
$sel->click_ok("link=bug $bug_id");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+ check_page_load($sel, WAIT_TIME, qq{http://HOSTNAME:8000/bmo/show_bug.cgi?id=$bug_id});
$sel->title_like(qr/^$bug_id /);
$sel->is_text_present_ok($comment);
next if $bug_id == $bug2_id;
$sel->go_back_ok();
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+ check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Bugs processed");
}
}
@@ -463,26 +470,26 @@ foreach my $params (["no_token_mass_change", ""], ["invalid_token_mass_change",
# Now move these bugs out of our radar.
$sel->click_ok("link=My bugs from QA_Selenium");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?cmdtype=runnamed&namedcmd=My%20bugs%20from%20QA_Selenium&list_id=21});
$sel->title_is("Bug List: My bugs from QA_Selenium");
$sel->is_text_present_ok("2 bugs found");
$sel->click_ok("link=Change Several Bugs at Once");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?email1=admin%40mozilla.test&email2=QA-Selenium-TEST%40mozilla.test&emailassigned_to1=1&emailassigned_to2=1&emailcc2=1&emailqa_contact2=1&emailreporter2=1&emailtype1=exact&emailtype2=exact&product=TestProduct&query_format=advanced&order=priority%2Cbug_severity&tweak=1&list_id=22});
$sel->title_is("Bug List");
$sel->click_ok("check_all");
$sel->type_ok("comment", "Reassigning to the reporter");
$sel->type_ok("assigned_to", $config->{QA_Selenium_TEST_user_login});
$sel->click_ok("commit");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/process_bug.cgi});
$sel->title_is("Bugs processed");
# Now delete the saved search.
$sel->click_ok("link=My bugs from QA_Selenium");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?cmdtype=runnamed&namedcmd=My%20bugs%20from%20QA_Selenium&list_id=23});
$sel->title_is("Bug List: My bugs from QA_Selenium");
$sel->click_ok("link=Forget Search 'My bugs from QA_Selenium'");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/buglist.cgi?cmdtype=dorem&remaction=forget&namedcmd=My%20bugs%20from%20QA_Selenium&token=1531926582-f228fa8ebc2f2b3970f2a791e54534ec&list_id=24});
$sel->title_is("Search is gone");
$sel->is_text_present_ok("OK, the My bugs from QA_Selenium search is gone");
@@ -495,10 +502,10 @@ sub clear_canedit_on_testproduct {
edit_product($sel, "TestProduct");
$sel->click_ok("link=Edit Group Access Controls:");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editproducts.cgi?action=editgroupcontrols&product=TestProduct});
$sel->title_is("Edit Group Controls for TestProduct");
$sel->uncheck_ok("canedit_$master_gid");
$sel->click_ok("submit");
- $sel->wait_for_page_to_load_ok(WAIT_TIME);
+check_page_load($sel, WAIT_TIME, q{http://HOSTNAME:8000/bmo/editproducts.cgi});
$sel->title_is("Update group access controls for TestProduct");
}
diff --git a/qa/t/test_shutdown.t b/qa/t/test_shutdown.t
deleted file mode 100644
index dc5cabd4a..000000000
--- a/qa/t/test_shutdown.t
+++ /dev/null
@@ -1,72 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# This Source Code Form is "Incompatible With Secondary Licenses", as
-# defined by the Mozilla Public License, v. 2.0.
-
-use strict;
-use warnings;
-use lib qw(lib ../../lib ../../local/lib/perl5);
-
-use Test::More "no_plan";
-
-use QA::Util;
-
-my ($sel, $config) = get_selenium();
-
-log_in($sel, $config, 'admin');
-set_parameters($sel, { "General" => {shutdownhtml => {type => "text",
- value => "I'm down (set by test_shutdown.t)" }
- } });
-
-# None of the following pages should be accessible when Bugzilla is down.
-
-my @pages = qw(admin attachment buglist chart colchange config createaccount
- describecomponents describekeywords duplicates
- editclassifications editcomponents editfields editflagtypes
- editgroups editkeywords editmilestones editproducts editsettings
- editusers editvalues editversions editwhines editworkflow
- enter_bug index long_list page post_bug process_bug query quips
- relogin report reports request sanitycheck search_plugin
- show_activity show_bug showattachment showdependencygraph
- showdependencytree sidebar summarize_time token userprefs votes
- xml xmlrpc);
-
-foreach my $page (@pages) {
- $sel->open_ok("/$config->{bugzilla_installation}/${page}.cgi");
- $sel->title_is("Bugzilla is Down");
-}
-
-# Those have parameters passed to the page, so we put them here separately.
-
-@pages = ("query.cgi?format=report-table", "query.cgi?format=report-graph",
- "votes.cgi?action=show_user", "votes.cgi?action=show_bug");
-
-foreach my $page (@pages) {
- $sel->open_ok("/$config->{bugzilla_installation}/$page");
- $sel->title_is("Bugzilla is Down");
-}
-
-# Clear 'shutdownhtml', to re-enable Bugzilla.
-# At this point, the admin has been logged out. We cannot use log_in(),
-# nor set_parameters(), due to shutdownhtml being active.
-
-$sel->open_ok("/$config->{bugzilla_installation}/editparams.cgi");
-$sel->title_is("Log in to Bugzilla");
-$sel->type_ok("Bugzilla_login", $config->{admin_user_login}, "Enter admin login name");
-$sel->type_ok("Bugzilla_password", $config->{admin_user_passwd}, "Enter admin password");
-$sel->click_ok("log_in");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
-$sel->title_is("Configuration: General");
-$sel->type_ok("shutdownhtml", "");
-$sel->click_ok('//input[@type="submit" and @value="Save Changes"]', undef, "Save Changes");
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
-$sel->title_is("Parameters Updated");
-
-# Accessing index.cgi should work again now.
-
-$sel->click_ok('//*[@id="header-title"]//a');
-$sel->wait_for_page_to_load_ok(WAIT_TIME);
-$sel->title_is("Bugzilla Main Page");
-logout($sel);
diff --git a/scripts/block-ip.pl b/scripts/block-ip.pl
index b767a1fd5..3fa66d336 100755
--- a/scripts/block-ip.pl
+++ b/scripts/block-ip.pl
@@ -12,8 +12,8 @@ use warnings;
use lib qw(. lib local/lib/perl5);
use Bugzilla;
+use Bugzilla::Quantum;
use Bugzilla::Constants;
-use Bugzilla::ModPerl::BlockIP;
use Getopt::Long;
Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
@@ -23,10 +23,12 @@ GetOptions('unblock' => \$unblock);
pod2usage("No IPs given") unless @ARGV;
+my $app = Bugzilla::Quantum->new;
+
if ($unblock) {
- Bugzilla::ModPerl::BlockIP->unblock_ip($_) for @ARGV;
+ $app->unblock_ip($_) for @ARGV;
} else {
- Bugzilla::ModPerl::BlockIP->block_ip($_) for @ARGV;
+ $app->block_ip($_) for @ARGV;
}
=head1 NAME
@@ -52,4 +54,4 @@ If passed, the IPs will be unblocked instead of blocked. Use this to remove IPs
=head1 DESCRIPTION
-This is just a simple CLI inteface to L<Bugzilla::ModPerl::BlockIP>.
+This is just a simple CLI inteface to L<Bugzilla::Quantum::Plugin::BlockIP>.
diff --git a/scripts/entrypoint.pl b/scripts/entrypoint.pl
index ce1cc795b..e5ecc4324 100755
--- a/scripts/entrypoint.pl
+++ b/scripts/entrypoint.pl
@@ -156,6 +156,7 @@ sub cmd_test_webservices {
sub cmd_test_selenium {
my $conf = require $ENV{BZ_QA_CONF_FILE};
+ $ENV{HTTP_BACKEND} = 'simple';
check_data_dir();
copy_qa_extension();
diff --git a/scripts/undo.pl b/scripts/undo.pl
index 24d6f594b..24d6f594b 100644..100755
--- a/scripts/undo.pl
+++ b/scripts/undo.pl
diff --git a/t/001compile.t b/t/001compile.t
index e81162056..3d8d82bf4 100644
--- a/t/001compile.t
+++ b/t/001compile.t
@@ -35,7 +35,7 @@ sub compile_file {
my ($file) = @_;
# Don't allow CPAN.pm to modify the global @INC, which the version
- # shipped with Perl 5.8.8 does. (It gets loaded by
+ # shipped with Perl 5.8.8 does. (It gets loaded by
# Bugzilla::Install::CPAN.)
local @INC = @INC;
@@ -43,10 +43,6 @@ sub compile_file {
skip "$file: extensions not tested", 1;
return;
}
- if ($file =~ /ModPerl/) {
- skip "$file: ModPerl stuff not tested", 1;
- return;
- }
if ($file =~ s/\.pm$//) {
$file =~ s{/}{::}g;
@@ -82,7 +78,7 @@ my $file_features = map_files_to_features();
# Test the scripts by compiling them
foreach my $file (@testitems) {
# These were already compiled, above.
- next if ($file eq 'Bugzilla.pm'
+ next if ($file eq 'Bugzilla.pm'
or $file eq 'Bugzilla/Constants.pm'
or $file eq 'Bugzilla/Install/Requirements.pm');
SKIP: {
@@ -94,10 +90,10 @@ foreach my $file (@testitems) {
skip "$file: $feature not enabled", 1;
}
- # Check that we have a DBI module to support the DB, if this
+ # Check that we have a DBI module to support the DB, if this
# is a database module (but not Schema)
if ($file =~ m{Bugzilla/DB/([^/]+)\.pm$}
- and $file ne "Bugzilla/DB/Schema.pm")
+ and $file ne "Bugzilla/DB/Schema.pm")
{
my $module = lc($1);
Bugzilla->feature($module) or skip "$file: Driver for $module not installed", 1;
@@ -105,4 +101,4 @@ foreach my $file (@testitems) {
compile_file($file);
}
-}
+}
diff --git a/t/002goodperl.t b/t/002goodperl.t
index 5f201160b..80d7cf2b9 100644
--- a/t/002goodperl.t
+++ b/t/002goodperl.t
@@ -83,6 +83,7 @@ foreach my $file (@testitems) {
my $found_use_strict = 0;
my $found_use_warnings = 0;
my $found_modern_perl = 0;
+ my $found_mojo = 0;
$file =~ s/\s.*$//; # nuke everything after the first space (#comment)
next if (!$file); # skip null entries
@@ -92,13 +93,17 @@ foreach my $file (@testitems) {
}
while (my $file_line = <FILE>) {
$found_modern_perl = 1 if $file_line =~ m/^use\s*(?:Moo|Role::Tiny)/;
+ $found_mojo = 1 if $file_line =~ m/^use\s(?:Mojo(?:licious::Lite|::Base)\b)/;
$found_use_perl = 1 if $file_line =~ m/^\s*use 5.10.1/;
$found_use_strict = 1 if $file_line =~ m/^\s*use strict/;
$found_use_warnings = 1 if $file_line =~ m/^\s*use warnings/;
- if ($found_modern_perl) {
+ if ($found_modern_perl || $found_mojo) {
$found_use_strict = 1;
$found_use_warnings = 1;
}
+ if ($found_mojo) {
+ $found_use_perl = 1;
+ }
last if ($found_use_perl && $found_use_strict && $found_use_warnings);
}
close (FILE);
diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl
index 6a19eaf39..efb8d4407 100644
--- a/template/en/default/global/header.html.tmpl
+++ b/template/en/default/global/header.html.tmpl
@@ -97,6 +97,8 @@
[% IF Param('utf8') %]
<meta charset="UTF-8">
[% END %]
+ [% USE Bugzilla %]
+ <base href="[% urlbase FILTER html %]">
[% IF Bugzilla.cgi.should_block_referrer %]
<meta name="referrer" content="origin">
diff --git a/vagrant_support/apache.yml b/vagrant_support/apache.yml
index 5031187e3..2d65965ab 100644
--- a/vagrant_support/apache.yml
+++ b/vagrant_support/apache.yml
@@ -6,8 +6,8 @@
mode: 0644
when: LAZY == 0
-- name: enable httpd
- service: name=httpd enabled=yes
+- name: disable httpd
+ service: name=httpd enabled=no
when: LAZY == 0
- name: ensure bugzilla.log has right permissions
@@ -16,5 +16,5 @@
- name: ensure bugzilla-json.log has right permissions
file: path=/vagrant/logs/bugzilla-json.log state=touch owner=vagrant group=apache mode=0660
-- name: restart httpd
- service: name=httpd state=restarted \ No newline at end of file
+- name: stop httpd
+ service: name=httpd state=stopped
diff --git a/vagrant_support/hypnotoad b/vagrant_support/hypnotoad
new file mode 100755
index 000000000..5e8dc910e
--- /dev/null
+++ b/vagrant_support/hypnotoad
@@ -0,0 +1,122 @@
+#!/bin/bash
+#
+# bugzilla-push This starts, stops, and restarts the Bugzilla push
+# daemon, which manages syncronising bugzilla.mozilla.org and
+# third party bugzilla installs.
+#
+# chkconfig: 345 85 15
+# description: Bugzilla push daemon
+#
+### BEGIN INIT INFO
+# Provides: bugzilla-push
+# Required-Start: $local_fs $syslog MTA mysqld
+# Required-Stop: $local_fs $syslog MTA mysqld
+# Default-Start: 3 5
+# Default-Stop: 0 1 2 6
+# Short-Description: Start and stop the Bugzilla push daemon.
+# Description: The Bugzilla push daemon (bugzilla-pushd.pl)
+#
+#
+#
+### END INIT INFO
+
+NAME=`basename $0`
+
+#################
+# Configuration #
+#################
+
+# This should be the path to your Bugzilla
+BUGZILLA=/vagrant
+# Who owns the Bugzilla directory and files?
+USER=vagrant
+
+PERL5LIB="$BUGZILLA:$BUGZILLA/lib:$BUGZILLA/local/lib/perl5"
+export PERL5LIB
+export MOJO_MODE
+
+if [[ x$PORT == x ]]; then
+ PORT=80
+ export PORT
+fi
+
+# If you want to pass any options to the daemon (like -d for debugging)
+# specify it here.
+OPTIONS=""
+
+# You can also override the configuration by creating a
+# /etc/sysconfig/bugzilla-queue file so that you don't
+# have to edit this script.
+if [ -r /etc/sysconfig/$NAME ]; then
+ . /etc/sysconfig/$NAME
+fi
+
+##########
+# Script #
+##########
+
+RETVAL=0
+BIN="$BUGZILLA/local/bin/hypnotoad"
+PIDFILE="$BUGZILLA/hypnotoad.pid"
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+usage ()
+{
+ echo "Usage: service $NAME {start|stop|status|restart|condrestart}"
+ RETVAL=1
+}
+
+
+start ()
+{
+ if [[ -f $PIDFILE ]]; then
+ checkpid "$(cat $PIDFILE)" && return 0
+ fi
+ echo -n "Starting $NAME: "
+ daemon --pidfile=$PIDFILE --user=$USER "cd $BUGZILLA && $BIN bugzilla.pl >/dev/null"
+ ret=$?
+ [ $ret -eq "0" ] && touch /var/lock/subsys/$NAME
+ echo
+ return $ret
+}
+
+stop ()
+{
+ cd $BUGZILLA && $BIN bugzilla.pl --stop
+ rm -f /var/lock/subsys/$NAME
+}
+
+restart ()
+{
+ stop
+ start
+}
+
+condrestart ()
+{
+ [ -e /var/lock/subsys/$NAME ] && restart || return 0
+}
+
+status ()
+{
+ if [[ -f $PIDFILE ]] && checkpid "$(cat $PIDFILE)"; then
+ echo hypnotoad is amazing
+ return 0
+ else
+ echo hypnotoad is not running
+ return 1
+ fi
+}
+
+case "$1" in
+ start) start; RETVAL=$? ;;
+ stop) stop; RETVAL=$? ;;
+ status) status; RETVAL=$?;;
+ restart) restart; RETVAL=$? ;;
+ condrestart) condrestart; RETVAL=$? ;;
+ *) usage ; RETVAL=2 ;;
+esac
+
+exit $RETVAL
diff --git a/vagrant_support/hypnotoad.yml b/vagrant_support/hypnotoad.yml
new file mode 100644
index 000000000..a66f9ba04
--- /dev/null
+++ b/vagrant_support/hypnotoad.yml
@@ -0,0 +1,27 @@
+- name: grant perl ability to listen to privledged ports
+ command: setcap 'cap_net_bind_service=+ep' /usr/bin/perl
+
+- name: hypnotoad daemon sysconfig
+ copy:
+ dest: /etc/sysconfig/hypnotoad
+ mode: 0644
+ content: |
+ BUGZILLA=/vagrant
+ USER=vagrant
+ MOJO_MODE=development
+
+- name: hypnotoad daemon init file
+ template:
+ dest: /etc/init.d/hypnotoad
+ src: hypnotoad
+ owner: root
+ group: root
+ mode: 0755
+
+- name: enable hypnotoad
+ service: name=hypnotoad enabled=yes
+ when: LAZY == 0
+
+- name: restart hypnotoad
+ service: name=hypnotoad state=restarted
+
diff --git a/vagrant_support/playbook.yml b/vagrant_support/playbook.yml
index c067eab05..3dd320f0b 100644
--- a/vagrant_support/playbook.yml
+++ b/vagrant_support/playbook.yml
@@ -170,9 +170,6 @@
dest: /usr/local/bin/cpanm
mode: '0755'
- - name: install more recent Apache2::SizeLimit
- cpanm: name=Apache2::SizeLimit executable=/usr/local/bin/cpanm
-
- name: 'check /opt/bmo (failure is ok)'
shell: test -d /opt/bmo && test -f /opt/bmo/local/lib/perl5/Plack.pm
register: opt_bmo
@@ -222,5 +219,8 @@
- include_tasks: apache.yml
vars:
LAZY: 0
+ - include_tasks: hypnotoad.yml
+ vars:
+ LAZY: 0
- import_tasks: devtools.yml
diff --git a/vagrant_support/update.yml b/vagrant_support/update.yml
index c53a0554e..533da5b5e 100644
--- a/vagrant_support/update.yml
+++ b/vagrant_support/update.yml
@@ -20,4 +20,7 @@
LAZY: 1
- include_tasks: apache.yml
vars:
- LAZY: 1 \ No newline at end of file
+ LAZY: 1
+ - include_tasks: hypnotoad.yml
+ vars:
+ LAZY: 1