summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml289
-rw-r--r--.gitignore2
-rw-r--r--.htaccess12
-rw-r--r--Bugzilla.pm47
-rw-r--r--Bugzilla/CGI.pm2
-rw-r--r--Bugzilla/Config/BugFields.pm2
-rw-r--r--Bugzilla/Config/General.pm8
-rw-r--r--Bugzilla/Constants.pm4
-rw-r--r--Bugzilla/DB.pm14
-rw-r--r--Bugzilla/Elastic/Role/HasClient.pm2
-rw-r--r--Bugzilla/Group.pm29
-rw-r--r--Bugzilla/Install.pm42
-rw-r--r--Bugzilla/Install/DB.pm11
-rw-r--r--Bugzilla/Install/Filesystem.pm83
-rw-r--r--Bugzilla/Install/Localconfig.pm7
-rw-r--r--Bugzilla/PSGI.pm42
-rw-r--r--Bugzilla/Quantum/Plugin/Hostage.pm32
-rw-r--r--Bugzilla/Quantum/Template.pm39
-rw-r--r--Bugzilla/Search.pm26
-rw-r--r--Bugzilla/Template.pm2
-rw-r--r--Dockerfile37
-rwxr-xr-xMakefile.PL3
-rw-r--r--app.psgi115
-rwxr-xr-xbuglist.cgi2
-rw-r--r--docs/en/rst/integrating/templates.rst2
-rwxr-xr-xeditusers.cgi3
-rwxr-xr-xenter_bug.cgi11
-rw-r--r--errors/401.html40
-rw-r--r--errors/403.html37
-rw-r--r--errors/404.html37
-rw-r--r--errors/500.html37
-rw-r--r--extensions/AntiSpam/lib/Config.pm2
-rw-r--r--extensions/BMO/Extension.pm33
-rwxr-xr-xextensions/BMO/bin/bug_1093952.pl2
-rwxr-xr-xextensions/BMO/bin/bug_1141452.pl2
-rwxr-xr-xextensions/BMO/bin/migrate-github-pull-requests.pl2
-rw-r--r--extensions/BMO/disabled0
-rw-r--r--extensions/BMO/lib/WebService.pm2
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/bug/create/user-message.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/pages/bug-writing.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/pages/etiquette.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/pages/group_admins.html.tmpl2
-rw-r--r--extensions/BugModal/Extension.pm10
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl2
-rw-r--r--extensions/BzAPI/Extension.pm9
-rw-r--r--extensions/ComponentWatching/Extension.pm6
-rw-r--r--extensions/ContributorEngagement/Extension.pm5
-rw-r--r--extensions/EditComments/Extension.pm4
-rw-r--r--extensions/EditComments/lib/WebService.pm2
-rw-r--r--extensions/Ember/lib/WebService.pm2
-rw-r--r--extensions/FlagTypeComment/Extension.pm19
-rw-r--r--extensions/GuidedBugEntry/disabled0
-rw-r--r--extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl2
-rw-r--r--extensions/MyDashboard/lib/WebService.pm2
-rw-r--r--extensions/PhabBugz/disabled0
-rw-r--r--extensions/PhabBugz/lib/Util.pm2
-rw-r--r--extensions/Push/Config.pm6
-rw-r--r--extensions/Push/disabled0
-rw-r--r--extensions/Push/lib/Connector/TCL.pm353
-rw-r--r--extensions/RestrictComments/Extension.pm4
-rw-r--r--extensions/Review/Extension.pm8
-rwxr-xr-xextensions/Review/bin/migrate_mentor_from_whiteboard.pl2
-rw-r--r--extensions/Review/lib/WebService.pm2
-rw-r--r--extensions/SecureMail/Extension.pm5
-rw-r--r--extensions/TagNewUsers/Extension.pm15
-rwxr-xr-xextensions/TrackingFlags/bin/bug_825946.pl2
-rwxr-xr-xextensions/TrackingFlags/bin/bulk_flag_clear.pl2
-rw-r--r--extensions/TrackingFlags/disabled0
-rw-r--r--extensions/UserProfile/Extension.pm4
-rwxr-xr-xheartbeat.cgi2
-rw-r--r--js/instant-search.js4
-rwxr-xr-xscripts/eject-users-from-groups.pl2
-rwxr-xr-xscripts/entrypoint.pl18
-rwxr-xr-xscripts/generate_bmo_data.pl6
-rwxr-xr-xscripts/move_os.pl2
-rwxr-xr-xscripts/movebugs.pl6
-rwxr-xr-xscripts/nagios_blocker_checker.pl2
-rwxr-xr-xscripts/remove_idle_group_members.pl2
-rwxr-xr-xscripts/reset_default_user.pl2
-rwxr-xr-xscripts/rewrite2mojo.pl70
-rw-r--r--t/bmo/comments.t4
-rw-r--r--t/docker.t4
-rw-r--r--template/en/default/account/prefs/account.html.tmpl2
-rw-r--r--template/en/default/attachment/create.html.tmpl4
-rw-r--r--template/en/default/bug/create/user-message.html.tmpl2
-rw-r--r--template/en/default/bug/new_bug.html.tmpl6
-rw-r--r--template/en/default/global/variables.none.tmpl4
-rw-r--r--template/en/default/index.html.tmpl2
-rw-r--r--template/en/default/list/edit-multiple.html.tmpl1
-rw-r--r--template/en/default/list/table.html.tmpl8
-rw-r--r--template/en/default/search/search-google.html.tmpl2
-rw-r--r--template/en/default/search/search-instant.html.tmpl8
-rwxr-xr-xvotes.cgi3
96 files changed, 678 insertions, 1032 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
deleted file mode 100644
index 44d196efe..000000000
--- a/.circleci/config.yml
+++ /dev/null
@@ -1,289 +0,0 @@
-# References:
-# 1. https://circleci.com/blog/how-to-build-a-docker-image-on-circleci-2-0/
-# 2. https://circleci.com/docs/2.0/building-docker-images/
-#
-
-version: 2
-
-defaults:
- bmo_slim_image: &bmo_slim_image
- image: mozillabteam/bmo-slim:20180801.2
- user: app
-
- mysql_image: &mysql_image
- image: mozillabteam/bmo-mysql:5.6
-
- store_log: &store_log
- store_artifacts:
- path: /app/bugzilla.log
- destination: bugzilla.log
-
- main_filters: &main_filters
- branches:
- ignore:
- - /^(?:release|test)-20\d\d\d\d\d\d\.\d+/
- - /\//
- - production
-
- bmo_env: &bmo_env
- PORT: 8000
- LOGGING_PORT: 5880
- LOCALCONFIG_ENV: 1
- LOG4PERL_CONFIG_FILE: log4perl-test.conf
- BMO_db_user: bugs
- BMO_db_host: 127.0.0.1
- BMO_db_pass: bugs
- BMO_db_name: bugs
- BMO_memcached_servers: localhost:11211
- BMO_memcached_namespace: "bugzilla:"
- BMO_urlbase: AUTOMATIC
-
- mysql_env: &mysql_env
- MYSQL_DATABASE: bugs
- MYSQL_USER: bugs
- MYSQL_PASSWORD: bugs
- MYSQL_ALLOW_EMPTY_PASSWORD: 1
-
- docker_oldtests: &docker_oldtests
- - <<: *bmo_slim_image
- environment:
- <<: *bmo_env
- BZ_QA_CONF_FILE: /app/.circleci/selenium_test.conf
- BZ_QA_ANSWERS_FILE: /app/.circleci/checksetup_answers.legacy.txt
- BZ_QA_LEGACY_MODE: 1
- - <<: *mysql_image
- environment: *mysql_env
- - image: selenium/standalone-firefox:2.53.1
- - image: memcached:latest
-
- default_qa_setup: &default_qa_setup
- run:
- name: default qa setup
- command: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- mv /opt/bmo/local /app/local
- perl -MSys::Hostname -i -pE 's/bmo.test/hostname() . ":$ENV{PORT}"/ges' $BZ_QA_CONF_FILE
- perl checksetup.pl --no-database --default-localconfig
- mkdir artifacts
-
-jobs:
- build_info:
- parallelism: 1
- working_directory: /app
- docker:
- - <<: *bmo_slim_image
- environment:
- <<: *bmo_env
- steps:
- - checkout
- - run:
- name: build push data
- command: |
- mv /opt/bmo/local /app/local
- perl Makefile.PL
- perl -I/app -I/app/local/lib/perl5 -MBugzilla -e 1
- perl checksetup.pl --no-database --no-templates --no-permissions
- perl scripts/build-bmo-push-data.pl
- - run:
- name: only publish if tag exists
- command: |
- tag="$(cat build_info/tag.txt)"
- git fetch --tags
- if git tag | fgrep -q "$tag"; then
- echo "tag $tag exists!"
- else
- echo "tag $tag does not exist"
- echo yes > build_info/publish.txt
- fi
- - run:
- name: check if only version changed
- command: |
- if git diff 'HEAD~..HEAD' --name-only | grep -qv '^Bugzilla.pm'; then
- echo "more files than just Bugzilla.pm changed."
- exit 0
- fi
- if git diff 'HEAD~..HEAD' |grep '^[+-][^+-]' | grep -qv '^[+-]our $VERSION'; then
- echo "Something other than the version number changed."
- exit 0
- fi
- if [[ "$CIRCLE_BRANCH" == "master" ]]; then
- echo "Can't cut corners on the master branch"
- exit 0
- fi
- echo yes > build_info/only_version_changed.txt
- - persist_to_workspace:
- root: /app/build_info
- paths: ["*.txt"]
- - store_artifacts:
- path: /app/build_info
- - *store_log
-
- build:
- working_directory: /app
- docker:
- - image: docker:17.06.1-ce
- steps:
- - setup_remote_docker
- - run:
- name: install git and ssh
- command: apk update && apk add git openssh-client
- - checkout
- - run: |
- docker build \
- --build-arg CI="$CI" \
- --build-arg CIRCLE_SHA1="$CIRCLE_SHA1" \
- --build-arg CIRCLE_BUILD_URL="$CIRCLE_BUILD_URL" \
- -t bmo .
- - attach_workspace:
- at: /app/build_info
- - run: "docker run --name bmo --entrypoint true bmo"
- - run: "docker cp bmo:/app/version.json build_info/version.json"
- - store_artifacts:
- path: /app/build_info
- - *store_log
- - deploy:
- command: |
- TAG="$(cat /app/build_info/tag.txt)"
- [[ "$CIRCLE_BRANCH" == "master" ]] || exit 0
- [[ -n "$DOCKERHUB_REPO" && -n "$DOCKER_USER" && -n "$DOCKER_PASS" ]] || exit 0
- [[ -n "$GITHUB_PERSONAL_TOKEN" ]] || exit 0
- docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
- if [[ -n "$TAG" && -f build_info/publish.txt ]]; then
- git config credential.helper "cache --timeout 120"
- git config user.email "$GITHUB_EMAIL"
- git config user.name "$GITHUB_NAME"
- git tag $TAG
- git push https://${GITHUB_PERSONAL_TOKEN}:x-oauth-basic@github.com/$GITHUB_REPO.git $TAG
- docker tag bmo "$DOCKERHUB_REPO:$TAG"
- docker push "$DOCKERHUB_REPO:$TAG"
- fi
- docker tag bmo "$DOCKERHUB_REPO:latest"
- docker push "$DOCKERHUB_REPO:latest"
-
- test_sanity:
- parallelism: 1
- working_directory: /app
- docker:
- - <<: *bmo_slim_image
- environment: *bmo_env
- steps:
- - checkout
- - attach_workspace:
- at: /app/build_info
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- mv /opt/bmo/local /app/local
- mkdir artifacts
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- perl -I/app -I/app/local/lib/perl5 -c -E 'use Bugzilla; BEGIN { Bugzilla->extensions }'
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- perl Makefile.PL
- - run:
- name: run sanity tests
- command: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl prove -qf $(circleci tests glob 't/*.t' | circleci tests split) | tee artifacts/$CIRCLE_JOB.txt
- - store_artifacts:
- path: /app/artifacts
- - *store_log
-
- test_webservices:
- parallelism: 1
- working_directory: /app
- docker: *docker_oldtests
- steps:
- - checkout
- - attach_workspace:
- at: /app/build_info
- - *default_qa_setup
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl load_test_data
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl test_webservices | tee artifacts/$CIRCLE_JOB.txt
- - store_artifacts:
- path: /app/artifacts
- - *store_log
-
- test_selenium:
- parallelism: 1
- working_directory: /app
- docker: *docker_oldtests
- steps:
- - checkout
- - attach_workspace:
- at: /app/build_info
- - *default_qa_setup
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl load_test_data --legacy
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl test_selenium | tee artifacts/$CIRCLE_JOB.txt
- - store_artifacts:
- path: /app/artifacts
- - *store_log
-
- test_bmo:
- parallelism: 1
- working_directory: /app
- docker:
- - <<: *bmo_slim_image
- environment:
- <<: *bmo_env
- BZ_QA_ANSWERS_FILE: /app/.circleci/checksetup_answers.txt
- TWD_HOST: localhost
- TWD_PORT: 4444
- TWD_BROWSER: firefox
- - <<: *mysql_image
- environment: *mysql_env
- - image: memcached:latest
- - image: selenium/standalone-firefox:2.53.1
- steps:
- - checkout
- - attach_workspace:
- at: /app/build_info
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- mv /opt/bmo/local /app/local
- perl checksetup.pl --no-database
- /app/scripts/entrypoint.pl load_test_data
- mkdir artifacts
- - run: |
- [[ -f build_info/only_version_changed.txt ]] && exit 0
- /app/scripts/entrypoint.pl test_bmo -q -f t/bmo/*.t
- - *store_log
-
-workflows:
- version: 2
- main:
- jobs:
- - build_info:
- filters: *main_filters
- - build:
- filters: *main_filters
- requires:
- - build_info
- - test_sanity
- - test_bmo
- - test_webservices
- - test_selenium
- - test_sanity:
- filters: *main_filters
- requires:
- - build_info
- - test_bmo:
- filters: *main_filters
- requires:
- - build_info
- - test_webservices:
- filters: *main_filters
- requires:
- - build_info
- - test_selenium:
- filters: *main_filters
- requires:
- - build_info
diff --git a/.gitignore b/.gitignore
index 18f2d0a17..7bf2816b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,7 +16,9 @@
/data
/localconfig
/localconfig.*
+/conf/env.conf
/index.html
+/errors/
/error_reports
/.DS_Store
/template_cache
diff --git a/.htaccess b/.htaccess
index d9681baa6..9e29dcc1c 100644
--- a/.htaccess
+++ b/.htaccess
@@ -7,13 +7,11 @@ AddType image/x-icon .ico
AddType application/font-woff .woff
AddType application/font-woff2 .woff2
-Redirect permanent /queryhelp.cgi https://bugzilla.mozilla.org/query.cgi?format=advanced&help=1
-Redirect permanent /bug_status.html https://bugzilla.mozilla.org/page.cgi?id=fields.html
-Redirect permanent /bugwritinghelp.html https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html
-Redirect permanent /etiquette.html https://bugzilla.mozilla.org/page.cgi?id=etiquette.html
-Redirect permanent /duplicates.html https://bugzilla.mozilla.org/duplicates.cgi
-Redirect permanent /quicksearch.html https://bugzilla.mozilla.org/page.cgi?id=quicksearch.html
-Redirect permanent /bugwritinghelp.html https://bugzilla.mozilla.org/page.cgi?id=bug-writing.html
+Redirect permanent /queryhelp.cgi /query.cgi?format=advanced&help=1
+Redirect permanent /bug_status.html /page.cgi?id=fields.html
+Redirect permanent /bugwritinghelp.html /page.cgi?id=bug-writing.html
+Redirect permanent /etiquette.html /page.cgi?id=etiquette.html
+Redirect permanent /duplicates.html /duplicates.cgi
RewriteEngine On
# This rewrite rule skips over the rest, which is good because the load balancers
diff --git a/Bugzilla.pm b/Bugzilla.pm
index 06bf2ddf0..a6f4e2b4d 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -13,7 +13,7 @@ use warnings;
use Bugzilla::Logging;
-our $VERSION = '20180803.1';
+our $VERSION = '5.13';
use Bugzilla::Auth;
use Bugzilla::Auth::Persist::Cookie;
@@ -46,6 +46,7 @@ use File::Basename;
use File::Spec::Functions;
use Safe;
use JSON::XS qw(decode_json);
+use URI;
use parent qw(Bugzilla::CPAN);
@@ -110,20 +111,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);
# Because of attachment_base, attachment.cgi handles this itself.
@@ -219,6 +206,14 @@ sub template_inner {
}
sub extensions {
+ # Guard against extensions querying the extension list during initialization
+ # (through this method or has_extension).
+ # The extension list is not fully populated at that point,
+ # so the results would not be meaningful.
+ state $recursive = 0;
+ die "Recursive attempt to load/query extensions" if $recursive;
+ $recursive = 1;
+
my $cache = request_cache;
if (!$cache->{extensions}) {
my $extension_packages = Bugzilla::Extension->load_all();
@@ -231,9 +226,20 @@ sub extensions {
}
$cache->{extensions} = \@extensions;
}
+ $recursive = 0;
return $cache->{extensions};
}
+sub has_extension {
+ my ($class, $name) = @_;
+ my $cache = $class->request_cache;
+ if (!$cache->{extensions_hash}) {
+ my %extensions = map { $_->NAME => 1 } @{ Bugzilla->extensions };
+ $cache->{extensions_hash} = \%extensions;
+ }
+ return exists $cache->{extensions_hash}{$name};
+}
+
sub cgi {
return request_cache->{cgi} ||= Bugzilla::CGI->new;
}
@@ -258,6 +264,13 @@ sub localconfig {
return $_[0]->process_cache->{localconfig} ||= read_localconfig();
}
+sub urlbase {
+ my ($class) = @_;
+
+ # Since this could be modified, we have to return a new one every time.
+ return URI->new($class->localconfig->{urlbase});
+}
+
sub params {
return request_cache->{params} ||= Bugzilla::Config::read_param_file();
}
@@ -844,10 +857,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 1bf0dd54a..9ac01c71e 100644
--- a/Bugzilla/CGI.pm
+++ b/Bugzilla/CGI.pm
@@ -704,7 +704,7 @@ sub send_cookie {
}
# Add the default path and the domain in.
- state $uri = URI->new( Bugzilla->localconfig->{urlbase} );
+ state $uri = Bugzilla->urlbase;
$paramhash{'-path'} = $uri->path;
# we don't set the domain.
$paramhash{'-secure'} = 1
diff --git a/Bugzilla/Config/BugFields.pm b/Bugzilla/Config/BugFields.pm
index 94a16b7c2..c443ffe78 100644
--- a/Bugzilla/Config/BugFields.pm
+++ b/Bugzilla/Config/BugFields.pm
@@ -65,7 +65,7 @@ sub get_param_list {
name => 'defaultpriority',
type => 's',
choices => \@legal_priorities,
- default => $legal_priorities[-1],
+ default => $legal_priorities[0],
checker => \&check_priority
},
diff --git a/Bugzilla/Config/General.pm b/Bugzilla/Config/General.pm
index c870c7376..fa7cf2d08 100644
--- a/Bugzilla/Config/General.pm
+++ b/Bugzilla/Config/General.pm
@@ -25,6 +25,14 @@ use constant get_param_list => (
},
{
+ name => 'nobody_user',
+ type => 't',
+ no_reset => '1',
+ default => 'nobody@mozilla.org',
+ checker => \&check_email
+ },
+
+ {
name => 'docs_urlbase',
type => 't',
default => 'docs/%lang%/html/',
diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm
index 185a30390..34e4a4cfe 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);
@@ -696,6 +698,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/DB.pm b/Bugzilla/DB.pm
index 80404131a..f07bb7183 100644
--- a/Bugzilla/DB.pm
+++ b/Bugzilla/DB.pm
@@ -61,14 +61,12 @@ use constant ISOLATION_LEVEL => 'REPEATABLE READ';
# Bugzilla with enums. After that, they are either controlled through
# the Bugzilla UI or through the DB.
use constant ENUM_DEFAULTS => {
- bug_severity => ['blocker', 'critical', 'major', 'normal',
- 'minor', 'trivial', 'enhancement'],
- priority => ["Highest", "High", "Normal", "Low", "Lowest", "---"],
- op_sys => ["All","Windows","Mac OS","Linux","Other"],
- rep_platform => ["All","PC","Macintosh","Other"],
- bug_status => ["UNCONFIRMED","CONFIRMED","IN_PROGRESS","RESOLVED",
- "VERIFIED"],
- resolution => ["","FIXED","INVALID","WONTFIX", "DUPLICATE","WORKSFORME"],
+ bug_severity => [qw(blocker critical major normal minor trivial enhancement )],
+ priority => [qw(-- P1 P2 P3 P4 P5)],
+ op_sys => [ "Unspecified", "All", "Windows", "Mac OS", "Linux", "Other" ],
+ rep_platform => [ "Unspecified", "All", "PC", "Macintosh", "Other" ],
+ bug_status => [qw(UNCONFIRMED NEW ASSIGNED REOPENED RESOLVED VERIFIED CLOSED)],
+ resolution => [ "", qw(FIXED INVALID WONTFIX DUPLICATE WORKSFORME INCOMPLETE) ],
};
# The character that means "OR" in a boolean fulltext search. If empty,
diff --git a/Bugzilla/Elastic/Role/HasClient.pm b/Bugzilla/Elastic/Role/HasClient.pm
index 8e2687880..a971392e0 100644
--- a/Bugzilla/Elastic/Role/HasClient.pm
+++ b/Bugzilla/Elastic/Role/HasClient.pm
@@ -8,7 +8,6 @@ package Bugzilla::Elastic::Role::HasClient;
use 5.10.1;
use Moo::Role;
-use Search::Elasticsearch;
has 'client' => (is => 'lazy');
@@ -16,6 +15,7 @@ has 'client' => (is => 'lazy');
sub _build_client {
my ($self) = @_;
+ require Search::Elasticsearch;
return Search::Elasticsearch->new(
nodes => [ split(/\s+/, Bugzilla->params->{elasticsearch_nodes}) ],
cxn_pool => 'Sniff',
diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm
index c941482f0..7f684ea15 100644
--- a/Bugzilla/Group.pm
+++ b/Bugzilla/Group.pm
@@ -26,17 +26,24 @@ use Scalar::Util qw(blessed);
use constant IS_CONFIG => 1;
-use constant DB_COLUMNS => qw(
- groups.id
- groups.name
- groups.description
- groups.isbuggroup
- groups.userregexp
- groups.isactive
- groups.icon_url
- groups.owner_user_id
- groups.idle_member_removal
-);
+sub DB_COLUMNS {
+ my $class = shift;
+ my @columns = qw(
+ id
+ name
+ description
+ isbuggroup
+ userregexp
+ isactive
+ icon_url
+ owner_user_id
+ idle_member_removal
+ );
+ my $dbh = Bugzilla->dbh;
+ my $table = $class->DB_TABLE;
+
+ return map { "$table.$_" } grep { $dbh->bz_column_info($table, $_) } @columns;
+}
use constant DB_TABLE => 'groups';
diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm
index 8bce9b5e7..14fe904eb 100644
--- a/Bugzilla/Install.pm
+++ b/Bugzilla/Install.pm
@@ -19,6 +19,7 @@ use 5.10.1;
use strict;
use warnings;
+use Bugzilla::Logging;
use Bugzilla::Component;
use Bugzilla::Config qw(:admin);
use Bugzilla::Constants;
@@ -31,21 +32,31 @@ use Bugzilla::Util qw(get_text);
use Bugzilla::Version;
use constant STATUS_WORKFLOW => (
- [undef, 'UNCONFIRMED'],
- [undef, 'CONFIRMED'],
- [undef, 'IN_PROGRESS'],
- ['UNCONFIRMED', 'CONFIRMED'],
- ['UNCONFIRMED', 'IN_PROGRESS'],
- ['UNCONFIRMED', 'RESOLVED'],
- ['CONFIRMED', 'IN_PROGRESS'],
- ['CONFIRMED', 'RESOLVED'],
- ['IN_PROGRESS', 'CONFIRMED'],
- ['IN_PROGRESS', 'RESOLVED'],
- ['RESOLVED', 'UNCONFIRMED'],
- ['RESOLVED', 'CONFIRMED'],
- ['RESOLVED', 'VERIFIED'],
- ['VERIFIED', 'UNCONFIRMED'],
- ['VERIFIED', 'CONFIRMED'],
+ [ undef, 'UNCONFIRMED' ],
+ [ undef, 'NEW' ],
+ [ undef, 'ASSIGNED' ],
+ [ 'UNCONFIRMED', 'NEW' ],
+ [ 'UNCONFIRMED', 'ASSIGNED' ],
+ [ 'UNCONFIRMED', 'RESOLVED' ],
+ [ 'NEW', 'UNCONFIRMED' ],
+ [ 'NEW', 'ASSIGNED' ],
+ [ 'NEW', 'RESOLVED' ],
+ [ 'ASSIGNED', 'UNCONFIRMED' ],
+ [ 'ASSIGNED', 'NEW' ],
+ [ 'ASSIGNED', 'RESOLVED' ],
+ [ 'REOPENED', 'UNCONFIRMED' ],
+ [ 'REOPENED', 'NEW' ],
+ [ 'REOPENED', 'ASSIGNED' ],
+ [ 'REOPENED', 'RESOLVED' ],
+ [ 'RESOLVED', 'UNCONFIRMED' ],
+ [ 'RESOLVED', 'REOPENED' ],
+ [ 'RESOLVED', 'VERIFIED' ],
+ [ 'VERIFIED', 'UNCONFIRMED' ],
+ [ 'VERIFIED', 'REOPENED' ],
+ [ 'VERIFIED', 'RESOLVED' ],
+ [ 'CLOSED', 'UNCONFIRMED' ],
+ [ 'CLOSED', 'REOPENED' ],
+ [ 'CLOSED', 'RESOLVED' ],
);
sub SETTINGS {
@@ -385,6 +396,7 @@ sub init_workflow {
'SELECT value, id FROM bug_status', {Columns=>[1,2]}) };
foreach my $pair (STATUS_WORKFLOW) {
+ WARN("unknown bug_status: " . $pair->[1]) unless $status_ids{$pair->[1]};
my $old_id = $pair->[0] ? $status_ids{$pair->[0]} : undef;
my $new_id = $status_ids{$pair->[1]};
$dbh->do('INSERT INTO status_workflow (old_status, new_status)
diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm
index 2e5ae5ff2..8b3d4b8cc 100644
--- a/Bugzilla/Install/DB.pm
+++ b/Bugzilla/Install/DB.pm
@@ -3908,7 +3908,16 @@ sub _migrate_group_owners {
my $dbh = Bugzilla->dbh;
return if $dbh->bz_column_info('groups', 'owner_user_id');
$dbh->bz_add_column('groups', 'owner_user_id', {TYPE => 'INT3'});
- my $nobody = Bugzilla::User->check('nobody@mozilla.org');
+ my $nobody = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'}, cache => 1 });
+ unless ($nobody) {
+ $nobody = Bugzilla::User->create(
+ {
+ login_name => Bugzilla->params->{'nobody_user'},
+ realname => 'Nobody (ok to assign bugs to)',
+ cryptpassword => '*',
+ }
+ );
+ }
$dbh->do('UPDATE groups SET owner_user_id = ?', undef, $nobody->id);
}
diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm
index f520d3d56..46e121779 100644
--- a/Bugzilla/Install/Filesystem.pm
+++ b/Bugzilla/Install/Filesystem.pm
@@ -72,6 +72,50 @@ sub HTTPD_ENV_CONF {
return join( "\n", map { "PerlPassEnv " . $_ } @env ) . "\n";
}
+sub _error_page {
+ my ($code, $title, $description) = @_;
+
+ return <<EOT;
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>$title</title>
+ <style>
+ body {
+ margin: 1em 2em;
+ background-color: #455372;
+ color: #ddd;
+ font-family: sans-serif;
+ }
+ h1, h3 {
+ color: #fff;
+ }
+ a {
+ color: #fff;
+ text-decoration: none;
+ }
+ #buggie {
+ float: left;
+ }
+ #content {
+ margin-left: 100px;
+ padding-top: 20px;
+ }
+ </style>
+ </head>
+ <body>
+ <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
+ <div id="content">
+ <h1>$title</h1>
+ <p>$description</p>
+ <h3>Error $code</h3>
+ <p><a href="/">this site</a></p>
+ </div>
+ </body>
+</html>
+EOT
+}
+
###############
# Permissions #
###############
@@ -169,6 +213,7 @@ sub FILESYSTEM {
# users to be able to cron them or otherwise run
# them as a secure user, like the webserver owner.
'*.cgi' => { perms => WS_EXECUTE },
+ '*.psgi' => { perms => CGI_READ },
'whineatnews.pl' => { perms => WS_EXECUTE },
'collectstats.pl' => { perms => WS_EXECUTE },
'importxml.pl' => { perms => WS_EXECUTE },
@@ -300,7 +345,7 @@ sub FILESYSTEM {
'contrib' => { files => OWNER_EXECUTE,
dirs => DIR_OWNER_WRITE, },
'scripts' => { files => OWNER_EXECUTE,
- dirs => DIR_OWNER_WRITE, },
+ dirs => DIR_WS_SERVE, },
);
# --- FILES TO CREATE --- #
@@ -387,6 +432,40 @@ sub FILESYSTEM {
contents => \&HTTPD_ENV_CONF },
);
+ # Create static error pages.
+ $create_dirs{"errors"} = DIR_CGI_READ;
+ $create_files{"errors/401.html"} = {
+ perms => CGI_READ,
+ overwrite => 1,
+ contents => _error_page(
+ 401, 'Authentication Required',
+ "This server could not verify that you are authorized to access
+ that url. you either supplied the wrong credentials (e.g., bad
+ password), or your browser doesn't understand how to supply the
+ credentials required.")
+ };
+ $create_files{"errors/403.html"} = {
+ perms => CGI_READ,
+ overwrite => 1,
+ contents => _error_page(
+ 403, 'Access Denied',
+ "Access to the requested resource has been denied.")
+ };
+ $create_files{"errors/404.html"} = {
+ perms => CGI_READ,
+ overwrite => 1,
+ contents => _error_page(
+ 404, 'Object Not Found',
+ "The requested URL was not found on this server.")
+ };
+ $create_files{"errors/500.html"} = {
+ perms => CGI_READ,
+ overwrite => 1,
+ contents => _error_page(
+ 500, 'Internal Server Error',
+ "The server encountered an internal error and was unable to complete your request.")
+ };
+
# Because checksetup controls the creation of index.html separately
# from all other files, it gets its very own hash.
my %index_html = (
@@ -472,7 +551,7 @@ sub update_filesystem {
# Delete old files that no longer need to exist
# 2001-04-29 jake@bugzilla.org - Remove oldemailtech
- # http://bugzilla.mozilla.org/show_bugs.cgi?id=71552
+ # http://bugzilla.mozilla.org/show_bug.cgi?id=71552
if (-d 'shadow') {
print "Removing shadow directory...\n";
rmtree("shadow");
diff --git a/Bugzilla/Install/Localconfig.pm b/Bugzilla/Install/Localconfig.pm
index e1a8e0909..39063ee63 100644
--- a/Bugzilla/Install/Localconfig.pm
+++ b/Bugzilla/Install/Localconfig.pm
@@ -288,7 +288,12 @@ sub read_localconfig {
my ($include_deprecated) = @_;
if ($ENV{LOCALCONFIG_ENV}) {
- return _read_localconfig_from_env();
+ my $lc = _read_localconfig_from_env();
+ if ( $lc->{urlbase} eq 'AUTOMATIC' ) {
+ $lc->{urlbase} = sprintf 'http://%s:%d/%s', hostname(), $ENV{PORT}, $ENV{BZ_QA_LEGACY_MODE} ? 'bmo/' : '';
+ $ENV{BZ_BASE_URL} = sprintf 'http://%s:%d', hostname(), $ENV{PORT};
+ }
+ return $lc;
}
else {
return _read_localconfig_from_file($include_deprecated);
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/Quantum/Plugin/Hostage.pm b/Bugzilla/Quantum/Plugin/Hostage.pm
index cbde7b5ee..418b09a0c 100644
--- a/Bugzilla/Quantum/Plugin/Hostage.pm
+++ b/Bugzilla/Quantum/Plugin/Hostage.pm
@@ -1,20 +1,19 @@
package Bugzilla::Quantum::Plugin::Hostage;
use 5.10.1;
use Mojo::Base 'Mojolicious::Plugin';
-use Bugzilla::Logging;
sub _attachment_root {
my ($base) = @_;
return undef unless $base;
return $base =~ m{^https?://(?:bug)?\%bugid\%\.([a-zA-Z\.-]+)}
- ? $1
- : undef;
+ ? $1
+ : undef;
}
sub _attachment_host_regex {
my ($base) = @_;
return undef unless $base;
- my $val = $base;
+ my $val = $base;
$val =~ s{^https?://}{}s;
$val =~ s{/$}{}s;
my $regex = quotemeta $val;
@@ -25,11 +24,11 @@ sub _attachment_host_regex {
sub register {
my ( $self, $app, $conf ) = @_;
- $app->hook( before_routes => \&_before_routes );
+ $app->hook(before_routes => \&_before_routes);
}
sub _before_routes {
- my ($c) = @_;
+ my ( $c ) = @_;
state $urlbase = Bugzilla->localconfig->{urlbase};
state $urlbase_uri = URI->new($urlbase);
state $urlbase_host = $urlbase_uri->host;
@@ -44,40 +43,35 @@ sub _before_routes {
return if $stash->{'mojo.static'};
- my $hostname = $url->host;
+ my $hostname = $url->host;
return if $hostname eq $urlbase_host;
my $path = $url->path;
return if $path eq '/__lbheartbeat__';
- if ( $attachment_base && $hostname eq $attachment_root ) {
- DEBUG("redirecting to $urlbase because $hostname is $attachment_root");
+ if ($attachment_base && $hostname eq $attachment_root) {
$c->redirect_to($urlbase);
return;
}
- elsif ( $attachment_base && $hostname =~ $attachment_host_regex ) {
- if ( $path =~ m{^/attachment\.cgi}s ) {
+ elsif ($attachment_base && $hostname =~ $attachment_host_regex) {
+ if ($path =~ m{^/attachment\.cgi}s) {
return;
- }
- else {
+ } else {
my $new_uri = $url->clone;
- $new_uri->scheme( $urlbase_uri->scheme );
+ $new_uri->scheme($urlbase_uri->scheme);
$new_uri->host($urlbase_host);
- DEBUG("redirecting to $new_uri because $hostname matches attachment regex");
$c->redirect_to($new_uri);
return;
}
}
- elsif ( my ($id) = $hostname =~ $urlbase_host_regex ) {
+ 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 );
- DEBUG("redirecting to $new_uri because $hostname includes bug id");
+ $new_uri->query_form(id => $id);
$c->redirect_to($new_uri);
return;
}
else {
- DEBUG("redirecting to $urlbase because $hostname doesn't make sense");
$c->redirect_to($urlbase);
return;
}
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/Search.pm b/Bugzilla/Search.pm
index f419955dc..e15c60f7f 100644
--- a/Bugzilla/Search.pm
+++ b/Bugzilla/Search.pm
@@ -802,18 +802,20 @@ sub data {
# BMO - to avoid massive amounts of joins, if we're selecting a lot of
# tracking flags, replace them with placeholders. the values will be
# retrieved later and injected into the result.
- my %tf_map = map { $_ => 1 } Bugzilla::Extension::TrackingFlags::Flag->get_all_names();
- my @tf_selected = grep { exists $tf_map{$_} } @orig_fields;
- # mysql has a limit of 61 joins, and we want to avoid massive amounts of joins
- # 30 ensures we won't hit the limit, nor generate too many joins
- if (scalar @tf_selected > 30) {
- foreach my $column (@tf_selected) {
- $self->COLUMNS->{$column}->{name} = "'---'";
+ if (Bugzilla->has_extension('TrackingFlags')) {
+ my %tf_map = map { $_ => 1 } Bugzilla::Extension::TrackingFlags::Flag->get_all_names();
+ my @tf_selected = grep { exists $tf_map{$_} } @orig_fields;
+ # mysql has a limit of 61 joins, and we want to avoid massive amounts of joins
+ # 30 ensures we won't hit the limit, nor generate too many joins
+ if (scalar @tf_selected > 30) {
+ foreach my $column (@tf_selected) {
+ $self->COLUMNS->{$column}->{name} = "'---'";
+ }
+ $self->{tracking_flags} = \@tf_selected;
+ }
+ else {
+ $self->{tracking_flags} = [];
}
- $self->{tracking_flags} = \@tf_selected;
- }
- else {
- $self->{tracking_flags} = [];
}
my $start_time = [gettimeofday()];
@@ -863,7 +865,7 @@ sub data {
$self->{data} = [map { $data{$_} } @$bug_ids];
# BMO - get tracking flags values, and insert into result
- if (@{ $self->{tracking_flags} }) {
+ if (Bugzilla->has_extension('TrackingFlags') && @{ $self->{tracking_flags} }) {
# read values
my $values;
$sql = "
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index 39272a538..cdeb54a50 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -995,6 +995,8 @@ sub create {
'feature_enabled' => sub { return Bugzilla->feature(@_); },
+ 'has_extension' => sub { return Bugzilla->has_extension(@_); },
+
# field_descs can be somewhat slow to generate, so we generate
# it only once per-language no matter how many times
# $template->process() is called.
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 0ac04acc6..000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,37 +0,0 @@
-FROM mozillabteam/bmo-slim:20180801.2
-
-ARG CI
-ARG CIRCLE_SHA1
-ARG CIRCLE_BUILD_URL
-
-ENV CI=${CI}
-ENV CIRCLE_BUILD_URL=${CIRCLE_BUILD_URL}
-ENV CIRCLE_SHA1=${CIRCLE_SHA1}
-
-ENV LOG4PERL_CONFIG_FILE=log4perl-json.conf
-
-ENV PORT=8000
-
-# we run a loopback logging server on this TCP port.
-ENV LOGGING_PORT=5880
-
-WORKDIR /app
-COPY . .
-
-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/bin/perl
-
-USER app
-
-RUN perl checksetup.pl --no-database --default-localconfig && \
- rm -rf /app/data /app/localconfig && \
- mkdir /app/data
-
-EXPOSE $PORT
-
-ENTRYPOINT ["/app/scripts/entrypoint.pl"]
-CMD ["httpd"]
diff --git a/Makefile.PL b/Makefile.PL
index 3cd1dabba..b0f7e88ce 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -47,7 +47,6 @@ my %requires = (
'Date::Format' => '2.23',
'DateTime' => '0.75',
'DateTime::TimeZone' => '2.11',
- 'Devel::NYTProf' => '6.04',
'Digest::SHA' => '5.47',
'Email::MIME' => '1.904',
'Email::Send' => '1.911',
@@ -75,7 +74,6 @@ my %requires = (
'Mozilla::CA' => '20160104',
'Parse::CPAN::Meta' => '1.44',
'Role::Tiny' => '2.000003',
- 'Sereal' => '4.004',
'Taint::Util' => '0.08',
'Template' => '2.24',
'Text::CSV_XS' => '1.26',
@@ -445,6 +443,7 @@ META.json: Makefile.PL
\tmake distmeta 2>&1 /dev/null; mv */META.json .
META.yml: Makefile.PL
+1: hit EOF seeking end of quote/pattern starting at line 1 ending in /
\tmake distmeta 2>&1 /dev/null; mv */META.yml .
MAKE
}
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/buglist.cgi b/buglist.cgi
index 019bf0d4e..d1cde7096 100755
--- a/buglist.cgi
+++ b/buglist.cgi
@@ -1103,4 +1103,4 @@ $cgi->close_standby_message($contenttype, $disposition, $disp_prefix, $format->{
# Generate and return the UI (HTML page) from the appropriate template.
$template->process($format->{'template'}, $vars)
- || ThrowTemplateError($template->error()); \ No newline at end of file
+ || ThrowTemplateError($template->error());
diff --git a/docs/en/rst/integrating/templates.rst b/docs/en/rst/integrating/templates.rst
index b477a9553..ee2c08e92 100644
--- a/docs/en/rst/integrating/templates.rst
+++ b/docs/en/rst/integrating/templates.rst
@@ -262,7 +262,7 @@ customizing for your installation.
It needs a couple of lines of boilerplate at the top like this::
[% USE Bugzilla %]
- [% cgi = Bugzilla.cgi %
+ [% cgi = Bugzilla.cgi %]
Then, this template can reference the form fields you have created using
the syntax ``[% cgi.param("field_name") %]``. When a bug report is
diff --git a/editusers.cgi b/editusers.cgi
index d2ad3a82f..beb9b3a4c 100755
--- a/editusers.cgi
+++ b/editusers.cgi
@@ -32,8 +32,7 @@ my $dbh = Bugzilla->dbh;
my $userid = $user->id;
my $editusers = $user->in_group('editusers');
my $disableusers = $user->in_group('disableusers');
-
-local our $vars = {};
+local our $vars = {};
# Reject access if there is no sense in continuing.
$editusers
diff --git a/enter_bug.cgi b/enter_bug.cgi
index 33cdf8535..5b8a97dba 100755
--- a/enter_bug.cgi
+++ b/enter_bug.cgi
@@ -37,6 +37,8 @@ use Bugzilla::Field;
use Bugzilla::Status;
use Bugzilla::UserAgent;
+use List::Util qw(any);
+
my $user = Bugzilla->login(LOGIN_REQUIRED);
my $cloned_bug;
@@ -299,8 +301,13 @@ else {
$default{'bug_severity'} = formvalue('bug_severity', Bugzilla->params->{'defaultseverity'});
# BMO - use per-product default hw/os
- $default{'rep_platform'} = formvalue('rep_platform', $product->default_platform // detect_platform());
- $default{'op_sys'} = formvalue('op_sys', $product->default_op_sys // detect_op_sys());
+ if (any { $_->NAME eq 'BMO' } @{ Bugzilla->extensions }) {
+ $default{'rep_platform'} = formvalue('rep_platform', $product->default_platform // detect_platform());
+ $default{'op_sys'} = formvalue('op_sys', $product->default_op_sys // detect_op_sys());
+ } else {
+ $default{'rep_platform'} = formvalue('rep_platform', detect_platform());
+ $default{'op_sys'} = formvalue('op_sys', detect_op_sys());
+ }
$vars->{'rep_platform'} = detect_platform();
$vars->{'rep_op_sys'} = detect_op_sys();
diff --git a/errors/401.html b/errors/401.html
deleted file mode 100644
index 8242b549f..000000000
--- a/errors/401.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>Access Denied</title>
- <style>
- body {
- margin: 1em 2em;
- background-color: #455372;
- color: #ddd;
- font-family: sans-serif;
- }
- h1, h3 {
- color: #fff;
- }
- a {
- color: #fff;
- text-decoration: none;
- }
- #buggie {
- float: left;
- }
- #content {
- margin-left: 100px;
- padding-top: 20px;
- }
- </style>
- </head>
- <body>
- <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
- <div id="content">
- <h1>Authentication Required</h1>
- <p>This server could not verify that you are authorized to access
- that url. you either supplied the wrong credentials (e.g., bad
- password), or your browser doesn't understand how to supply the
- credentials required.</p>
- <h3>Error 401</h3>
- <p><a href="/">bugzilla.mozilla.org</a></p>
- </div>
- </body>
-</html>
diff --git a/errors/403.html b/errors/403.html
deleted file mode 100644
index e2faf8522..000000000
--- a/errors/403.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>Access Denied</title>
- <style>
- body {
- margin: 1em 2em;
- background-color: #455372;
- color: #ddd;
- font-family: sans-serif;
- }
- h1, h3 {
- color: #fff;
- }
- a {
- color: #fff;
- text-decoration: none;
- }
- #buggie {
- float: left;
- }
- #content {
- margin-left: 100px;
- padding-top: 20px;
- }
- </style>
- </head>
- <body>
- <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
- <div id="content">
- <h1>Access Denied</h1>
- <p>Access to the requested resource has been denied.</p>
- <h3>Error 403</h3>
- <p><a href="/">bugzilla.mozilla.org</a></p>
- </div>
- </body>
-</html>
diff --git a/errors/404.html b/errors/404.html
deleted file mode 100644
index 3b476471c..000000000
--- a/errors/404.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>Object Not Found</title>
- <style>
- body {
- margin: 1em 2em;
- background-color: #455372;
- color: #ddd;
- font-family: sans-serif;
- }
- h1, h3 {
- color: #fff;
- }
- a {
- color: #fff;
- text-decoration: none;
- }
- #buggie {
- float: left;
- }
- #content {
- margin-left: 100px;
- padding-top: 20px;
- }
- </style>
- </head>
- <body>
- <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
- <div id="content">
- <h1>Object Not Found</h1>
- <p>The requested URL was not found on this server.</p>
- <h3>Error 404</h3>
- <p><a href="/">bugzilla.mozilla.org</a></p>
- </div>
- </body>
-</html>
diff --git a/errors/500.html b/errors/500.html
deleted file mode 100644
index e0657001d..000000000
--- a/errors/500.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE HTML>
-<html>
- <head>
- <title>Internal Server Error</title>
- <style>
- body {
- margin: 1em 2em;
- background-color: #455372;
- color: #ddd;
- font-family: sans-serif;
- }
- h1, h3 {
- color: #fff;
- }
- a {
- color: #fff;
- text-decoration: none;
- }
- #buggie {
- float: left;
- }
- #content {
- margin-left: 100px;
- padding-top: 20px;
- }
- </style>
- </head>
- <body>
- <img src="/images/buggie.png" id="buggie" alt="buggie" width="78" height="215">
- <div id="content">
- <h1>Internal Server Error</h1>
- <p>The server encountered an internal error and was unable to complete your request.</p>
- <h3>Error 500</h3>
- <p><a href="/">bugzilla.mozilla.org</a></p>
- </div>
- </body>
-</html>
diff --git a/extensions/AntiSpam/lib/Config.pm b/extensions/AntiSpam/lib/Config.pm
index e35a7f001..278baea8f 100644
--- a/extensions/AntiSpam/lib/Config.pm
+++ b/extensions/AntiSpam/lib/Config.pm
@@ -55,7 +55,7 @@ sub get_param_list {
"This account has been automatically disabled as a result of " .
"a high number of comments tagged as abusive.<br>\n<br>\n" .
"All interactions on Bugzilla should follow our " .
- "<a href=\"https://bugzilla.mozilla.org/page.cgi?id=etiquette.html\">" .
+ "<a href=\"" . Bugzilla->localconfig->{'urlbase'} . "page.cgi?id=etiquette.html\">" .
"etiquette guidelines</a>.<br>\n<br>\n" .
"Please contact the address at the end of this message if you " .
"believe this to be an error, or if you would like your account " .
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
index 102b71068..743d03099 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;
@@ -878,7 +879,7 @@ sub object_end_of_create {
# Add default searches to new user's footer
my $dbh = Bugzilla->dbh;
- my $sharer = Bugzilla::User->new({ name => 'nobody@mozilla.org' })
+ my $sharer = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} })
or return;
my $group = Bugzilla::Group->new({ name => 'everyone' })
or return;
@@ -919,7 +920,7 @@ sub _bug_reporters_hw_os {
sub _bug_is_unassigned {
my ($self) = @_;
my $assignee = $self->assigned_to->login;
- return $assignee eq 'nobody@mozilla.org' || $assignee =~ /\.bugs$/;
+ return $assignee eq Bugzilla->params->{'nobody_user'} || $assignee =~ /\.bugs$/;
}
sub _bug_has_current_patch {
@@ -1100,7 +1101,7 @@ sub object_start_of_update {
# and the assignee isn't a real person
return unless
- $new_bug->assigned_to->login eq 'nobody@mozilla.org'
+ $new_bug->assigned_to->login eq Bugzilla->params->{'nobody_user'}
|| $new_bug->assigned_to->login =~ /\.bugs$/;
# and the user can set the status to NEW
@@ -1595,7 +1596,7 @@ sub field_end_of_create {
my $name = $field->name;
if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) {
- Bugzilla->set_user(Bugzilla::User->check({ name => 'nobody@mozilla.org' }));
+ Bugzilla->set_user(Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }));
print "Creating IT permission grant bug for new field '$name'...";
}
@@ -1666,6 +1667,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;
@@ -1951,7 +1974,7 @@ sub _post_employee_incident_bug {
my ($investigate_bug, $ssh_key_bug);
my $old_user = Bugzilla->user;
eval {
- Bugzilla->set_user(Bugzilla::User->new({ name => 'nobody@mozilla.org' }));
+ Bugzilla->set_user(Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} }));
my $new_user = Bugzilla->user;
# HACK: User needs to be in the editbugs and primary bug's group to allow
diff --git a/extensions/BMO/bin/bug_1093952.pl b/extensions/BMO/bin/bug_1093952.pl
index 735c6a37a..fd891f4ae 100755
--- a/extensions/BMO/bin/bug_1093952.pl
+++ b/extensions/BMO/bin/bug_1093952.pl
@@ -52,7 +52,7 @@ printf "About to fix %s bugs\n", scalar(@$bugs);
print "Press <Ctrl-C> to stop or <Enter> to continue...\n";
getc();
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} });
my $field = Bugzilla::Field->check({ name => 'status_whiteboard' });
my $when = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
diff --git a/extensions/BMO/bin/bug_1141452.pl b/extensions/BMO/bin/bug_1141452.pl
index 869593802..155c4704c 100755
--- a/extensions/BMO/bin/bug_1141452.pl
+++ b/extensions/BMO/bin/bug_1141452.pl
@@ -50,7 +50,7 @@ printf "About to fix %s bugs\n", scalar(@$flags);
print "Press <Ctrl-C> to stop or <Enter> to continue...\n";
getc();
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} });
my $when = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
$dbh->bz_start_transaction();
diff --git a/extensions/BMO/bin/migrate-github-pull-requests.pl b/extensions/BMO/bin/migrate-github-pull-requests.pl
index 53c1727b5..c39778a4a 100755
--- a/extensions/BMO/bin/migrate-github-pull-requests.pl
+++ b/extensions/BMO/bin/migrate-github-pull-requests.pl
@@ -23,7 +23,7 @@ use Bugzilla::User;
use Bugzilla::Util qw(trim);
my $dbh = Bugzilla->dbh;
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} });
my $field = Bugzilla::Field->check({ name => 'attachments.mimetype' });
# grab list of suitable attachments
diff --git a/extensions/BMO/disabled b/extensions/BMO/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/BMO/disabled
diff --git a/extensions/BMO/lib/WebService.pm b/extensions/BMO/lib/WebService.pm
index 327c8563f..b9d8e4132 100644
--- a/extensions/BMO/lib/WebService.pm
+++ b/extensions/BMO/lib/WebService.pm
@@ -116,7 +116,7 @@ Bugzilla::Extension::BMO::Webservice - The BMO WebServices API
=head1 DESCRIPTION
-This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+This module contains API methods that are useful to users of bugzilla.mozilla.org.
=head1 METHODS
diff --git a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
index 697542ead..0bd1c94d7 100644
--- a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
+++ b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
@@ -297,7 +297,7 @@ function validate_form() {
<input type="hidden" name="version" value="unspecified">
<input type="hidden" name="bug_severity" value="normal">
<input type="hidden" name="group" value="pr-private">
-<input type="hidden" name="assigned_to" id="assigned_to" value="nobody@mozilla.org">
+<input type="hidden" name="assigned_to" id="assigned_to" value="[% Param('nobody_user') FILTER html %]">
<input type="hidden" name="token" value="[% token FILTER html %]">
<div class="head">
diff --git a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
index d6243c73b..9c0c4780d 100644
--- a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
+++ b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
@@ -43,7 +43,7 @@ please provide some information about your application or product.</p>
<input type="hidden" name="priority" value="--">
<input type="hidden" name="op_sys" value="Other">
<input type="hidden" name="version" value="unspecified">
- <input type="hidden" name="assigned_to" value="nobody@mozilla.org">
+ <input type="hidden" name="assigned_to" value="[% Param('nobody_user') FILTER html %]">
<input type="hidden" name="cc" value="liz@mozilla.com">
<input type="hidden" name="groups" value="marketing-private">
<input type="hidden" name="token" value="[% token FILTER html %]">
diff --git a/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl
index 92517cb80..803f2a746 100644
--- a/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl
+++ b/extensions/BMO/template/en/default/bug/create/create-web-bounty.html.tmpl
@@ -88,7 +88,7 @@ function validateAndSubmit() {
<input type="hidden" name="token" value="[% token FILTER html %]">
<div class="head_desc">
- <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">
+ <a href="[% terms.BugWritingGuidelinesURL %]">
[% terms.Bug %] writing guidelines</a>
</div>
diff --git a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
index 6ecd0bc75..d3c7412bf 100644
--- a/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
+++ b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
@@ -17,7 +17,7 @@
[% END +%]
[% UNLESS no_bug_guidelines %]
Before reporting a [% terms.bug %], make sure you've read our
- <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">
+ <a href="[% terms.BugWritingGuidelinesURL %]">
[% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already
been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi">
most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi">
diff --git a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
index e1c67605f..dc253ee03 100644
--- a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
+++ b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
@@ -7,5 +7,5 @@
#%]
[% PROCESS global/redirect.html.tmpl
- url = "https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines"
+ url = terms.BugWritingGuidelinesURL
%]
diff --git a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
index 45dd5bd65..fe7d2cd3d 100644
--- a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
+++ b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
@@ -173,7 +173,7 @@
<h2>See Also</h2>
<p>
- <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">The [% terms.Bug %] Writing Guidelines</a>.
+ <a href="[% terms.BugWritingGuidelinesURL %]">The [% terms.Bug %] Writing Guidelines</a>.
</p>
[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
index cfa3bd3ea..838a1e84a 100644
--- a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
+++ b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
@@ -39,7 +39,7 @@
[% group.name FILTER html %]</span>
</td>
<td nowrap>
- [% IF group.owner.login == 'nobody@mozilla.org' %]
+ [% IF group.owner.login == Param('nobody_user') %]
&ndash;
[% ELSE %]
[% INCLUDE global/user.html.tmpl who = group.owner %]
diff --git a/extensions/BugModal/Extension.pm b/extensions/BugModal/Extension.pm
index 1291fca21..ef9c93a37 100644
--- a/extensions/BugModal/Extension.pm
+++ b/extensions/BugModal/Extension.pm
@@ -188,10 +188,12 @@ sub template_before_process {
return if exists $bug->{error};
# trigger loading of tracking flags
- Bugzilla::Extension::TrackingFlags->template_before_process({
- file => 'bug/edit.html.tmpl',
- vars => $vars,
- });
+ if (Bugzilla->has_extension('TrackingFlags')) {
+ Bugzilla::Extension::TrackingFlags->template_before_process({
+ file => 'bug/edit.html.tmpl',
+ vars => $vars,
+ });
+ }
if (any { $bug->product eq $_ } READABLE_BUG_STATUS_PRODUCTS) {
my @flags = map { { name => $_->name, status => $_->status } } @{$bug->flags};
diff --git a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
index 47044e232..5d38d8340 100644
--- a/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
+++ b/extensions/BugModal/template/en/default/bug_modal/edit.html.tmpl
@@ -19,7 +19,7 @@
# these are used in a few places
is_cced = bug.cc.contains(user.login);
- unassigned = (bug.assigned_to.login == "nobody@mozilla.org")
+ unassigned = (bug.assigned_to.login == Param('nobody_user'))
|| (bug.assigned_to.login.search('\.bugs$'));
# custom fields that have custom rendering, or should not be rendered
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/ComponentWatching/Extension.pm b/extensions/ComponentWatching/Extension.pm
index 674e0da7b..96eb877a6 100644
--- a/extensions/ComponentWatching/Extension.pm
+++ b/extensions/ComponentWatching/Extension.pm
@@ -23,7 +23,7 @@ use Bugzilla::Util qw(detaint_natural trim trick_taint);
our $VERSION = '2';
use constant REQUIRE_WATCH_USER => 1;
-use constant DEFAULT_ASSIGNEE => 'nobody@mozilla.org';
+use constant DEFAULT_ASSIGNEE => Bugzilla->params->{'nobody_user'};
use constant REL_COMPONENT_WATCHER => 15;
@@ -158,7 +158,9 @@ sub object_columns {
my $columns = $args->{columns};
return unless $class->isa('Bugzilla::Component');
- push(@$columns, 'watch_user');
+ if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'watch_user')) {
+ push @$columns, 'watch_user';
+ }
}
sub object_update_columns {
diff --git a/extensions/ContributorEngagement/Extension.pm b/extensions/ContributorEngagement/Extension.pm
index 949517ecf..35eba24ab 100644
--- a/extensions/ContributorEngagement/Extension.pm
+++ b/extensions/ContributorEngagement/Extension.pm
@@ -70,7 +70,10 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::User')) {
- push(@$columns, 'first_patch_reviewed_id');
+ my $dbh = Bugzilla->dbh;
+ if ($dbh->bz_column_info($class->DB_TABLE, 'first_patch_reviewed_id')) {
+ push @$columns, 'first_patch_reviewed_id';
+ }
}
}
diff --git a/extensions/EditComments/Extension.pm b/extensions/EditComments/Extension.pm
index ab19ab6e7..e2ace3f23 100644
--- a/extensions/EditComments/Extension.pm
+++ b/extensions/EditComments/Extension.pm
@@ -191,7 +191,9 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::Comment')) {
- push(@$columns, 'edit_count');
+ if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'edit_count')) {
+ push @$columns, 'edit_count';
+ }
}
}
diff --git a/extensions/EditComments/lib/WebService.pm b/extensions/EditComments/lib/WebService.pm
index 6969ca742..5fdd6ffee 100644
--- a/extensions/EditComments/lib/WebService.pm
+++ b/extensions/EditComments/lib/WebService.pm
@@ -88,7 +88,7 @@ Bugzilla::Extension::EditComments::Webservice - The EditComments WebServices API
=head1 DESCRIPTION
-This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+This module contains API methods that are useful to users of bugzilla.mozilla.org.
=head1 METHODS
diff --git a/extensions/Ember/lib/WebService.pm b/extensions/Ember/lib/WebService.pm
index 10c828537..2e00773f2 100644
--- a/extensions/Ember/lib/WebService.pm
+++ b/extensions/Ember/lib/WebService.pm
@@ -781,7 +781,7 @@ Bugzilla::Extension::Ember::Webservice - The BMO Ember WebServices API
=head1 DESCRIPTION
-This module contains API methods that are useful to user's of the Bugzilla Ember
+This module contains API methods that are useful to users of the Bugzilla Ember
based UI.
=head1 METHODS
diff --git a/extensions/FlagTypeComment/Extension.pm b/extensions/FlagTypeComment/Extension.pm
index 3ec506176..e7b34113d 100644
--- a/extensions/FlagTypeComment/Extension.pm
+++ b/extensions/FlagTypeComment/Extension.pm
@@ -127,13 +127,18 @@ sub _set_ftc_states {
'active_or_has_flags' => $bug->id,
});
- my $types = join(',', map { $_->id } @$flag_types);
- my $states = "'" . join("','", FLAGTYPE_COMMENT_STATES) . "'";
- $db_result = $dbh->selectall_arrayref(
- "SELECT type_id AS flagtype, on_status AS state, comment AS text
- FROM flagtype_comments
- WHERE type_id IN ($types) AND on_status IN ($states)",
- { Slice => {} });
+ if (@$flag_types) {
+ my $types = join(',', map { $_->id } @$flag_types);
+ my $states = "'" . join("','", FLAGTYPE_COMMENT_STATES) . "'";
+ $db_result = $dbh->selectall_arrayref(
+ "SELECT type_id AS flagtype, on_status AS state, comment AS text
+ FROM flagtype_comments
+ WHERE type_id IN ($types) AND on_status IN ($states)",
+ { Slice => {} });
+ }
+ else {
+ $db_result = [];
+ }
}
foreach my $row (@$db_result) {
diff --git a/extensions/GuidedBugEntry/disabled b/extensions/GuidedBugEntry/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/GuidedBugEntry/disabled
diff --git a/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl
index e1a9e0bc5..7ffa04922 100644
--- a/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl
+++ b/extensions/GuidedBugEntry/template/en/default/guided/guided.html.tmpl
@@ -356,7 +356,7 @@ Product: <b><span id="dupes_product_name">?</span></b>:
<ul>
<li>Please fill out this form clearly, precisely and in as much detail as you can manage.</li>
<li>Please report only a single problem at a time.</li>
-<li><a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines" target="_blank" rel="noopener noreferrer">These guidelines</a>
+<li><a href="[% terms.BugWritingGuidelinesURL %]" target="_blank" rel="noopener noreferrer">These guidelines</a>
explain how to write effective [% terms.bug %] reports.</li>
</ul>
diff --git a/extensions/MyDashboard/lib/WebService.pm b/extensions/MyDashboard/lib/WebService.pm
index 5407c1d0b..5ab849350 100644
--- a/extensions/MyDashboard/lib/WebService.pm
+++ b/extensions/MyDashboard/lib/WebService.pm
@@ -172,7 +172,7 @@ Bugzilla::Extension::MyDashboard::Webservice - The MyDashboard WebServices API
=head1 DESCRIPTION
-This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+This module contains API methods that are useful to users of bugzilla.mozilla.org.
=head1 METHODS
diff --git a/extensions/PhabBugz/disabled b/extensions/PhabBugz/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/PhabBugz/disabled
diff --git a/extensions/PhabBugz/lib/Util.pm b/extensions/PhabBugz/lib/Util.pm
index 5dbe31d0e..5ad8a5207 100644
--- a/extensions/PhabBugz/lib/Util.pm
+++ b/extensions/PhabBugz/lib/Util.pm
@@ -107,7 +107,7 @@ sub get_bug_role_phids {
my @bug_users = ( $bug->reporter );
push(@bug_users, $bug->assigned_to)
- if $bug->assigned_to->email !~ /^nobody\@mozilla\.org$/;
+ if $bug->assigned_to->email != Bugzilla->params->{'nobody_user'};
push(@bug_users, $bug->qa_contact) if $bug->qa_contact;
push(@bug_users, @{ $bug->cc_users }) if @{ $bug->cc_users };
diff --git a/extensions/Push/Config.pm b/extensions/Push/Config.pm
index 860e31a23..59b78d5a2 100644
--- a/extensions/Push/Config.pm
+++ b/extensions/Push/Config.pm
@@ -42,12 +42,6 @@ use constant REQUIRED_MODULES => [
];
use constant OPTIONAL_MODULES => [
- # connectors need the ability to extend this
- {
- package => 'Net-SFTP',
- module => 'Net::SFTP',
- version => '0'
- },
{
package => 'XML-Simple',
module => 'XML::Simple',
diff --git a/extensions/Push/disabled b/extensions/Push/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/Push/disabled
diff --git a/extensions/Push/lib/Connector/TCL.pm b/extensions/Push/lib/Connector/TCL.pm
deleted file mode 100644
index f5b430e47..000000000
--- a/extensions/Push/lib/Connector/TCL.pm
+++ /dev/null
@@ -1,353 +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::Extension::Push::Connector::TCL;
-
-use 5.10.1;
-use strict;
-use warnings;
-
-use base 'Bugzilla::Extension::Push::Connector::Base';
-
-use Bugzilla::Constants;
-use Bugzilla::Extension::Push::Constants;
-use Bugzilla::Extension::Push::Serialise;
-use Bugzilla::Extension::Push::Util;
-use Bugzilla::User;
-use Bugzilla::Attachment;
-
-use Digest::MD5 qw(md5_hex);
-use Encode qw(encode_utf8);
-
-sub options {
- return (
- {
- name => 'tcl_user',
- label => 'Bugzilla TCL User',
- type => 'string',
- default => 'tcl@bugzilla.tld',
- required => 1,
- validate => sub {
- Bugzilla::User->new({ name => $_[0] })
- || die "Invalid Bugzilla user ($_[0])\n";
- },
- },
- {
- name => 'sftp_host',
- label => 'SFTP Host',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'sftp_port',
- label => 'SFTP Port',
- type => 'string',
- default => '22',
- required => 1,
- validate => sub {
- $_[0] =~ /\D/ && die "SFTP Port must be an integer\n";
- },
- },
- {
- name => 'sftp_user',
- label => 'SFTP Username',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'sftp_pass',
- label => 'SFTP Password',
- type => 'password',
- default => '',
- required => 1,
- },
- {
- name => 'sftp_remote_path',
- label => 'SFTP Remote Path',
- type => 'string',
- default => '',
- required => 0,
- },
- );
-}
-
-my $_instance;
-
-sub init {
- my ($self) = @_;
- $_instance = $self;
-}
-
-sub load_config {
- my ($self) = @_;
- $self->SUPER::load_config(@_);
-}
-
-sub should_send {
- my ($self, $message) = @_;
-
- my $data = $message->payload_decoded;
- my $bug_data = $self->_get_bug_data($data)
- || return 0;
-
- # sanity check user
- $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} });
- if (!$self->{tcl_user} || !$self->{tcl_user}->is_enabled) {
- return 0;
- }
-
- # only send bugs created by the tcl user
- unless ($bug_data->{reporter}->{id} == $self->{tcl_user}->id) {
- return 0;
- }
-
- # don't push changes made by the tcl user
- if ($data->{event}->{user}->{id} == $self->{tcl_user}->id) {
- return 0;
- }
-
- # send comments
- if ($data->{event}->{routing_key} eq 'comment.create') {
- return 0 if $data->{comment}->{is_private};
- return 1;
- }
-
- # send status and resolution updates
- foreach my $change (@{ $data->{event}->{changes} }) {
- return 1 if $change->{field} eq 'bug_status'
- || $change->{field} eq 'resolution'
- || $change->{field} eq 'cf_blocking_b2g';
- }
-
- # send attachments
- if ($data->{event}->{routing_key} =~ /^attachment\./) {
- return 0 if $data->{attachment}->{is_private};
- return 1;
- }
-
- # and nothing else
- return 0;
-}
-
-sub send {
- my ($self, $message) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- require XML::Simple;
- require Net::SFTP;
-
- $self->{tcl_user} ||= Bugzilla::User->new({ name => $self->config->{tcl_user} });
- if (!$self->{tcl_user}) {
- return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{tcl_user} . ")");
- }
-
- # load the bug
- my $data = $message->payload_decoded;
- my $bug_data = $self->_get_bug_data($data);
-
- # build payload
- my $attachment;
- my %xml = (
- Mozilla_ID => $bug_data->{id},
- When => $data->{event}->{time},
- Who => $data->{event}->{user}->{login},
- Status => $bug_data->{status}->{name},
- Resolution => $bug_data->{resolution},
- Blocking_B2G => $bug_data->{cf_blocking_b2g},
- );
- if ($data->{event}->{routing_key} eq 'comment.create') {
- $xml{Comment} = $data->{comment}->{body};
- } elsif ($data->{event}->{routing_key} =~ /^attachment\.(\w+)/) {
- my $is_update = $1 eq 'modify';
- if (!$is_update) {
- $attachment = Bugzilla::Attachment->new($data->{attachment}->{id});
- }
- $xml{Attach} = {
- Attach_ID => $data->{attachment}->{id},
- Filename => $data->{attachment}->{file_name},
- Description => $data->{attachment}->{description},
- ContentType => $data->{attachment}->{content_type},
- IsPatch => $data->{attachment}->{is_patch} ? 'true' : 'false',
- IsObsolete => $data->{attachment}->{is_obsolete} ? 'true' : 'false',
- IsUpdate => $is_update ? 'true' : 'false',
- };
- }
-
- # convert to xml
- my $xml = XML::Simple::XMLout(
- \%xml,
- NoAttr => 1,
- RootName => 'sync',
- XMLDecl => 1,
- );
- $xml = encode_utf8($xml);
-
- # generate md5
- my $md5 = md5_hex($xml);
-
- # build filename
- my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
- my $change_set = $data->{event}->{change_set};
- $change_set =~ s/\.//g;
- my $filename = sprintf(
- '%04s%02d%02d%02d%02d%02d%s',
- $year + 1900,
- $mon + 1,
- $day,
- $hour,
- $min,
- $sec,
- $change_set,
- );
-
- # create temp files;
- my $temp_dir = File::Temp::Directory->new();
- my $local_dir = $temp_dir->dirname;
- _write_file("$local_dir/$filename.sync", $xml);
- _write_file("$local_dir/$filename.sync.check", $md5);
- _write_file("$local_dir/$filename.done", '');
- if ($attachment) {
- _write_file("$local_dir/$filename.sync.attach", $attachment->data);
- }
-
- my $remote_dir = $self->config->{sftp_remote_path} eq ''
- ? ''
- : $self->config->{sftp_remote_path} . '/';
-
- # send files via sftp
- $logger->debug("Connecting to " . $self->config->{sftp_host} . ":" . $self->config->{sftp_port});
- my $sftp = Net::SFTP->new(
- $self->config->{sftp_host},
- ssh_args => {
- port => $self->config->{sftp_port},
- },
- user => $self->config->{sftp_user},
- password => $self->config->{sftp_pass},
- );
-
- $logger->debug("Uploading $local_dir/$filename.sync");
- $sftp->put("$local_dir/$filename.sync", "$remote_dir$filename.sync")
- or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync");
-
- $logger->debug("Uploading $local_dir/$filename.sync.check");
- $sftp->put("$local_dir/$filename.sync.check", "$remote_dir$filename.sync.check")
- or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.check");
-
- if ($attachment) {
- $logger->debug("Uploading $local_dir/$filename.sync.attach");
- $sftp->put("$local_dir/$filename.sync.attach", "$remote_dir$filename.sync.attach")
- or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.sync.attach");
- }
-
- $logger->debug("Uploading $local_dir/$filename.done");
- $sftp->put("$local_dir/$filename.done", "$remote_dir$filename.done")
- or return (PUSH_RESULT_ERROR, "Failed to upload $local_dir/$filename.done");
-
- # success
- return (PUSH_RESULT_OK, "uploaded $filename.sync");
-}
-
-sub _get_bug_data {
- my ($self, $data) = @_;
- my $target = $data->{event}->{target};
- if ($target eq 'bug') {
- return $data->{bug};
- } elsif (exists $data->{$target}->{bug}) {
- return $data->{$target}->{bug};
- } else {
- return;
- }
-}
-
-sub _write_file {
- my ($filename, $content) = @_;
- open(my $fh, ">", $filename) or die "Failed to write to $filename: $!\n";
- binmode($fh);
- print $fh $content;
- close($fh) or die "Failed to write to $filename: $!\n";
-}
-
-1;
-
-# File::Temp->newdir() requires a newer version of File::Temp than we have on
-# production, so here's a small inline package which performs the same task.
-
-package File::Temp::Directory;
-
-use strict;
-use warnings;
-
-use File::Temp;
-use File::Path qw(rmtree);
-use File::Spec;
-
-my @chars;
-
-sub new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
-
- @chars = qw/ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
- a b c d e f g h i j k l m n o p q r s t u v w x y z
- 0 1 2 3 4 5 6 7 8 9 _
- /;
-
- $self->{TEMPLATE} = File::Spec->catdir(File::Spec->tmpdir, 'X' x 10);
- $self->{DIRNAME} = $self->_mktemp();
- return $self;
-}
-
-sub _mktemp {
- my ($self) = @_;
- my $path = $self->_random_name();
- while(1) {
- if (mkdir($path, 0700)) {
- # in case of odd umask
- chmod(0700, $path);
- return $path;
- } else {
- # abort with error if the reason for failure was anything except eexist
- die "Could not create directory $path: $!\n" unless ($!{EEXIST});
- # loop round for another try
- }
- $path = $self->_random_name();
- }
-
- return $path;
-}
-
-sub _random_name {
- my ($self) = @_;
- my $path = $self->{TEMPLATE};
- $path =~ s/X/$chars[int(rand(@chars))]/ge;
- return $path;
-}
-
-sub dirname {
- my ($self) = @_;
- return $self->{DIRNAME};
-}
-
-sub DESTROY {
- my ($self) = @_;
- local($., $@, $!, $^E, $?);
- if (-d $self->{DIRNAME}) {
- # Some versions of rmtree will abort if you attempt to remove the
- # directory you are sitting in. We protect that and turn it into a
- # warning. We do this because this occurs during object destruction and
- # so can not be caught by the user.
- eval { rmtree($self->{DIRNAME}, 0, 0); };
- warn $@ if ($@ && $^W);
- }
-}
-
-1;
-
diff --git a/extensions/RestrictComments/Extension.pm b/extensions/RestrictComments/Extension.pm
index 213a1c44a..e93540d5a 100644
--- a/extensions/RestrictComments/Extension.pm
+++ b/extensions/RestrictComments/Extension.pm
@@ -68,7 +68,9 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::Bug')) {
- push(@$columns, 'restrict_comments');
+ if (Bugzilla->dbh->bz_column_info($class->DB_TABLE, 'restrict_comments')) {
+ push @$columns, 'restrict_comments';
+ }
}
}
diff --git a/extensions/Review/Extension.pm b/extensions/Review/Extension.pm
index 406c29c7c..a918a5ca5 100644
--- a/extensions/Review/Extension.pm
+++ b/extensions/Review/Extension.pm
@@ -286,10 +286,14 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::Product')) {
- push @$columns, 'reviewer_required';
+ my $dbh = Bugzilla->dbh;
+ my @new_columns = qw(reviewer_required);
+ push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns;
}
elsif ($class->isa('Bugzilla::User')) {
- push @$columns, qw(review_request_count feedback_request_count needinfo_request_count);
+ my $dbh = Bugzilla->dbh;
+ my @new_columns = qw(review_request_count feedback_request_count needinfo_request_count);
+ push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns;
}
}
diff --git a/extensions/Review/bin/migrate_mentor_from_whiteboard.pl b/extensions/Review/bin/migrate_mentor_from_whiteboard.pl
index c6b69006f..debf173a7 100755
--- a/extensions/Review/bin/migrate_mentor_from_whiteboard.pl
+++ b/extensions/Review/bin/migrate_mentor_from_whiteboard.pl
@@ -36,7 +36,7 @@ EOF
<>;
# we need to be logged in to do user searching and update bugs
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} });
$nobody->{groups} = [ Bugzilla::Group->get_all ];
Bugzilla->set_user($nobody);
diff --git a/extensions/Review/lib/WebService.pm b/extensions/Review/lib/WebService.pm
index 3f6816916..0c54d725a 100644
--- a/extensions/Review/lib/WebService.pm
+++ b/extensions/Review/lib/WebService.pm
@@ -51,7 +51,7 @@ sub suggestions {
# we always need to be authentiated to perform user matching
my $user = Bugzilla->user;
if (!$user->id) {
- Bugzilla->set_user(Bugzilla::User->check({ name => 'nobody@mozilla.org' }));
+ Bugzilla->set_user(Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} }));
push @reviewers, @{ $bug->mentors };
Bugzilla->set_user($user);
} else {
diff --git a/extensions/SecureMail/Extension.pm b/extensions/SecureMail/Extension.pm
index 508b1f5e8..2b5e1bdd6 100644
--- a/extensions/SecureMail/Extension.pm
+++ b/extensions/SecureMail/Extension.pm
@@ -104,7 +104,10 @@ sub object_columns {
my $columns = $args->{'columns'};
if ($class->isa('Bugzilla::Group')) {
- push(@$columns, 'secure_mail');
+ my $dbh = Bugzilla->dbh;
+ if ($dbh->bz_column_info($class->DB_TABLE, 'secure_mail')) {
+ push @$columns, 'secure_mail';
+ }
}
}
diff --git a/extensions/TagNewUsers/Extension.pm b/extensions/TagNewUsers/Extension.pm
index b94873979..1810f204f 100644
--- a/extensions/TagNewUsers/Extension.pm
+++ b/extensions/TagNewUsers/Extension.pm
@@ -123,7 +123,9 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::User')) {
- push(@$columns, qw(comment_count creation_ts first_patch_bug_id));
+ my $dbh = Bugzilla->dbh;
+ my @new_columns = qw(comment_count creation_ts first_patch_bug_id);
+ push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns;
}
}
@@ -131,9 +133,14 @@ sub object_before_create {
my ($self, $args) = @_;
my ($class, $params) = @$args{qw(class params)};
if ($class->isa('Bugzilla::User')) {
- my ($timestamp) = Bugzilla->dbh->selectrow_array("SELECT NOW()");
- $params->{comment_count} = 0;
- $params->{creation_ts} = $timestamp;
+ my $dbh = Bugzilla->dbh;
+ my ($timestamp) = $dbh->selectrow_array("SELECT NOW()");
+ if ($dbh->bz_column_info($class->DB_TABLE, 'comment_count')) {
+ $params->{comment_count} = 0;
+ }
+ if ($dbh->bz_column_info($class->DB_TABLE, 'creation_ts')) {
+ $params->{creation_ts} = $timestamp;
+ }
} elsif ($class->isa('Bugzilla::Attachment')) {
if ($params->{ispatch} && !Bugzilla->user->first_patch_bug_id) {
Bugzilla->user->first_patch_bug_id($params->{bug}->id);
diff --git a/extensions/TrackingFlags/bin/bug_825946.pl b/extensions/TrackingFlags/bin/bug_825946.pl
index 3f380b7ac..896dc5448 100755
--- a/extensions/TrackingFlags/bin/bug_825946.pl
+++ b/extensions/TrackingFlags/bin/bug_825946.pl
@@ -24,7 +24,7 @@ use Bugzilla::Bug qw(LogActivityEntry);
Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
my $dbh = Bugzilla->dbh;
-my $user = Bugzilla::User->check({name => 'nobody@mozilla.org'});
+my $user = Bugzilla::User->check({name => Bugzilla->params->{'nobody_user'}});
my $tf_vis = $dbh->selectall_arrayref(<<SQL);
SELECT
diff --git a/extensions/TrackingFlags/bin/bulk_flag_clear.pl b/extensions/TrackingFlags/bin/bulk_flag_clear.pl
index 1745018d5..305fbf883 100755
--- a/extensions/TrackingFlags/bin/bulk_flag_clear.pl
+++ b/extensions/TrackingFlags/bin/bulk_flag_clear.pl
@@ -110,7 +110,7 @@ if (!$config->{update_db}) {
# update bugs
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org' });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'} });
# put our nobody user into all groups to avoid permissions issues
$nobody->{groups} = [Bugzilla::Group->get_all];
Bugzilla->set_user($nobody);
diff --git a/extensions/TrackingFlags/disabled b/extensions/TrackingFlags/disabled
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/extensions/TrackingFlags/disabled
diff --git a/extensions/UserProfile/Extension.pm b/extensions/UserProfile/Extension.pm
index 079f7a948..9171b942d 100644
--- a/extensions/UserProfile/Extension.pm
+++ b/extensions/UserProfile/Extension.pm
@@ -385,7 +385,9 @@ sub object_columns {
my ($self, $args) = @_;
my ($class, $columns) = @$args{qw(class columns)};
if ($class->isa('Bugzilla::User')) {
- push(@$columns, qw(last_activity_ts last_statistics_ts));
+ my $dbh = Bugzilla->dbh;
+ my @new_columns = qw(last_activity_ts last_statistics_ts);
+ push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns;
}
}
diff --git a/heartbeat.cgi b/heartbeat.cgi
index 493674c16..11bb3ac30 100755
--- a/heartbeat.cgi
+++ b/heartbeat.cgi
@@ -44,4 +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"; \ No newline at end of file
+print $ok ? "Bugzilla OK\n" : "Bugzilla NOT OK\n";
diff --git a/js/instant-search.js b/js/instant-search.js
index 6e8f104f2..183d5a3be 100644
--- a/js/instant-search.js
+++ b/js/instant-search.js
@@ -138,7 +138,7 @@ YAHOO.bugzilla.instantSearch = {
YAHOO.bugzilla.instantSearch.dataTable.showTableMessage(
'Searching...&nbsp;&nbsp;&nbsp;' +
- '<img src="extensions/GuidedBugEntry/web/images/throbber.gif"' +
+ '<img src="images/throbber.gif"' +
' width="16" height="11">',
YAHOO.widget.DataTable.CLASS_LOADING
);
@@ -191,7 +191,7 @@ YAHOO.bugzilla.instantSearch = {
var result = [];
var name = Dom.get('product').value;
result.push(name);
- if (products[name] && products[name].related) {
+ if (typeof products !== 'undefined' && products[name] && products[name].related) {
for (var i = 0, n = products[name].related.length; i < n; i++) {
result.push(products[name].related[i]);
}
diff --git a/scripts/eject-users-from-groups.pl b/scripts/eject-users-from-groups.pl
index 52e2bbbf3..4b27be83d 100755
--- a/scripts/eject-users-from-groups.pl
+++ b/scripts/eject-users-from-groups.pl
@@ -23,7 +23,7 @@ Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
my $dbh = Bugzilla->dbh;
my @remove_group_names;
-my $nobody_name = 'nobody@mozilla.org';
+my $nobody_name = Bugzilla->params->{'nobody_user'};
my $admin_name = 'automation@bmo.tld';
GetOptions(
diff --git a/scripts/entrypoint.pl b/scripts/entrypoint.pl
index 21d9aebb1..f5c52f6a6 100755
--- a/scripts/entrypoint.pl
+++ b/scripts/entrypoint.pl
@@ -57,11 +57,6 @@ check_env(qw(
BMO_urlbase
));
-if ( $ENV{BMO_urlbase} eq 'AUTOMATIC' ) {
- $ENV{BMO_urlbase} = sprintf 'http://%s:%d/%s', hostname(), $ENV{PORT}, $ENV{BZ_QA_LEGACY_MODE} ? 'bmo/' : '';
- $ENV{BZ_BASE_URL} = sprintf 'http://%s:%d', hostname(), $ENV{PORT};
-}
-
$func->($opts->());
sub cmd_demo {
@@ -110,6 +105,11 @@ sub cmd_dev_httpd {
exit $httpd_exit_f->get;
}
+sub cmd_checksetup_gen_files {
+ my (@args) = @_;
+ run( 'perl', 'checksetup.pl', '--no-database', @args);
+}
+
sub cmd_checksetup {
check_data_dir();
wait_for_db();
@@ -140,7 +140,7 @@ sub cmd_test_webservices {
check_data_dir();
copy_qa_extension();
assert_database()->get;
- my $httpd_exit_f = run_cereal_and_httpd('-DHTTPD_IN_SUBDIR', '-DACCESS_LOGS');
+ my $httpd_exit_f = run_cereal_and_httpd('-DHTTPD_IN_SUBDIR');
my $prove_exit_f = run_prove(
httpd_url => $conf->{browser_url},
prove_cmd => [
@@ -195,7 +195,7 @@ sub cmd_test_bmo {
$ENV{BZ_TEST_NEWBIE2} = 'newbie2@mozilla.example';
$ENV{BZ_TEST_NEWBIE2_PASS} = 'captain.space.pants.time.lord';
- my $httpd_exit_f = run_cereal_and_httpd('-DACCESS_LOGS');
+ my $httpd_exit_f = run_cereal_and_httpd();
my $prove_exit_f = run_prove(
httpd_url => $ENV{BZ_BASE_URL},
prove_cmd => [ 'prove', '-I/app', '-I/app/local/lib/perl5', @prove_args ],
@@ -244,6 +244,10 @@ sub copy_qa_extension {
dircopy('/app/qa/extensions/QA', '/app/extensions/QA');
}
+sub cmd_wait_for_db {
+ wait_for_db();
+}
+
sub wait_for_db {
assert_database()->get;
}
diff --git a/scripts/generate_bmo_data.pl b/scripts/generate_bmo_data.pl
index 6356762c8..8a9f72d17 100755
--- a/scripts/generate_bmo_data.pl
+++ b/scripts/generate_bmo_data.pl
@@ -158,7 +158,7 @@ $group->update();
my @users = (
{
- login => 'nobody@mozilla.org',
+ login => Bugzilla->params->{'nobody_user'},
realname => 'Nobody; OK to take it and work on it',
password => '*'
},
@@ -267,7 +267,7 @@ my @products = (
name => 'General',
description => 'For bugs in Firefox which do not fit into ' .
'other more specific Firefox components',
- initialowner => 'nobody@mozilla.org',
+ initialowner => Bugzilla->params->{'nobody_user'},
initialqaowner => '',
initial_cc => [],
watch_user => 'general@firefox.bugs'
@@ -287,7 +287,7 @@ my @products = (
name => 'General',
description => 'This is the component for issues specific to bugzilla.mozilla.org '
. 'that do not belong in other components.',
- initialowner => 'nobody@mozilla.org',
+ initialowner => Bugzilla->params->{'nobody_user'},
initialqaowner => '',
initial_cc => [],
watch_user => 'general@bugzilla.bugs'
diff --git a/scripts/move_os.pl b/scripts/move_os.pl
index 546b47c7e..963188261 100755
--- a/scripts/move_os.pl
+++ b/scripts/move_os.pl
@@ -40,7 +40,7 @@ my $dbh = Bugzilla->dbh;
my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
my $bug_ids = $dbh->selectcol_arrayref(q{SELECT bug_id FROM bugs WHERE bugs.op_sys = ?}, undef, $from_os);
my $field = Bugzilla::Field->check({ name => 'op_sys', cache => 1 });
-my $nobody = Bugzilla::User->check({ name => 'nobody@mozilla.org', cache => 1 });
+my $nobody = Bugzilla::User->check({ name => Bugzilla->params->{'nobody_user'}, cache => 1 });
my $bug_count = @$bug_ids;
if ($bug_count == 0) {
diff --git a/scripts/movebugs.pl b/scripts/movebugs.pl
index 2c643cdfb..55a43d943 100755
--- a/scripts/movebugs.pl
+++ b/scripts/movebugs.pl
@@ -73,10 +73,12 @@ my $component_field_id = $dbh->selectrow_array(
$component_field_id
or die "Can't find field ID for 'component' field\n";
+my $nobody = Bugzilla->params->{'nobody_user'};
my $user_id = $dbh->selectrow_array(
- "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'");
+ "SELECT userid FROM profiles WHERE login_name=?",
+ undef, $nobody);
$user_id
- or die "Can't find user ID for 'nobody\@mozilla.org'\n";
+ or die "Can't find user ID for '$nobody'\n";
$dbh->bz_start_transaction();
diff --git a/scripts/nagios_blocker_checker.pl b/scripts/nagios_blocker_checker.pl
index a02a1602a..01a7b7348 100755
--- a/scripts/nagios_blocker_checker.pl
+++ b/scripts/nagios_blocker_checker.pl
@@ -28,7 +28,7 @@ my $config = {
assignee => '',
product => '',
component => '',
- unassigned => 'nobody@mozilla.org',
+ unassigned => Bugzilla->params->{'nobody_user'},
# severities
severity => 'major,critical,blocker',
# time in hours to wait before paging/warning
diff --git a/scripts/remove_idle_group_members.pl b/scripts/remove_idle_group_members.pl
index 74e8658ff..e4ef88bc1 100755
--- a/scripts/remove_idle_group_members.pl
+++ b/scripts/remove_idle_group_members.pl
@@ -78,7 +78,7 @@ foreach my $group_id (keys %remove_data) {
$dbh->bz_commit_transaction();
# nobody@mozilla.org cannot recieve email
- next if $group->owner->login eq 'nobody@mozilla.org';
+ next if $group->owner->login eq Bugzilla->params->{'nobody_user'};
_send_email($group, \@users_removed);
}
diff --git a/scripts/reset_default_user.pl b/scripts/reset_default_user.pl
index d0d2534f2..942afda17 100755
--- a/scripts/reset_default_user.pl
+++ b/scripts/reset_default_user.pl
@@ -52,7 +52,7 @@ if (!$product || $help
}
# We will need these for entering into bugs_activity
-my $who = Bugzilla::User->new({ name => 'nobody@mozilla.org' });
+my $who = Bugzilla::User->new({ name => Bugzilla->params->{'nobody_user'} });
my $field = Bugzilla::Field->new({ name => $field_name });
trick_taint($product);
diff --git a/scripts/rewrite2mojo.pl b/scripts/rewrite2mojo.pl
new file mode 100755
index 000000000..bae6d514b
--- /dev/null
+++ b/scripts/rewrite2mojo.pl
@@ -0,0 +1,70 @@
+#!/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 Mojo::Parameters;
+use Data::Dumper;
+
+while (<>) {
+ my ($cmd, @args) = split /\s+/, $_;
+ next unless $cmd;
+ if (lc($cmd) eq "\LRewriteRule") {
+ my ($regex, $target, $flags) = @args;
+ $flags //= '';
+ next if $flags =~ /E=HTTP/;
+ next if $target eq '-';
+ my $action = 'rewrite_query';
+ if ($flags =~ /R/) {
+ next;
+ }
+ my ($script, $query) = $target =~ /^([^?]+)(?:\?(.+))?$/;
+ my $name = _file_to_method($script);
+ $regex =~ s/^\^//;
+ $regex =~ s/\$$//;
+ my $regex_name = _regex_to_name($regex);
+ my $param_hash = Mojo::Parameters->new($query)->to_hash;
+ my $param_str = Data::Dumper->new([$param_hash])->Terse(1)->Indent(0)->Dump;
+ say "\$r->any('/:$regex_name' => [$regex_name => qr{$regex}])->to(";
+ say " 'CGI#$name' => $param_str";
+ say ");";
+
+ }
+ # elsif (lc($cmd) eq "\LRedirect") {
+ # my ($type, $path, $url) = @args;
+ # if ($type eq 'permanent') {
+ # say "if (\$path =~ m{^\Q$path\E}s) {";
+ # say " redirect(\$c, q{$url});";
+ # say " return;";
+ # say "}";
+ # }
+ # else {
+ # warn "I don't understand Redirect $type\n";
+ # }
+ # }
+}
+
+sub _file_to_method {
+ my ($name) = @_;
+ $name =~ s/\./_/s;
+ $name =~ s/\W+/_/gs;
+ return $name;
+}
+
+sub _regex_to_name {
+ my ($name) = @_;
+ $name =~ s/\./_/s;
+ $name =~ s/\W+/_/gs;
+ $name =~ s/_+/_/g;
+ $name =~ s/^_//s;
+ $name =~ s/_$//s;
+ return $name;
+}
+
+
diff --git a/t/bmo/comments.t b/t/bmo/comments.t
index 4b0bb8177..00002040c 100644
--- a/t/bmo/comments.t
+++ b/t/bmo/comments.t
@@ -35,7 +35,7 @@ my $bug_1 = Bugzilla::Bug->create(
keywords => [],
cc => [],
comment => 'This is a brand new bug',
- assigned_to => 'nobody@mozilla.org',
+ assigned_to => Bugzilla->params->{'nobody_user'},
}
);
ok($bug_1->id, "got a new bug");
@@ -55,7 +55,7 @@ my $bug_2 = Bugzilla::Bug->create(
keywords => [],
cc => [],
comment => "This is related to ${urlbase}show_bug.cgi?id=$bug_1_id",
- assigned_to => 'nobody@mozilla.org',
+ assigned_to => Bugzilla->params->{'nobody_user'},
}
);
diff --git a/t/docker.t b/t/docker.t
index 3c8cd055b..c1f85088c 100644
--- a/t/docker.t
+++ b/t/docker.t
@@ -28,7 +28,7 @@ while (my $line = readline $dockerfile_fh) {
close $dockerfile_fh;
my ($image, $version) = split(/:/ms, $base, 2);
-is($image, 'mozillabteam/bmo-slim', "base image is mozillabteam/bmo-slim");
+is($image, 'bugzilla/harmony-slim', "base image is bugzilla/harmony-slim");
like($version, qr/\d{4}\d{2}\d{2}\.\d+/ms, "version is YYYYMMDD.x");
my $regex = qr{
@@ -49,4 +49,4 @@ while (my $line = readline $ci_config_fh) {
}
close $ci_config_fh;
-done_testing; \ No newline at end of file
+done_testing;
diff --git a/template/en/default/account/prefs/account.html.tmpl b/template/en/default/account/prefs/account.html.tmpl
index 1e7bc25db..61ce80011 100644
--- a/template/en/default/account/prefs/account.html.tmpl
+++ b/template/en/default/account/prefs/account.html.tmpl
@@ -138,7 +138,7 @@
<td></td>
<td>
<p>
- Your contributions on bugzilla.mozilla.org will still be visible;
+ Your contributions on [% terms.Bugzilla %] will still be visible;
however, your email address and name will be removed in most locations.
We are not able to remove your details that are part of comment text.
</p>
diff --git a/template/en/default/attachment/create.html.tmpl b/template/en/default/attachment/create.html.tmpl
index 329e0ab49..7006448d3 100644
--- a/template/en/default/attachment/create.html.tmpl
+++ b/template/en/default/attachment/create.html.tmpl
@@ -83,14 +83,14 @@ TUI_hide_default('attachment_text_field');
<td>
<em>If you want to assign this [% terms.bug %] to yourself,
check the box below.</em><br>
- [% IF bug.assigned_to.login == "nobody@mozilla.org" || bug.assigned_to.login.search('.bugs$') %]
+ [% IF bug.assigned_to.login == Param('nobody_user') || bug.assigned_to.login.search('.bugs$') %]
[% take_if_patch = 1 %]
[% END %]
<input type="checkbox" id="takebug" name="takebug" value="1" [% IF take_if_patch %] data-take-if-patch="1" [% END %]>
<label for="takebug">take [% terms.bug %]</label>
[% bug_statuses = [] %]
[% FOREACH bug_status = bug.status.can_change_to %]
- [% NEXT IF bug_status.name == "UNCONFIRMED"
+ [% NEXT IF bug_status.name == "UNCONFIRMED"
&& !bug.product_obj.allows_unconfirmed %]
[% bug_statuses.push(bug_status) IF bug_status.is_open %]
[% END %]
diff --git a/template/en/default/bug/create/user-message.html.tmpl b/template/en/default/bug/create/user-message.html.tmpl
index fa42ace81..51e787870 100644
--- a/template/en/default/bug/create/user-message.html.tmpl
+++ b/template/en/default/bug/create/user-message.html.tmpl
@@ -30,7 +30,7 @@
[% PROCESS global/variables.none.tmpl %]
Before reporting [% terms.abug %], please read the
-<a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">
+<a href="[% terms.BugWritingGuidelinesURL %]">
[% terms.bug %] writing guidelines</a>, please look at the list of
<a href="duplicates.cgi">most frequently reported [% terms.bugs %]</a>, and please
<a href="query.cgi">search</a> for the [% terms.bug %].
diff --git a/template/en/default/bug/new_bug.html.tmpl b/template/en/default/bug/new_bug.html.tmpl
index ef5e361c0..9e0b2c1ab 100644
--- a/template/en/default/bug/new_bug.html.tmpl
+++ b/template/en/default/bug/new_bug.html.tmpl
@@ -27,10 +27,10 @@
<h2>Create New [% terms.Bug %]</h2>
<p>
Before reporting a [% terms.bug %], make sure you've read our
- <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">
+ <a href="[% terms.BugWritingGuidelinesURL %]">
[% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already
- been reported. Consult our list of <a href="https://bugzilla.mozilla.org/duplicates.cgi">
- most frequently reported [% terms.bugs %]</a> and <a href="https://bugzilla.mozilla.org/query.cgi">
+ been reported. Consult our list of <a href="duplicates.cgi">
+ most frequently reported [% terms.bugs %]</a> and <a href="query.cgi">
search through descriptions</a> of previously reported [% terms.bugs %].
</p>
</div>
diff --git a/template/en/default/global/variables.none.tmpl b/template/en/default/global/variables.none.tmpl
index faf1a5427..93002efa3 100644
--- a/template/en/default/global/variables.none.tmpl
+++ b/template/en/default/global/variables.none.tmpl
@@ -37,7 +37,9 @@
"bugs" => "bugs",
"Bugs" => "Bugs",
"zeroSearchResults" => "Zarro Boogs found",
- "Bugzilla" => "Bugzilla"
+ "Bugzilla" => "Bugzilla",
+
+ "BugWritingGuidelinesURL" => "https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines",
}
%]
diff --git a/template/en/default/index.html.tmpl b/template/en/default/index.html.tmpl
index e63bf0e87..2aff68615 100644
--- a/template/en/default/index.html.tmpl
+++ b/template/en/default/index.html.tmpl
@@ -76,7 +76,7 @@
<a href="page.cgi?id=etiquette.html">[%- terms.Bugzilla %] Etiquette</a>
</li>
<li>
- | <a href="https://developer.mozilla.org/docs/Mozilla/QA/Bug_writing_guidelines">[%- terms.Bug %] Writing Guidelines</a>
+ | <a href="[% terms.BugWritingGuidelinesURL %]">[%- terms.Bug %] Writing Guidelines</a>
</li>
[% Hook.process('additional_links') %]
</ul>
diff --git a/template/en/default/list/edit-multiple.html.tmpl b/template/en/default/list/edit-multiple.html.tmpl
index eb989d15c..ead3ff54c 100644
--- a/template/en/default/list/edit-multiple.html.tmpl
+++ b/template/en/default/list/edit-multiple.html.tmpl
@@ -437,7 +437,6 @@
[% FOREACH r = resolutions %]
[% NEXT IF !r %]
[% NEXT IF r == "DUPLICATE" || r == "MOVED" %]
- [% NEXT IF r == "EXPIRED" AND user.login != "gerv@mozilla.org" %]
<option value="[% r FILTER html %]">[% display_value("resolution", r) FILTER html %]</option>
[% END %]
</select>
diff --git a/template/en/default/list/table.html.tmpl b/template/en/default/list/table.html.tmpl
index df2f6b349..486f3a00a 100644
--- a/template/en/default/list/table.html.tmpl
+++ b/template/en/default/list/table.html.tmpl
@@ -90,7 +90,9 @@
<th class="sorttable_nosort">&nbsp;</th>
[% END %]
<th colspan="[% splitheader ? 2 : 1 %]" class="first-child
- sorted_[% lsearch(order_columns, 'bug_id') FILTER html %]">
+ [% order_columns.defined
+ ? 'sorted_' _ lsearch(order_columns, 'bug_id')
+ : '' FILTER html %]">
<a href="buglist.cgi?
[% urlquerypart FILTER html %]&amp;order=
[% PROCESS new_order id='bug_id' %]
@@ -136,7 +138,9 @@
[% BLOCK columnheader %]
<th colspan="[% splitheader ? 2 : 1 %]"
class="sortable_column_[% key FILTER html %]
- sorted_[% lsearch(order_columns, id) FILTER html %]">
+ [% order_columns.defined
+ ? 'sorted_' _ lsearch(order_columns, id)
+ : '' FILTER html %]">
<a href="buglist.cgi?[% urlquerypart FILTER html %]&amp;order=
[% PROCESS new_order %]
[%-#%]&amp;query_based_on=
diff --git a/template/en/default/search/search-google.html.tmpl b/template/en/default/search/search-google.html.tmpl
index 7fdc1daaa..1b07320ce 100644
--- a/template/en/default/search/search-google.html.tmpl
+++ b/template/en/default/search/search-google.html.tmpl
@@ -32,7 +32,7 @@
<p>
<form method="get" action="https://www.google.com/search" data-no-csrf>
-<input type="hidden" name="sitesearch" value="bugzilla.mozilla.org">
+<input type="hidden" name="sitesearch" value="[% urlbase.match('^([^:]*://)?(.*?)/?$').1 %]">
<nobr>
<input type="text" name="q" size="60" maxlength="255" value="">
<input type="submit" value="Search">
diff --git a/template/en/default/search/search-instant.html.tmpl b/template/en/default/search/search-instant.html.tmpl
index d0cf078e7..ed3942166 100644
--- a/template/en/default/search/search-instant.html.tmpl
+++ b/template/en/default/search/search-instant.html.tmpl
@@ -8,11 +8,15 @@
[% PROCESS global/variables.none.tmpl %]
+[% javascript_urls = [ 'js/instant-search.js' ] %]
+[% IF has_extension('GuidedBugEntry') %]
+ [% javascript_urls.import(['extensions/GuidedBugEntry/web/js/products.js']); %]
+[% END %]
+
[% PROCESS global/header.html.tmpl
title = "Instant Search"
generate_api_token = 1
- javascript_urls = [ 'extensions/GuidedBugEntry/web/js/products.js',
- 'js/instant-search.js', ]
+ javascript_urls = javascript_urls
%]
[% UNLESS default.exists('product') && default.product.size %]
diff --git a/votes.cgi b/votes.cgi
index d9dba1541..7c1fff67a 100755
--- a/votes.cgi
+++ b/votes.cgi
@@ -30,8 +30,7 @@ use lib qw(. lib local/lib/perl5);
use Bugzilla;
use Bugzilla::Error;
-my $is_enabled = grep { $_->NAME eq 'Voting' } @{ Bugzilla->extensions };
-$is_enabled || ThrowCodeError('extension_disabled', { name => 'Voting' });
+Bugzilla->has_extension('Voting') || ThrowCodeError('extension_disabled', { name => 'Voting' });
my $cgi = Bugzilla->cgi;
my $action = $cgi->param('action') || 'show_user';