summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Bugzilla.pm20
-rw-r--r--Bugzilla/CGI.pm4
-rw-r--r--Bugzilla/Constants.pm4
-rw-r--r--Bugzilla/DaemonControl.pm34
-rw-r--r--Bugzilla/Logging.pm2
-rw-r--r--Bugzilla/PSGI.pm42
-rw-r--r--Bugzilla/Template.pm4
-rwxr-xr-xMakefile.PL34
-rw-r--r--app.psgi115
-rwxr-xr-xeditusers.cgi5
-rw-r--r--extensions/BMO/Extension.pm23
-rw-r--r--extensions/BzAPI/Extension.pm9
-rw-r--r--extensions/MyDashboard/web/styles/mydashboard.css3
-rw-r--r--extensions/Push/lib/Logger.pm2
-rw-r--r--extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl2
-rwxr-xr-xheartbeat.cgi2
-rw-r--r--mod_perl.pl3
-rwxr-xr-xscripts/cereal.pl49
-rwxr-xr-xscripts/migrate-database.pl47
-rwxr-xr-xtoken.cgi2
-rwxr-xr-xuserprefs.cgi2
21 files changed, 347 insertions, 61 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm
index 17fefa447..3e969a99d 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -118,20 +118,6 @@ sub init_page {
# 001compile.t test).
return if $^C;
- # IIS prints out warnings to the webpage, so ignore them, or log them
- # to a file if the file exists.
- if ($ENV{SERVER_SOFTWARE} && $ENV{SERVER_SOFTWARE} =~ /microsoft-iis/i) {
- $SIG{__WARN__} = sub {
- my ($msg) = @_;
- my $datadir = bz_locations()->{'datadir'};
- if (-w "$datadir/errorlog") {
- my $warning_log = new IO::File(">>$datadir/errorlog");
- print $warning_log $msg;
- $warning_log->close();
- }
- };
- }
-
my $script = basename($0);
# BMO - init metrics collection if required
@@ -370,7 +356,7 @@ sub login {
return $class->user if $class->user->id;
# Load all extensions here if not running under mod_perl
- $class->extensions unless $ENV{MOD_PERL};
+ $class->extensions unless BZ_PERSISTENT;
my $authorizer = new Bugzilla::Auth();
$type = LOGIN_REQUIRED if $class->cgi->param('GoAheadAndLogIn');
@@ -917,10 +903,10 @@ sub _cleanup {
sub END {
# Bugzilla.pm cannot compile in mod_perl.pl if this runs.
- _cleanup() unless $ENV{MOD_PERL};
+ _cleanup() unless BZ_PERSISTENT;
}
-init_page() if !$ENV{MOD_PERL};
+init_page() unless BZ_PERSISTENT;
1;
diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm
index 3737b97e2..05e2bd749 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -113,7 +113,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() if BZ_PERSISTENT;
my $self = $class->SUPER::new(@args);
@@ -597,6 +597,8 @@ sub header {
sub param {
my $self = shift;
+ local $CGI::LIST_CONTEXT_WARN = 0;
+
# When we are just requesting the value of a parameter...
if (scalar(@_) == 1) {
my @result = $self->SUPER::param(@_);
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 00f0f8104..2971c7a53 100644
--- a/Bugzilla/Constants.pm
+++ b/Bugzilla/Constants.pm
@@ -194,6 +194,8 @@ use Memoize;
EMAIL_LIMIT_EXCEPTION
JOB_QUEUE_VIEW_MAX_JOBS
+
+ BZ_PERSISTENT
);
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
@@ -705,6 +707,8 @@ sub _bz_locations {
};
}
+use constant BZ_PERSISTENT => $main::BUGZILLA_PERSISTENT;
+
# This makes us not re-compute all the bz_locations data every time it's
# called.
BEGIN { memoize('_bz_locations') };
diff --git a/Bugzilla/DaemonControl.pm b/Bugzilla/DaemonControl.pm
index 05aaf8130..b7f7bcbe9 100644
--- a/Bugzilla/DaemonControl.pm
+++ b/Bugzilla/DaemonControl.pm
@@ -39,6 +39,8 @@ our %EXPORT_TAGS = (
utils => [qw(catch_signal on_exception on_finish)],
);
+use constant CEREAL_BIN => realpath(catfile( bz_locations->{cgi_path}, 'scripts', 'cereal.pl'));
+
use constant HTTPD_BIN => '/usr/sbin/httpd';
use constant HTTPD_CONFIG => realpath(catfile( bz_locations->{confdir}, 'httpd.conf' ));
@@ -67,41 +69,11 @@ sub catch_signal {
return $signal_f;
}
-sub cereal {
- local $PROGRAM_NAME = "cereal";
- $ENV{LOGGING_PORT} //= 5880;
-
- my $loop = IO::Async::Loop->new;
- my $on_stream = sub {
- my ($stream) = @_;
- my $protocol = IO::Async::Protocol::LineStream->new(
- transport => $stream,
- on_read_line => sub {
- my ( $self, $line ) = @_;
- say $line;
- },
- );
- $loop->add($protocol);
- };
- my @signals = (
- catch_signal('TERM', 0),
- catch_signal('INT', 0 ),
- catch_signal('KILL', 0 ),
- );
- $loop->listen(
- host => '127.0.0.1',
- service => $ENV{LOGGING_PORT},
- socktype => 'stream',
- on_stream => $on_stream,
- )->get;
- exit Future->wait_any(@signals)->get;
-}
-
sub run_cereal {
my $loop = IO::Async::Loop->new;
my $exit_f = $loop->new_future;
my $cereal = IO::Async::Process->new(
- code => \&cereal,
+ command => [CEREAL_BIN],
on_finish => on_finish($exit_f),
on_exception => on_exception( "cereal", $exit_f ),
);
diff --git a/Bugzilla/Logging.pm b/Bugzilla/Logging.pm
index b69ffa2e9..769485c86 100644
--- a/Bugzilla/Logging.pm
+++ b/Bugzilla/Logging.pm
@@ -17,7 +17,7 @@ use Bugzilla::Constants qw(bz_locations);
use English qw(-no_match_vars $PROGRAM_NAME);
sub is_interactive {
- return exists $ENV{'SERVER_SOFTWARE'} ? 1 : 0;
+ return not exists $ENV{SERVER_SOFTWARE}
}
BEGIN {
diff --git a/Bugzilla/PSGI.pm b/Bugzilla/PSGI.pm
new file mode 100644
index 000000000..46352b319
--- /dev/null
+++ b/Bugzilla/PSGI.pm
@@ -0,0 +1,42 @@
+# 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::PSGI;
+use 5.10.1;
+use strict;
+use warnings;
+
+use base qw(Exporter);
+
+use Bugzilla::Logging;
+our @EXPORT_OK = qw(compile_cgi);
+
+sub compile_cgi {
+ my ($script) = @_;
+ require CGI::Compile;
+ require CGI::Emulate::PSGI;
+
+ my $cgi = CGI::Compile->compile($script);
+ my $app = CGI::Emulate::PSGI->handler(
+ sub {
+ Bugzilla::init_page();
+ $cgi->();
+ }
+ );
+ return sub {
+ my $env = shift;
+ if ($env->{'psgix.cleanup'}) {
+ push @{ $env->{'psgix.cleanup.handler'} }, \&Bugzilla::_cleanup;
+ }
+ my $res = $app->($env);
+ Bugzilla::_cleanup() if not $env->{'psgix.cleanup'};
+ return $res;
+ };
+}
+
+
+1; \ No newline at end of file
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index d27896532..0d2a4cd86 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -570,7 +570,7 @@ sub create {
# if a packager has modified bz_locations() to contain absolute
# paths.
ABSOLUTE => 1,
- RELATIVE => $ENV{MOD_PERL} ? 0 : 1,
+ RELATIVE => 0,
COMPILE_DIR => bz_locations()->{'template_cache'},
@@ -1037,7 +1037,7 @@ sub create {
# under mod_perl, use a provider (template loader) that preloads all templates into memory
my $provider_class
- = $ENV{MOD_PERL}
+ = BZ_PERSISTENT
? 'Bugzilla::Template::PreloadProvider'
: 'Template::Provider';
diff --git a/Makefile.PL b/Makefile.PL
index 34e4e2487..57bc06001 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -34,6 +34,8 @@ BEGIN {
my %requires = (
'Algorithm::BloomFilter' => '0.02',
'CGI' => '3.51',
+ 'CGI::Compile' => 0,
+ 'CGI::Emulate::PSGI' => 0,
'CPAN::Meta::Prereqs' => '2.132830',
'CPAN::Meta::Requirements' => '2.121',
'Class::XSAccessor' => '1.18',
@@ -51,11 +53,14 @@ my %requires = (
'HTML::Escape' => '1.10',
'IO::Async' => '0.71',
'JSON::MaybeXS' => '1.003008',
+ 'JSON::MaybeXS' => '1.003008',
'JSON::XS' => '2.01',
'LWP::Protocol::https' => '6.07',
'LWP::UserAgent' => '6.26',
'List::MoreUtils' => '0.418',
'Log::Dispatch' => '2.67',
+ 'Log::Dispatch' => '2.67',
+ 'Log::Log4perl' => '1.49',
'Log::Log4perl' => '1.49',
'Math::Random::ISAAC' => '1.0.1',
'Module::Metadata' => '1.000033',
@@ -64,8 +69,10 @@ my %requires = (
'MooX::StrictConstructor' => '0.008',
'Mozilla::CA' => '20160104',
'Parse::CPAN::Meta' => '1.44',
+ 'Plack' => '1.0031',
'Role::Tiny' => '2.000003',
'Sereal' => '4.004',
+ 'Sereal' => '4.004',
'Taint::Util' => '0.08',
'Template' => '2.24',
'Text::CSV_XS' => '1.26',
@@ -318,6 +325,32 @@ my %optional_features = (
}
}
},
+<<<<<<< HEAD
+=======
+ psgi => {
+ description => "PSGI Support",
+ prereqs => {
+ runtime => {
+ requires => {
+ 'Plack' => '1.0031',
+ 'CGI::Compile' => 0,
+ 'CGI::Emulate::PSGI' => 0,
+ },
+ },
+ },
+ },
+ csp => {
+ description => 'Content-Security-Policy support',
+ prereqs => {
+ runtime => {
+ requires => {
+ 'Type::Tiny' => 1,
+ 'MooX::StrictConstructor' => 0.008,
+ }
+ }
+ }
+ },
+>>>>>>> 741eeec31... psgi optionalize until can rebuild vendor bundle
elasticsearch => {
description => 'Elasticsearch-powered searches',
prereqs => {
@@ -363,6 +396,7 @@ my @bmo_features = grep {
(?: pg
| oracle
| mod_perl
+ | psgi
| sqlite
| auth_ldap
| auth_radius
diff --git a/app.psgi b/app.psgi
new file mode 100644
index 000000000..4425b3e0c
--- /dev/null
+++ b/app.psgi
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+# 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 5.10.1;
+use strict;
+use warnings;
+
+BEGIN { $main::BUGZILLA_PERSISTENT = 1 }
+
+use File::Basename;
+use File::Spec;
+
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs( dirname(__FILE__) );
+ lib->import(
+ $dir,
+ File::Spec->catdir( $dir, 'lib' ),
+ File::Spec->catdir( $dir, qw(local lib perl5) )
+ );
+
+ # disable "use lib" from now on
+ no warnings qw(redefine);
+ *lib::import = sub { };
+}
+
+# it is very important for CGI::Compile to be loaded first.
+use CGI::Compile;
+use Bugzilla::PSGI qw(compile_cgi);
+use Bugzilla::Logging;
+use Bugzilla ();
+use Bugzilla::Constants ();
+use Bugzilla::BugMail ();
+use Bugzilla::CGI ();
+use Bugzilla::Extension ();
+use Bugzilla::Install::Requirements ();
+use Bugzilla::Util ();
+use Bugzilla::RNG ();
+
+use Plack;
+use Plack::Builder;
+use Plack::App::URLMap;
+use Plack::App::WrapCGI;
+use Plack::Response;
+
+# Pre-load all extensions and find their static dirs.
+my @extensions = map { $_->NAME } @{ Bugzilla::Extension->load_all() };
+my @static_dirs = qw( data/webdot docs graphs images js skins static );
+foreach my $name (@extensions) {
+ my $dir = File::Spec->catfile('extensions', $name, 'web');
+ push @static_dirs, $dir if -d $dir;
+}
+
+Bugzilla->preload_features();
+
+# Force instantiation of template so Bugzilla::Template::PreloadProvider can do its magic.
+Bugzilla->template;
+
+use Bugzilla::Sentry;
+
+
+my $bugzilla_app = builder {
+ my $static_paths = join '|', map quotemeta, sort {length $b <=> length $a || $a cmp $b } @static_dirs;
+
+ enable 'Log4perl', category => 'Plack';
+
+ enable 'Static',
+ path => sub { s{^/(?:static/v\d+\.\d+/)?($static_paths)/}{$1/}gs },
+ root => Bugzilla::Constants::bz_locations->{cgi_path};
+
+ my @scripts = glob('*.cgi');
+
+ my %mount;
+
+ foreach my $script (@scripts) {
+ my $name = basename($script);
+ $mount{$name} = compile_cgi($script);
+ }
+
+ Bugzilla::Hook::process('psgi_builder', { mount => \%mount });
+
+ foreach my $name ( keys %mount ) {
+ mount "/$name" => $mount{$name};
+ }
+
+ # so mount / => $app will make *all* files redirect to the index.
+ # instead we use an inline middleware to rewrite / to /index.cgi
+ enable sub {
+ my $app = shift;
+ return sub {
+ my $env = shift;
+ $env->{PATH_INFO} = '/index.cgi' if $env->{PATH_INFO} eq '/';
+ return $app->($env);
+ };
+ };
+
+ mount '/robots.txt' => $mount{'robots.cgi'};
+ mount '/rest' => $mount{'rest.cgi'};
+
+};
+
+unless (caller) {
+ require Plack::Runner;
+ my $runner = Plack::Runner->new;
+ $runner->parse_options(@ARGV);
+ $runner->run($bugzilla_app);
+ exit 0;
+}
+
+return $bugzilla_app;
diff --git a/editusers.cgi b/editusers.cgi
index 934e0a4ef..ae1f35835 100755
--- a/editusers.cgi
+++ b/editusers.cgi
@@ -24,14 +24,13 @@ use Bugzilla::Field;
use Bugzilla::Group;
use Bugzilla::Token;
-my $user = Bugzilla->login(LOGIN_REQUIRED);
-
+local our $user = Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
my $template = Bugzilla->template;
my $dbh = Bugzilla->dbh;
my $userid = $user->id;
my $editusers = $user->in_group('editusers');
-local our $vars = {};
+local our $vars = {};
# Reject access if there is no sense in continuing.
$editusers
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
index cce76e268..322d03769 100644
--- a/extensions/BMO/Extension.pm
+++ b/extensions/BMO/Extension.pm
@@ -46,6 +46,7 @@ use Bugzilla::User;
use Bugzilla::UserAgent qw(detect_platform detect_op_sys);
use Bugzilla::User::Setting;
use Bugzilla::Util;
+use Bugzilla::PSGI qw(compile_cgi);
use Date::Parse;
use DateTime;
@@ -1489,6 +1490,28 @@ sub webservice {
$dispatch->{BMO} = "Bugzilla::Extension::BMO::WebService";
}
+sub psgi_builder {
+ my ($self, $args) = @_;
+ my $mount = $args->{mount};
+
+ my $ses_index = Plack::Builder::builder(sub {
+ my $auth_user = Bugzilla->localconfig->{ses_username};
+ my $auth_pass = Bugzilla->localconfig->{ses_password};
+ Plack::Builder::enable("Auth::Basic", authenticator => sub {
+ my ($username, $password, $env) = @_;
+ return ( $auth_user
+ && $auth_pass
+ && $username
+ && $password
+ && $username eq $auth_user
+ && $password eq $auth_pass );
+ });
+ compile_cgi("ses/index.cgi");
+ });
+
+ $mount->{'ses/index.cgi'} = $ses_index;
+}
+
our $search_content_matches;
BEGIN {
$search_content_matches = \&Bugzilla::Search::_content_matches;
diff --git a/extensions/BzAPI/Extension.pm b/extensions/BzAPI/Extension.pm
index bb9805134..1f7cce04a 100644
--- a/extensions/BzAPI/Extension.pm
+++ b/extensions/BzAPI/Extension.pm
@@ -15,6 +15,7 @@ use base qw(Bugzilla::Extension);
use Bugzilla::Extension::BzAPI::Constants;
use Bugzilla::Extension::BzAPI::Util qw(fix_credentials filter_wants_nocache);
+use Bugzilla::PSGI qw(compile_cgi);
use Bugzilla::Error;
use Bugzilla::Util qw(trick_taint datetime_from);
@@ -188,6 +189,14 @@ sub webservice_status_code_map {
$status_code_map->{51} = STATUS_BAD_REQUEST;
}
+sub psgi_builder {
+ my ($self, $args) = @_;
+ my $mount = $args->{mount};
+
+ $mount->{'bzapi'} = compile_cgi('extensions/BzAPI/bin/rest.cgi');
+}
+
+
#####################
# Utility Functions #
#####################
diff --git a/extensions/MyDashboard/web/styles/mydashboard.css b/extensions/MyDashboard/web/styles/mydashboard.css
index 8314755c0..1011a9143 100644
--- a/extensions/MyDashboard/web/styles/mydashboard.css
+++ b/extensions/MyDashboard/web/styles/mydashboard.css
@@ -82,5 +82,6 @@
}
#saved_searches_container li {
- margin: 5px 0;
+ margin: 5px;
+ display: inline;
}
diff --git a/extensions/Push/lib/Logger.pm b/extensions/Push/lib/Logger.pm
index 833cb3b19..7ae96b58a 100644
--- a/extensions/Push/lib/Logger.pm
+++ b/extensions/Push/lib/Logger.pm
@@ -31,11 +31,11 @@ sub debugging {
}
sub _log_it {
- require Apache2::Log;
my ($self, $method, $message) = @_;
return if $method eq 'DEBUG' && !$self->debugging;
chomp $message;
if ($ENV{MOD_PERL}) {
+ require Apache2::Log;
Apache2::ServerRec::warn("Push $method: $message");
} elsif ($ENV{SCRIPT_FILENAME}) {
print STDERR "Push $method: $message\n";
diff --git a/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl b/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl
index a5fc61cea..5ce2efeeb 100644
--- a/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl
+++ b/extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl
@@ -1,4 +1,4 @@
-[% IF column == 'attachment' && request.ispatch %]
+[% IF column == 'attachment' && request.attach_ispatch %]
&nbsp;
<a href="[% Bugzilla.splinter_review_url(request.bug_id, request.attach_id) FILTER none %]">[review]</a>
[% END %]
diff --git a/heartbeat.cgi b/heartbeat.cgi
index 40dc8e79b..917853d2b 100755
--- a/heartbeat.cgi
+++ b/heartbeat.cgi
@@ -28,7 +28,7 @@ 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};
+ die "mod_perl/psgi not configured?" unless BZ_PERSISTENT;
die "missing bmo feature dependencies" unless Bugzilla->has_feature('bmo');
1;
};
diff --git a/mod_perl.pl b/mod_perl.pl
index 09fd80850..af60bb359 100644
--- a/mod_perl.pl
+++ b/mod_perl.pl
@@ -6,12 +6,15 @@
# 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;
+BEGIN { $main::BUGZILLA_PERSISTENT = 1 }
+
# This sets up our libpath without having to specify it in the mod_perl
# configuration.
use File::Basename;
diff --git a/scripts/cereal.pl b/scripts/cereal.pl
new file mode 100755
index 000000000..d5b556451
--- /dev/null
+++ b/scripts/cereal.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+# 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 5.10.1;
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs(File::Spec->catdir(dirname(__FILE__), '..'));
+ lib->import($dir, File::Spec->catdir($dir, 'lib'), File::Spec->catdir($dir, qw(local lib perl5)));
+}
+
+use Bugzilla::DaemonControl qw(catch_signal);
+use Future;
+use IO::Async::Loop;
+use IO::Async::Protocol::LineStream;
+
+$ENV{LOGGING_PORT} //= 5880;
+
+my $loop = IO::Async::Loop->new;
+my $on_stream = sub {
+ my ($stream) = @_;
+ my $protocol = IO::Async::Protocol::LineStream->new(
+ transport => $stream,
+ on_read_line => sub {
+ my ( $self, $line ) = @_;
+ say $line;
+ },
+ );
+ $loop->add($protocol);
+};
+my @signals = qw( TERM INT KILL );
+
+$loop->listen(
+ host => '127.0.0.1',
+ service => $ENV{LOGGING_PORT},
+ socktype => 'stream',
+ on_stream => $on_stream,
+)->get;
+
+exit Future->wait_any(map { catch_signal($_, 0) } @signals)->get; \ No newline at end of file
diff --git a/scripts/migrate-database.pl b/scripts/migrate-database.pl
new file mode 100755
index 000000000..cde7c80c0
--- /dev/null
+++ b/scripts/migrate-database.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+use 5.10.1;
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs(dirname(__FILE__));
+ my $base = File::Spec->catdir($dir, "..");
+ lib->import($base, File::Spec->catdir($base, "lib"), File::Spec->catdir($base, qw(local lib perl5)));
+ chdir $base;
+}
+
+use Bugzilla;
+BEGIN { Bugzilla->extensions }
+
+use Bugzilla::DB;
+use Bugzilla::Install::DB;
+use Bugzilla::Config qw(update_params);
+
+Bugzilla::DB::bz_create_database();
+
+# Clear all keys from Memcached to ensure we see the correct schema.
+Bugzilla->memcached->clear_all();
+
+# now get a handle to the database:
+my $dbh = Bugzilla->dbh;
+# Create the tables, and do any database-specific schema changes.
+$dbh->bz_setup_database();
+# Populate the tables that hold the values for the <select> fields.
+$dbh->bz_populate_enum_tables();
+
+# Using Bugzilla::Field's create() or update() depends on the
+# fielddefs table having a modern definition. So, we have to make
+# these particular schema changes before we make any other schema changes.
+Bugzilla::Install::DB::update_fielddefs_definition();
+
+Bugzilla::Field::populate_field_definitions();
+
+###########################################################################
+# Update the tables to the current definition --TABLE--
+###########################################################################
+
+Bugzilla::Install::DB::update_table_definitions({});
+Bugzilla::Install::init_workflow();
diff --git a/token.cgi b/token.cgi
index 51ed93977..990040050 100755
--- a/token.cgi
+++ b/token.cgi
@@ -23,7 +23,7 @@ use Date::Format;
use Date::Parse;
use JSON qw( decode_json );
-my $dbh = Bugzilla->dbh;
+local our $dbh = Bugzilla->dbh;
local our $cgi = Bugzilla->cgi;
local our $template = Bugzilla->template;
local our $vars = {};
diff --git a/userprefs.cgi b/userprefs.cgi
index e70b9780a..830c49eed 100755
--- a/userprefs.cgi
+++ b/userprefs.cgi
@@ -29,7 +29,7 @@ use DateTime;
use constant SESSION_MAX => 20;
-my $template = Bugzilla->template;
+local our $template = Bugzilla->template;
local our $vars = {};
###############################################################################