diff options
-rw-r--r-- | Bugzilla.pm | 20 | ||||
-rw-r--r-- | Bugzilla/CGI.pm | 4 | ||||
-rw-r--r-- | Bugzilla/Constants.pm | 4 | ||||
-rw-r--r-- | Bugzilla/DaemonControl.pm | 34 | ||||
-rw-r--r-- | Bugzilla/Logging.pm | 2 | ||||
-rw-r--r-- | Bugzilla/PSGI.pm | 42 | ||||
-rw-r--r-- | Bugzilla/Template.pm | 4 | ||||
-rwxr-xr-x | Makefile.PL | 34 | ||||
-rw-r--r-- | app.psgi | 115 | ||||
-rwxr-xr-x | editusers.cgi | 5 | ||||
-rw-r--r-- | extensions/BMO/Extension.pm | 23 | ||||
-rw-r--r-- | extensions/BzAPI/Extension.pm | 9 | ||||
-rw-r--r-- | extensions/MyDashboard/web/styles/mydashboard.css | 3 | ||||
-rw-r--r-- | extensions/Push/lib/Logger.pm | 2 | ||||
-rw-r--r-- | extensions/Splinter/template/en/default/hook/request/queue-after_column.html.tmpl | 2 | ||||
-rwxr-xr-x | heartbeat.cgi | 2 | ||||
-rw-r--r-- | mod_perl.pl | 3 | ||||
-rwxr-xr-x | scripts/cereal.pl | 49 | ||||
-rwxr-xr-x | scripts/migrate-database.pl | 47 | ||||
-rwxr-xr-x | token.cgi | 2 | ||||
-rwxr-xr-x | userprefs.cgi | 2 |
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 %] <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(); @@ -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 = {}; ############################################################################### |