Commit 8bbc156c authored by Frédéric Buclin's avatar Frédéric Buclin

Bug 1201113: Support to run Bugzilla as a PSGI application

r=dylan
parent c94abb04
# Don't allow people to retrieve non-cgi executable files or our private data # Don't allow people to retrieve non-cgi executable files or our private data
<FilesMatch (\.pm|\.pl|\.tmpl|localconfig.*|cpanfile)$> <FilesMatch (\.pm|\.pl|\.psgi|\.tmpl|localconfig.*|cpanfile)$>
<IfModule mod_version.c> <IfModule mod_version.c>
<IfVersion < 2.4> <IfVersion < 2.4>
Deny from all Deny from all
......
...@@ -13,8 +13,11 @@ use warnings; ...@@ -13,8 +13,11 @@ use warnings;
# We want any compile errors to get to the browser, if possible. # We want any compile errors to get to the browser, if possible.
BEGIN { BEGIN {
# This makes sure we're in a CGI. # This makes sure we're in a CGI. mod_perl doesn't support Carp
if ($ENV{SERVER_SOFTWARE} && !$ENV{MOD_PERL}) { # and Plack reports errors elsewhere.
# We cannot call i_am_persistent() from here as its module is
# not loaded yet.
if ($ENV{SERVER_SOFTWARE} && !($ENV{MOD_PERL} || $ENV{BZ_PLACK})) {
require CGI::Carp; require CGI::Carp;
CGI::Carp->import('fatalsToBrowser'); CGI::Carp->import('fatalsToBrowser');
} }
...@@ -32,7 +35,7 @@ use Bugzilla::Field; ...@@ -32,7 +35,7 @@ use Bugzilla::Field;
use Bugzilla::Flag; use Bugzilla::Flag;
use Bugzilla::Install::Localconfig qw(read_localconfig); use Bugzilla::Install::Localconfig qw(read_localconfig);
use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES have_vers); use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES have_vers);
use Bugzilla::Install::Util qw(init_console include_languages); use Bugzilla::Install::Util qw(init_console include_languages i_am_persistent);
use Bugzilla::Memcached; use Bugzilla::Memcached;
use Bugzilla::Template; use Bugzilla::Template;
use Bugzilla::Token; use Bugzilla::Token;
...@@ -149,11 +152,16 @@ sub init_page { ...@@ -149,11 +152,16 @@ sub init_page {
{ {
exit; exit;
} }
# Plack requires to exit differently.
return -1 if $ENV{BZ_PLACK};
_shutdown();
}
}
sub _shutdown {
# For security reasons, log out users when Bugzilla is down. # For security reasons, log out users when Bugzilla is down.
# Bugzilla->login() is required to catch the logincookie, if any. # Bugzilla->login() is required to catch the logincookie, if any.
my $user; my $user = eval { Bugzilla->login(LOGIN_OPTIONAL); };
eval { $user = Bugzilla->login(LOGIN_OPTIONAL); };
if ($@) { if ($@) {
# The DB is not accessible. Use the default user object. # The DB is not accessible. Use the default user object.
$user = Bugzilla->user; $user = Bugzilla->user;
...@@ -162,30 +170,28 @@ sub init_page { ...@@ -162,30 +170,28 @@ sub init_page {
my $userid = $user->id; my $userid = $user->id;
Bugzilla->logout(); Bugzilla->logout();
my $template = Bugzilla->template;
my $vars = {};
$vars->{'message'} = 'shutdown';
$vars->{'userid'} = $userid;
# Generate and return a message about the downtime, appropriately # Generate and return a message about the downtime, appropriately
# for if we're a command-line script or a CGI script. # for if we're a command-line script or a CGI script.
my $extension; my $cgi = Bugzilla->cgi;
if (i_am_cgi() && (!Bugzilla->cgi->param('ctype') my $extension = 'txt';
|| Bugzilla->cgi->param('ctype') eq 'html')) {
$extension = 'html';
}
else {
$extension = 'txt';
}
if (i_am_cgi()) { if (i_am_cgi()) {
# Set the HTTP status to 503 when Bugzilla is down to avoid pages # Set the HTTP status to 503 when Bugzilla is down to avoid pages
# being indexed by search engines. # being indexed by search engines.
print Bugzilla->cgi->header(-status => 503, print $cgi->header(-status => 503,
-retry_after => SHUTDOWNHTML_RETRY_AFTER); -retry_after => SHUTDOWNHTML_RETRY_AFTER);
if (!$cgi->param('ctype') || $cgi->param('ctype') eq 'html') {
$extension = 'html';
} }
}
my $template = Bugzilla->template;
my $vars = { message => 'shutdown', userid => $userid };
$template->process("global/message.$extension.tmpl", $vars) $template->process("global/message.$extension.tmpl", $vars)
|| ThrowTemplateError($template->error); or ThrowTemplateError($template->error);
exit; exit;
}
} }
##################################################################### #####################################################################
...@@ -714,11 +720,13 @@ sub _cleanup { ...@@ -714,11 +720,13 @@ sub _cleanup {
} }
sub END { sub END {
# Bugzilla.pm cannot compile in mod_perl.pl if this runs. # This is managed in mod_perl.pl and app.psgi when running
_cleanup() unless $ENV{MOD_PERL}; # in a persistent environment.
_cleanup() unless i_am_persistent();
} }
init_page() if !$ENV{MOD_PERL}; # Also managed in mod_perl.pl and app.psgi.
init_page() unless i_am_persistent();
1; 1;
......
...@@ -66,7 +66,7 @@ sub new { ...@@ -66,7 +66,7 @@ sub new {
# else we will be redirected outside Bugzilla. # else we will be redirected outside Bugzilla.
my $script_name = $self->script_name; my $script_name = $self->script_name;
$path_info =~ s/^\Q$script_name\E//; $path_info =~ s/^\Q$script_name\E//;
if ($path_info) { if ($script_name && $path_info) {
print $self->redirect($self->url(-path => 0, -query => 1)); print $self->redirect($self->url(-path => 0, -query => 1));
} }
} }
...@@ -283,7 +283,7 @@ sub close_standby_message { ...@@ -283,7 +283,7 @@ sub close_standby_message {
print $self->multipart_end(); print $self->multipart_end();
print $self->multipart_start(-type => $contenttype); print $self->multipart_start(-type => $contenttype);
} }
else { elsif (!$self->{_header_done}) {
print $self->header($contenttype); print $self->header($contenttype);
} }
} }
...@@ -356,6 +356,7 @@ sub header { ...@@ -356,6 +356,7 @@ sub header {
Bugzilla::Hook::process('cgi_headers', Bugzilla::Hook::process('cgi_headers',
{ cgi => $self, headers => \%headers } { cgi => $self, headers => \%headers }
); );
$self->{_header_done} = 1;
return $self->SUPER::header(%headers) || ""; return $self->SUPER::header(%headers) || "";
} }
......
...@@ -16,6 +16,7 @@ use autodie qw(:default); ...@@ -16,6 +16,7 @@ use autodie qw(:default);
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::Hook; use Bugzilla::Hook;
use Bugzilla::Install::Util qw(i_am_persistent);
use Bugzilla::Util qw(trick_taint); use Bugzilla::Util qw(trick_taint);
use JSON::XS; use JSON::XS;
...@@ -324,8 +325,10 @@ sub read_param_file { ...@@ -324,8 +325,10 @@ sub read_param_file {
# might not have thrown an error. Bugzilla::CGI->new # might not have thrown an error. Bugzilla::CGI->new
# hasn't even been called yet, so we manually use CGI::Carp here # hasn't even been called yet, so we manually use CGI::Carp here
# so that the user sees the error. # so that the user sees the error.
unless (i_am_persistent()) {
require CGI::Carp; require CGI::Carp;
CGI::Carp->import('fatalsToBrowser'); CGI::Carp->import('fatalsToBrowser');
}
die "The $file file does not exist." die "The $file file does not exist."
. ' You probably need to run checksetup.pl.', . ' You probably need to run checksetup.pl.',
} }
......
...@@ -28,8 +28,9 @@ use Date::Format; ...@@ -28,8 +28,9 @@ use Date::Format;
sub _in_eval { sub _in_eval {
my $in_eval = 0; my $in_eval = 0;
for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) { for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
last if $sub =~ /^ModPerl/; last if $sub =~ /^(?:ModPerl|Plack|CGI::Compile)/;
$in_eval = 1 if $sub =~ /^\(eval\)/; # An eval followed by CGI::Compile is not a "real" eval.
$in_eval = 1 if $sub =~ /^\(eval\)/ && (caller($stack + 1))[3] !~ /^CGI::Compile/;
} }
return $in_eval; return $in_eval;
} }
......
...@@ -167,6 +167,7 @@ sub FILESYSTEM { ...@@ -167,6 +167,7 @@ sub FILESYSTEM {
'install-module.pl' => { perms => OWNER_EXECUTE }, 'install-module.pl' => { perms => OWNER_EXECUTE },
'clean-bug-user-last-visit.pl' => { perms => WS_EXECUTE }, 'clean-bug-user-last-visit.pl' => { perms => WS_EXECUTE },
'app.psgi' => { perms => CGI_READ },
'Bugzilla.pm' => { perms => CGI_READ }, 'Bugzilla.pm' => { perms => CGI_READ },
"$localconfig*" => { perms => CGI_READ }, "$localconfig*" => { perms => CGI_READ },
'bugzilla.dtd' => { perms => WS_SERVE }, 'bugzilla.dtd' => { perms => WS_SERVE },
......
...@@ -313,6 +313,26 @@ sub OPTIONAL_MODULES { ...@@ -313,6 +313,26 @@ sub OPTIONAL_MODULES {
feature => ['jsonrpc'], feature => ['jsonrpc'],
}, },
{ {
package => 'Plack',
module => 'Plack',
# 1.0031 contains a security fix which would affect us.
# It also fixes warnings thrown in Perl 5.20 and newer.
version => 1.0031,
feature => ['psgi'],
},
{
package => 'CGI-Compile',
module => 'CGI::Compile',
version => 0,
feature => ['psgi'],
},
{
package => 'CGI-Emulate-PSGI',
module => 'CGI::Emulate::PSGI',
version => 0,
feature => ['psgi'],
},
{
package => 'Test-Taint', package => 'Test-Taint',
module => 'Test::Taint', module => 'Test::Taint',
# 1.06 no longer throws warnings with Perl 5.10+. # 1.06 no longer throws warnings with Perl 5.10+.
...@@ -474,6 +494,7 @@ use constant FEATURE_FILES => ( ...@@ -474,6 +494,7 @@ use constant FEATURE_FILES => (
'Bugzilla/WebService.pm', 'Bugzilla/WebService/*.pm'], 'Bugzilla/WebService.pm', 'Bugzilla/WebService/*.pm'],
rest => ['Bugzilla/WebService/Server/REST.pm', 'rest.cgi', rest => ['Bugzilla/WebService/Server/REST.pm', 'rest.cgi',
'Bugzilla/WebService/Server/REST/Resources/*.pm'], 'Bugzilla/WebService/Server/REST/Resources/*.pm'],
psgi => ['app.psgi'],
moving => ['importxml.pl'], moving => ['importxml.pl'],
auth_ldap => ['Bugzilla/Auth/Verify/LDAP.pm'], auth_ldap => ['Bugzilla/Auth/Verify/LDAP.pm'],
auth_radius => ['Bugzilla/Auth/Verify/RADIUS.pm'], auth_radius => ['Bugzilla/Auth/Verify/RADIUS.pm'],
......
...@@ -34,6 +34,7 @@ our @EXPORT_OK = qw( ...@@ -34,6 +34,7 @@ our @EXPORT_OK = qw(
extension_requirement_packages extension_requirement_packages
extension_template_directory extension_template_directory
extension_web_directory extension_web_directory
i_am_persistent
indicate_progress indicate_progress
install_string install_string
include_languages include_languages
...@@ -83,6 +84,10 @@ sub get_version_and_os { ...@@ -83,6 +84,10 @@ sub get_version_and_os {
os_ver => $os_details[3] }; os_ver => $os_details[3] };
} }
sub i_am_persistent {
return ($ENV{MOD_PERL} || $ENV{BZ_PLACK}) ? 1 : 0;
}
sub _extension_paths { sub _extension_paths {
my $dir = bz_locations()->{'extensionsdir'}; my $dir = bz_locations()->{'extensionsdir'};
my @extension_items = glob("$dir/*"); my @extension_items = glob("$dir/*");
...@@ -711,6 +716,11 @@ binary, if the binary is in the C<PATH>. ...@@ -711,6 +716,11 @@ binary, if the binary is in the C<PATH>.
Returns a hash containing information about what version of Bugzilla we're Returns a hash containing information about what version of Bugzilla we're
running, what perl version we're using, and what OS we're running on. running, what perl version we're using, and what OS we're running on.
=item C<i_am_persistent>
Returns true if Bugzilla is running in a persistent environment, such as
mod_perl or PSGI. Returns false if running in mod_cgi mode.
=item C<get_console_locale> =item C<get_console_locale>
Returns the language to use based on the LC_CTYPE value returned by the OS. Returns the language to use based on the LC_CTYPE value returned by the OS.
......
...@@ -17,7 +17,7 @@ use Bugzilla::WebService::Constants; ...@@ -17,7 +17,7 @@ use Bugzilla::WebService::Constants;
use Bugzilla::Hook; use Bugzilla::Hook;
use Bugzilla::Install::Requirements; use Bugzilla::Install::Requirements;
use Bugzilla::Install::Util qw(install_string template_include_path use Bugzilla::Install::Util qw(install_string template_include_path
include_languages); include_languages i_am_persistent);
use Bugzilla::Classification; use Bugzilla::Classification;
use Bugzilla::Keyword; use Bugzilla::Keyword;
use Bugzilla::Util; use Bugzilla::Util;
...@@ -740,7 +740,7 @@ sub create { ...@@ -740,7 +740,7 @@ sub create {
# if a packager has modified bz_locations() to contain absolute # if a packager has modified bz_locations() to contain absolute
# paths. # paths.
ABSOLUTE => 1, ABSOLUTE => 1,
RELATIVE => $ENV{MOD_PERL} ? 0 : 1, RELATIVE => i_am_persistent() ? 0 : 1,
COMPILE_DIR => bz_locations()->{'template_cache'}, COMPILE_DIR => bz_locations()->{'template_cache'},
......
#!/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 lib dirname(__FILE__);
use Bugzilla::Constants ();
use lib Bugzilla::Constants::bz_locations()->{ext_libpath};
use Plack;
use Plack::Builder;
use Plack::App::URLMap;
use Plack::App::WrapCGI;
use Plack::Response;
use constant STATIC => qw(
data/assets
data/webdot
docs
extensions/[^/]+/web
graphs
images
js
skins
);
builder {
my $static_paths = join('|', STATIC);
enable 'Static',
path => qr{^/($static_paths)/},
root => Bugzilla::Constants::bz_locations->{cgi_path};
$ENV{BZ_PLACK} = 'Plack/' . Plack->VERSION;
my $map = Plack::App::URLMap->new;
my @cgis = glob('*.cgi');
my $shutdown_app = Plack::App::WrapCGI->new(script => 'shutdown.cgi')->to_app;
foreach my $cgi_script (@cgis) {
my $app = eval { Plack::App::WrapCGI->new(script => $cgi_script)->to_app };
# Some CGI scripts won't compile if not all optional Perl modules are
# installed. That's expected.
if ($@) {
warn "Cannot compile $cgi_script. Skipping!\n";
next;
}
my $wrapper = sub {
my $ret = Bugzilla::init_page();
my $res = ($ret eq '-1' && $cgi_script ne 'editparams.cgi') ? $shutdown_app->(@_) : $app->(@_);
Bugzilla::_cleanup();
return $res;
};
my $base_name = basename($cgi_script);
$map->map('/' => $wrapper) if $cgi_script eq 'index.cgi';
$map->map('/rest' => $wrapper) if $cgi_script eq 'rest.cgi';
$map->map("/$base_name" => $wrapper);
}
my $app = $map->to_app;
};
...@@ -38,7 +38,6 @@ sub LoadTemplate { ...@@ -38,7 +38,6 @@ sub LoadTemplate {
$action =~ /(\w+)/; $action =~ /(\w+)/;
$action = $1; $action = $1;
print $cgi->header();
$template->process("admin/classifications/$action.html.tmpl", $vars) $template->process("admin/classifications/$action.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
......
...@@ -136,7 +136,6 @@ unless ($action) { ...@@ -136,7 +136,6 @@ unless ($action) {
my @groups = Bugzilla::Group->get_all; my @groups = Bugzilla::Group->get_all;
$vars->{'groups'} = \@groups; $vars->{'groups'} = \@groups;
print $cgi->header();
$template->process("admin/groups/list.html.tmpl", $vars) $template->process("admin/groups/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -157,10 +156,8 @@ if ($action eq 'changeform') { ...@@ -157,10 +156,8 @@ if ($action eq 'changeform') {
$vars->{'group'} = $group; $vars->{'group'} = $group;
$vars->{'token'} = issue_session_token('edit_group'); $vars->{'token'} = issue_session_token('edit_group');
print $cgi->header();
$template->process("admin/groups/edit.html.tmpl", $vars) $template->process("admin/groups/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
...@@ -172,10 +169,9 @@ if ($action eq 'changeform') { ...@@ -172,10 +169,9 @@ if ($action eq 'changeform') {
if ($action eq 'add') { if ($action eq 'add') {
$vars->{'token'} = issue_session_token('add_group'); $vars->{'token'} = issue_session_token('add_group');
print $cgi->header();
$template->process("admin/groups/create.html.tmpl", $vars) $template->process("admin/groups/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
...@@ -204,7 +200,6 @@ if ($action eq 'new') { ...@@ -204,7 +200,6 @@ if ($action eq 'new') {
get_current_and_available($group, $vars); get_current_and_available($group, $vars);
$vars->{'token'} = issue_session_token('edit_group'); $vars->{'token'} = issue_session_token('edit_group');
print $cgi->header();
$template->process("admin/groups/edit.html.tmpl", $vars) $template->process("admin/groups/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -228,10 +223,8 @@ if ($action eq 'del') { ...@@ -228,10 +223,8 @@ if ($action eq 'del') {
$vars->{'group'} = $group; $vars->{'group'} = $group;
$vars->{'token'} = issue_session_token('delete_group'); $vars->{'token'} = issue_session_token('delete_group');
print $cgi->header();
$template->process("admin/groups/delete.html.tmpl", $vars) $template->process("admin/groups/delete.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
...@@ -255,7 +248,6 @@ if ($action eq 'delete') { ...@@ -255,7 +248,6 @@ if ($action eq 'delete') {
$vars->{'message'} = 'group_deleted'; $vars->{'message'} = 'group_deleted';
$vars->{'groups'} = [Bugzilla::Group->get_all]; $vars->{'groups'} = [Bugzilla::Group->get_all];
print $cgi->header();
$template->process("admin/groups/list.html.tmpl", $vars) $template->process("admin/groups/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -277,7 +269,6 @@ if ($action eq 'postchanges') { ...@@ -277,7 +269,6 @@ if ($action eq 'postchanges') {
$vars->{'changes'} = $changes; $vars->{'changes'} = $changes;
$vars->{'token'} = issue_session_token('edit_group'); $vars->{'token'} = issue_session_token('edit_group');
print $cgi->header();
$template->process("admin/groups/edit.html.tmpl", $vars) $template->process("admin/groups/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -288,6 +279,7 @@ if ($action eq 'confirm_remove') { ...@@ -288,6 +279,7 @@ if ($action eq 'confirm_remove') {
$vars->{'group'} = $group; $vars->{'group'} = $group;
$vars->{'regexp'} = CheckGroupRegexp($cgi->param('regexp')); $vars->{'regexp'} = CheckGroupRegexp($cgi->param('regexp'));
$vars->{'token'} = issue_session_token('remove_group_members'); $vars->{'token'} = issue_session_token('remove_group_members');
$template->process('admin/groups/confirm-remove.html.tmpl', $vars) $template->process('admin/groups/confirm-remove.html.tmpl', $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -326,10 +318,8 @@ if ($action eq 'remove_regexp') { ...@@ -326,10 +318,8 @@ if ($action eq 'remove_regexp') {
$vars->{'group'} = $group->name; $vars->{'group'} = $group->name;
$vars->{'groups'} = [Bugzilla::Group->get_all]; $vars->{'groups'} = [Bugzilla::Group->get_all];
print $cgi->header();
$template->process("admin/groups/list.html.tmpl", $vars) $template->process("admin/groups/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
......
...@@ -24,10 +24,6 @@ my $dbh = Bugzilla->dbh; ...@@ -24,10 +24,6 @@ my $dbh = Bugzilla->dbh;
my $template = Bugzilla->template; my $template = Bugzilla->template;
my $vars = {}; my $vars = {};
#
# Preliminary checks:
#
my $user = Bugzilla->login(LOGIN_REQUIRED); my $user = Bugzilla->login(LOGIN_REQUIRED);
print $cgi->header(); print $cgi->header();
...@@ -47,22 +43,16 @@ $vars->{'action'} = $action; ...@@ -47,22 +43,16 @@ $vars->{'action'} = $action;
if ($action eq "") { if ($action eq "") {
$vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count(); $vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count();
print $cgi->header();
$template->process("admin/keywords/list.html.tmpl", $vars) $template->process("admin/keywords/list.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
if ($action eq 'add') { if ($action eq 'add') {
$vars->{'token'} = issue_session_token('add_keyword'); $vars->{'token'} = issue_session_token('add_keyword');
print $cgi->header();
$template->process("admin/keywords/create.html.tmpl", $vars) $template->process("admin/keywords/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
...@@ -79,8 +69,6 @@ if ($action eq 'new') { ...@@ -79,8 +69,6 @@ if ($action eq 'new') {
delete_token($token); delete_token($token);
print $cgi->header();
$vars->{'message'} = 'keyword_created'; $vars->{'message'} = 'keyword_created';
$vars->{'name'} = $keyword->name; $vars->{'name'} = $keyword->name;
$vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count(); $vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count();
...@@ -90,7 +78,6 @@ if ($action eq 'new') { ...@@ -90,7 +78,6 @@ if ($action eq 'new') {
exit; exit;
} }
# #
# action='edit' -> present the edit keywords from # action='edit' -> present the edit keywords from
# #
...@@ -104,13 +91,11 @@ if ($action eq 'edit') { ...@@ -104,13 +91,11 @@ if ($action eq 'edit') {
$vars->{'keyword'} = $keyword; $vars->{'keyword'} = $keyword;
$vars->{'token'} = issue_session_token('edit_keyword'); $vars->{'token'} = issue_session_token('edit_keyword');
print $cgi->header();
$template->process("admin/keywords/edit.html.tmpl", $vars) $template->process("admin/keywords/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
} }
# #
# action='update' -> update the keyword # action='update' -> update the keyword
# #
...@@ -129,8 +114,6 @@ if ($action eq 'update') { ...@@ -129,8 +114,6 @@ if ($action eq 'update') {
delete_token($token); delete_token($token);
print $cgi->header();
$vars->{'message'} = 'keyword_updated'; $vars->{'message'} = 'keyword_updated';
$vars->{'keyword'} = $keyword; $vars->{'keyword'} = $keyword;
$vars->{'changes'} = $changes; $vars->{'changes'} = $changes;
...@@ -148,7 +131,6 @@ if ($action eq 'del') { ...@@ -148,7 +131,6 @@ if ($action eq 'del') {
$vars->{'keyword'} = $keyword; $vars->{'keyword'} = $keyword;
$vars->{'token'} = issue_session_token('delete_keyword'); $vars->{'token'} = issue_session_token('delete_keyword');
print $cgi->header();
$template->process("admin/keywords/confirm-delete.html.tmpl", $vars) $template->process("admin/keywords/confirm-delete.html.tmpl", $vars)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
exit; exit;
...@@ -163,8 +145,6 @@ if ($action eq 'delete') { ...@@ -163,8 +145,6 @@ if ($action eq 'delete') {
delete_token($token); delete_token($token);
print $cgi->header();
$vars->{'message'} = 'keyword_deleted'; $vars->{'message'} = 'keyword_deleted';
$vars->{'keyword'} = $keyword; $vars->{'keyword'} = $keyword;
$vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count(); $vars->{'keywords'} = Bugzilla::Keyword->get_all_with_bug_count();
......
#!/usr/bin/perl -T
# 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 lib qw(. lib);
use Bugzilla;
Bugzilla::_shutdown();
...@@ -40,7 +40,7 @@ foreach my $file (@testitems) { ...@@ -40,7 +40,7 @@ foreach my $file (@testitems) {
ok(1,"$file does not have a shebang"); ok(1,"$file does not have a shebang");
} else { } else {
my $flags; my $flags;
if (!defined $ext || $ext eq "pl") { if (!defined $ext || $ext eq 'pl' || $ext eq 'psgi') {
# standalone programs aren't taint checked yet # standalone programs aren't taint checked yet
if (grep { $file eq $_ } @require_taint) { if (grep { $file eq $_ } @require_taint) {
$flags = 'T'; $flags = 'T';
......
...@@ -34,7 +34,7 @@ sub isTestingFile { ...@@ -34,7 +34,7 @@ sub isTestingFile {
my ($file) = @_; my ($file) = @_;
my $exclude; my $exclude;
if ($file =~ /\.cgi$|\.pl$|\.pm$/) { if ($file =~ /\.psgi$|\.cgi$|\.pl$|\.pm$/) {
return 1; return 1;
} }
my $additional; my $additional;
......
...@@ -103,6 +103,7 @@ END ...@@ -103,6 +103,7 @@ END
feature_mod_perl => 'mod_perl', feature_mod_perl => 'mod_perl',
feature_moving => 'Move Bugs Between Installations', feature_moving => 'Move Bugs Between Installations',
feature_patch_viewer => 'Patch Viewer', feature_patch_viewer => 'Patch Viewer',
feature_psgi => 'PSGI Support',
feature_rest => 'REST Interface', feature_rest => 'REST Interface',
feature_smtp_auth => 'SMTP Authentication', feature_smtp_auth => 'SMTP Authentication',
feature_smtp_ssl => 'SSL Support for SMTP', feature_smtp_ssl => 'SSL Support for SMTP',
......
...@@ -15,5 +15,6 @@ use strict; ...@@ -15,5 +15,6 @@ use strict;
use warnings; use warnings;
say "content-type:text/plain\n"; say "content-type:text/plain\n";
say "OK " . ($::ENV{MOD_PERL} || "mod_cgi");
exit; print 'OK ';
say $ENV{BZ_PLACK} || $ENV{MOD_PERL} || 'mod_cgi';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment