From 57584dc4744fea59833ef355f7513690d246c70f Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Tue, 4 Oct 2011 18:25:23 -0400 Subject: more porting work --- .bzrignore | 1 - .htaccess | 15 + Bugzilla/Bug.pm | 43 ++- Bugzilla/BugMail.pm | 7 +- Bugzilla/Component.pm | 6 +- Bugzilla/Config/Advanced.pm | 6 + Bugzilla/Constants.pm | 26 +- Bugzilla/Error.pm | 40 ++- Bugzilla/Field.pm | 167 ++++++--- Bugzilla/Group.pm | 5 +- Bugzilla/Install.pm | 2 + Bugzilla/Install/DB.pm | 28 ++ Bugzilla/Install/Filesystem.pm | 14 +- Bugzilla/Product.pm | 5 +- Bugzilla/Search.pm | 3 +- Bugzilla/Search/Quicksearch.pm | 3 + Bugzilla/Template.pm | 13 +- Bugzilla/Token.pm | 2 + Bugzilla/User.pm | 7 +- Bugzilla/WebService/Bug.pm | 47 ++- Bugzilla/WebService/User.pm | 4 + attachment.cgi | 9 +- bzr-update.sh | 9 + chart.cgi | 3 +- contrib/addcustomfield.pl | 62 ++++ contrib/fix_comment_text.pl | 75 ++++ contrib/moco-ldap-check.pl | 224 ++++++++++++ contrib/reorg-tools/README | 9 + contrib/reorg-tools/bmo-plan.txt | 82 +++++ contrib/reorg-tools/fixgroupqueries.pl | 119 +++++++ contrib/reorg-tools/fixqueries.pl | 132 +++++++ contrib/reorg-tools/migrate_crash_signatures.pl | 126 +++++++ contrib/reorg-tools/move_flag_types.pl | 168 +++++++++ contrib/reorg-tools/movebugs.pl | 151 ++++++++ contrib/reorg-tools/movecomponent.pl | 193 ++++++++++ contrib/reorg-tools/syncflags.pl | 86 +++++ contrib/reorg-tools/syncmsandversions.pl | 107 ++++++ contrib/sanitizeme.pl | 176 +++++++++ contrib/verify-user.pl | 129 +++++++ enter_bug.cgi | 216 ++--------- extensions/BMO/Extension.pm | 233 +++++------- extensions/BMO/lib/Data.pm | 31 +- extensions/BMO/lib/FakeBug.pm | 2 - extensions/BMO/lib/Reports.pm | 62 +++- .../template/en/default/account/create.html.tmpl | 10 +- .../en/default/bug/create/comment-mozreps.txt.tmpl | 81 ----- .../bug/create/comment-remo-budget.txt.tmpl | 64 ---- .../default/bug/create/comment-remo-swag.txt.tmpl | 68 ---- .../default/bug/create/create-brownbag.html.tmpl | 35 +- .../default/bug/create/create-itrequest.html.tmpl | 27 +- .../default/bug/create/create-mktgevent.html.tmpl | 23 +- .../en/default/bug/create/create-mozlist.html.tmpl | 26 +- .../en/default/bug/create/create-mozpr.html.tmpl | 31 +- .../en/default/bug/create/create-mozreps.html.tmpl | 204 ----------- .../bug/create/create-presentation.html.tmpl | 4 +- .../bug/create/create-remo-budget.html.tmpl | 248 ------------- .../default/bug/create/create-remo-swag.html.tmpl | 292 --------------- .../en/default/bug/create/create-swag.html.tmpl | 30 +- .../en/default/bug/create/user-message.html.tmpl | 22 +- .../en/default/global/choose-product.html.tmpl | 5 +- .../hook/bug/create/create-guided-form.html.tmpl | 2 +- .../hook/bug/edit-after_custom_fields.html.tmpl | 1 + .../hook/global/header-additional_header.html.tmpl | 2 +- .../user-error-auth_failure_object.html.tmpl | 3 + .../hook/global/user-error-errors.html.tmpl | 19 +- .../auth_failure/permissions.html.tmpl | 2 +- .../default/hook/pages/fields-resolution.html.tmpl | 13 + .../en/default/hook/reports/menu-end.html.tmpl | 6 + .../en/default/list/list.microsummary.tmpl | 3 +- .../template/en/default/list/server-push.html.tmpl | 2 +- .../pages/comment-remo-form-payment.txt.tmpl | 37 -- .../template/en/default/pages/etiquette.html.tmpl | 42 +-- .../en/default/pages/group_admins.html.tmpl | 53 +++ .../en/default/pages/remo-form-payment.html.tmpl | 243 ------------- .../en/default/pages/triage_reports.html.tmpl | 6 +- .../en/default/pages/user_activity.html.tmpl | 8 +- extensions/BMO/web/js/edit_bug.js | 15 + extensions/BMO/web/js/edituser_menu.js | 26 ++ extensions/BMO/web/styles/moz_reps.css | 44 --- extensions/BMO/web/styles/reports.css | 37 ++ .../BzAPI/template/en/default/config.json.tmpl | 21 +- .../account/prefs/component_watch.html.tmpl | 10 +- extensions/Example/Extension.pm | 36 +- extensions/Example/lib/Config.pm | 2 - .../template/en/default/guided/guided.html.tmpl | 30 +- extensions/GuidedBugEntry/web/js/guided.js | 4 +- extensions/GuidedBugEntry/web/style/guided.css | 2 + extensions/InlineHistory/Config.pm | 31 ++ extensions/InlineHistory/Extension.pm | 183 ++++++++++ extensions/InlineHistory/README | 10 + .../hook/bug/comments-aftercomments.html.tmpl | 135 +++++++ .../en/default/hook/bug/show-header-end.html.tmpl | 33 ++ .../hook/global/setting-descs-settings.none.tmpl | 31 ++ extensions/InlineHistory/web/inline-history.js | 396 +++++++++++++++++++++ extensions/InlineHistory/web/style.css | 54 +++ extensions/REMO/Config.pm | 34 ++ extensions/REMO/Extension.pm | 184 ++++++++++ .../en/default/bug/create/comment-mozreps.txt.tmpl | 81 +++++ .../bug/create/comment-remo-budget.txt.tmpl | 64 ++++ .../default/bug/create/comment-remo-swag.txt.tmpl | 72 ++++ .../en/default/bug/create/create-mozreps.html.tmpl | 204 +++++++++++ .../bug/create/create-remo-budget.html.tmpl | 254 +++++++++++++ .../default/bug/create/create-remo-swag.html.tmpl | 305 ++++++++++++++++ .../default/bug/create/created-mozreps.html.tmpl | 38 ++ .../hook/global/user-error-errors.html.tmpl | 40 +++ .../pages/comment-remo-form-payment.txt.tmpl | 37 ++ .../en/default/pages/remo-form-payment.html.tmpl | 243 +++++++++++++ extensions/REMO/web/js/form_validate.js | 21 ++ extensions/REMO/web/js/swag.js | 60 ++++ extensions/REMO/web/styles/moz_reps.css | 44 +++ .../en/default/account/prefs/securemail.html.tmpl | 10 +- .../en/default/pages/securemail/help.html.tmpl | 8 +- extensions/SiteMapIndex/Extension.pm | 3 +- extensions/SiteMapIndex/lib/Util.pm | 4 +- extensions/Splinter/lib/Util.pm | 22 +- .../template/en/default/pages/splinter.html.tmpl | 13 +- .../en/default/pages/splinter/help.html.tmpl | 54 +-- extensions/Splinter/web/splinter.css | 13 + extensions/Splinter/web/splinter.js | 97 ++++- extensions/TagNewUsers/Extension.pm | 16 + .../en/default/hook/bug/comments-user.html.tmpl | 4 +- extensions/TypeSniffer/Extension.pm | 24 +- extensions/Voting/Extension.pm | 38 +- .../hook/admin/products/updated-changes.html.tmpl | 14 +- .../hook/bug/edit-after_importance.html.tmpl | 3 + .../en/default/pages/voting/user.html.tmpl | 11 +- js/comments.js | 27 ++ js/field.js | 5 +- mod_perl.pl | 2 +- post_bug.cgi | 6 + process_bug.cgi | 6 + quips.cgi | 1 + request.cgi | 10 +- robots.txt | 13 +- skins/contrib/Dusk-Helvetica/buglist.css | 24 ++ skins/contrib/Dusk-Helvetica/global.css | 263 ++++++++++++++ skins/contrib/Dusk-Helvetica/index.css | 9 + skins/contrib/Dusk-Segoe/buglist.css | 24 ++ skins/contrib/Dusk-Segoe/global.css | 263 ++++++++++++++ skins/contrib/Dusk-Segoe/index.css | 9 + skins/contrib/Dusk-Segoe/show_bug.css | 3 + skins/contrib/Dusk/global.css | 6 +- skins/custom/IE-fixes.css | 4 + skins/custom/buglist.css | 36 ++ skins/custom/global.css | 73 ++++ skins/custom/index.css | 11 + skins/custom/search_form.css | 6 + skins/custom/show_bug.css | 85 +++++ skins/standard/enter_bug.css | 2 +- skins/standard/guided.css | 4 + .../en/default/account/auth/login-small.html.tmpl | 4 +- template/en/default/account/auth/login.html.tmpl | 8 +- .../en/default/account/prefs/permissions.html.tmpl | 4 +- .../en/default/admin/params/advanced.html.tmpl | 3 + .../attachment/createformcontents.html.tmpl | 1 + template/en/default/bug/comments.html.tmpl | 53 ++- .../en/default/bug/create/comment-guided.txt.tmpl | 2 +- .../en/default/bug/create/create-guided.html.tmpl | 48 +-- template/en/default/bug/create/create.html.tmpl | 52 +-- template/en/default/bug/edit.html.tmpl | 224 +++++++----- template/en/default/bug/field.html.tmpl | 24 ++ .../default/bug/process/updates-disabled.html.tmpl | 73 ++++ template/en/default/bug/show-multiple.html.tmpl | 1 + template/en/default/bug/show.xml.tmpl | 5 +- template/en/default/config.rdf.tmpl | 3 +- template/en/default/email/bugmail.txt.tmpl | 6 + template/en/default/global/header.html.tmpl | 5 +- template/en/default/global/setting-descs.none.tmpl | 1 + template/en/default/global/user-error.html.tmpl | 34 ++ template/en/default/global/user.html.tmpl | 3 + template/en/default/list/edit-multiple.html.tmpl | 4 +- template/en/default/list/list.html.tmpl | 5 +- template/en/default/list/table.html.tmpl | 30 +- template/en/default/pages/bugzilla.dtd.tmpl | 179 ++++++++++ template/en/default/pages/fields.html.tmpl | 61 ++-- template/en/default/request/email.txt.tmpl | 3 +- template/en/default/search/field.html.tmpl | 2 +- template/en/default/search/search-google.html.tmpl | 57 +++ .../en/default/search/search-specific.html.tmpl | 11 +- template/en/default/search/tabs.html.tmpl | 4 +- 180 files changed, 7070 insertions(+), 2307 deletions(-) create mode 100644 bzr-update.sh create mode 100644 contrib/addcustomfield.pl create mode 100644 contrib/fix_comment_text.pl create mode 100644 contrib/moco-ldap-check.pl create mode 100644 contrib/reorg-tools/README create mode 100644 contrib/reorg-tools/bmo-plan.txt create mode 100644 contrib/reorg-tools/fixgroupqueries.pl create mode 100644 contrib/reorg-tools/fixqueries.pl create mode 100644 contrib/reorg-tools/migrate_crash_signatures.pl create mode 100644 contrib/reorg-tools/move_flag_types.pl create mode 100644 contrib/reorg-tools/movebugs.pl create mode 100644 contrib/reorg-tools/movecomponent.pl create mode 100644 contrib/reorg-tools/syncflags.pl create mode 100644 contrib/reorg-tools/syncmsandversions.pl create mode 100644 contrib/sanitizeme.pl create mode 100644 contrib/verify-user.pl delete mode 100644 extensions/BMO/template/en/default/bug/create/comment-mozreps.txt.tmpl delete mode 100644 extensions/BMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl delete mode 100644 extensions/BMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl delete mode 100644 extensions/BMO/template/en/default/bug/create/create-mozreps.html.tmpl delete mode 100644 extensions/BMO/template/en/default/bug/create/create-remo-budget.html.tmpl delete mode 100644 extensions/BMO/template/en/default/bug/create/create-remo-swag.html.tmpl create mode 100644 extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl create mode 100644 extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl delete mode 100644 extensions/BMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl create mode 100644 extensions/BMO/template/en/default/pages/group_admins.html.tmpl delete mode 100644 extensions/BMO/template/en/default/pages/remo-form-payment.html.tmpl create mode 100644 extensions/BMO/web/js/edituser_menu.js delete mode 100644 extensions/BMO/web/styles/moz_reps.css create mode 100644 extensions/BMO/web/styles/reports.css create mode 100644 extensions/InlineHistory/Config.pm create mode 100644 extensions/InlineHistory/Extension.pm create mode 100644 extensions/InlineHistory/README create mode 100644 extensions/InlineHistory/template/en/default/hook/bug/comments-aftercomments.html.tmpl create mode 100644 extensions/InlineHistory/template/en/default/hook/bug/show-header-end.html.tmpl create mode 100644 extensions/InlineHistory/template/en/default/hook/global/setting-descs-settings.none.tmpl create mode 100644 extensions/InlineHistory/web/inline-history.js create mode 100644 extensions/InlineHistory/web/style.css create mode 100644 extensions/REMO/Config.pm create mode 100644 extensions/REMO/Extension.pm create mode 100644 extensions/REMO/template/en/default/bug/create/comment-mozreps.txt.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/create-mozreps.html.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/create-remo-budget.html.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/create-remo-swag.html.tmpl create mode 100644 extensions/REMO/template/en/default/bug/create/created-mozreps.html.tmpl create mode 100644 extensions/REMO/template/en/default/hook/global/user-error-errors.html.tmpl create mode 100644 extensions/REMO/template/en/default/pages/comment-remo-form-payment.txt.tmpl create mode 100644 extensions/REMO/template/en/default/pages/remo-form-payment.html.tmpl create mode 100644 extensions/REMO/web/js/form_validate.js create mode 100644 extensions/REMO/web/js/swag.js create mode 100644 extensions/REMO/web/styles/moz_reps.css create mode 100644 skins/contrib/Dusk-Helvetica/buglist.css create mode 100644 skins/contrib/Dusk-Helvetica/global.css create mode 100644 skins/contrib/Dusk-Helvetica/index.css create mode 100644 skins/contrib/Dusk-Segoe/buglist.css create mode 100644 skins/contrib/Dusk-Segoe/global.css create mode 100644 skins/contrib/Dusk-Segoe/index.css create mode 100644 skins/contrib/Dusk-Segoe/show_bug.css create mode 100644 skins/custom/IE-fixes.css create mode 100644 skins/custom/buglist.css create mode 100644 skins/custom/global.css create mode 100644 skins/custom/index.css create mode 100644 skins/custom/search_form.css create mode 100644 skins/custom/show_bug.css create mode 100644 skins/standard/guided.css create mode 100644 template/en/default/bug/process/updates-disabled.html.tmpl create mode 100644 template/en/default/pages/bugzilla.dtd.tmpl create mode 100644 template/en/default/search/search-google.html.tmpl diff --git a/.bzrignore b/.bzrignore index 7ab83e7ad..e009f01c8 100644 --- a/.bzrignore +++ b/.bzrignore @@ -6,7 +6,6 @@ /docs/en/txt /docs/en/html /docs/en/pdf -/skins/custom /graphs /data /localconfig diff --git a/.htaccess b/.htaccess index 4b06fe9a9..b3053515a 100644 --- a/.htaccess +++ b/.htaccess @@ -23,3 +23,18 @@ + +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 + +RewriteEngine On +RewriteRule ^form[\.:](itrequest|brownbag|mozlist|mktgevent|poweredby|presentation|swag|trademark)$ enter_bug.cgi?product=mozilla.org&format=$1 +RewriteRule ^form[\.:]legal$ enter_bug.cgi?product=Legal&format=legal +RewriteRule ^form[\.:]mozpr$ enter_bug.cgi?product=Mozilla+PR&format=mozpr +RewriteRule ^form[\.:]reps[\.:]mentorship$ enter_bug.cgi?product=Mozilla+Reps&format=mozreps +RewriteRule ^form[\.:]reps[\.:]budget$ enter_bug.cgi?product=Mozilla+Reps&format=remo-budget +RewriteRule ^form[\.:]reps[\.:]swag$ enter_bug.cgi?product=Mozilla+Reps&format=remo-swag +RewriteRule ^form[\.:]reps[\.:]payment$ page.cgi?id=remo-form-payment.html diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 175bcd050..26d2a89f3 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -1628,6 +1628,14 @@ sub _check_groups { : $params->{product}; my %add_groups; + # BMO: Allow extension to add groups before the + # real checks are done. + Bugzilla::Hook::process('bug_check_groups', { + product => $product, + group_names => $group_names, + add_groups => \%add_groups + }); + # In email or WebServices, when the "groups" item actually # isn't specified, then just add the default groups. if (!defined $group_names) { @@ -1646,7 +1654,12 @@ sub _check_groups { foreach my $name (@$group_names) { my $group = Bugzilla::Group->check_no_disclose({ %args, name => $name }); - if (!$product->group_is_settable($group)) { + # BMO: Do not check group_is_settable if the group is + # already added, such as from the extension hook. group_is_settable + # will reject any group the user is not currently in. + if (!$add_groups{$group->id} + && !$product->group_is_settable($group)) + { ThrowUserError('group_restriction_not_allowed', { %args, name => $name }); } $add_groups{$group->id} = $group; @@ -1655,7 +1668,7 @@ sub _check_groups { # Now enforce mandatory groups. $add_groups{$_->id} = $_ foreach @{ $product->groups_mandatory }; - + my @add_groups = values %add_groups; return \@add_groups; } @@ -3244,15 +3257,37 @@ sub depends_on_obj { return $self->{depends_on_obj}; } +sub duplicates { + my $self = shift; + return $self->{duplicates} if exists $self->{duplicates}; + return [] if $self->{error}; + $self->{duplicates} = Bugzilla::Bug->new_from_list($self->duplicate_ids); + return $self->{duplicates}; +} + +sub duplicate_ids { + my $self = shift; + return $self->{duplicate_ids} if exists $self->{duplicate_ids}; + return [] if $self->{error}; + + my $dbh = Bugzilla->dbh; + $self->{duplicate_ids} = + $dbh->selectcol_arrayref('SELECT dupe FROM duplicates WHERE dupe_of = ?', + undef, $self->id); + return $self->{duplicate_ids}; +} + sub flag_types { - my ($self) = @_; + my ($self, $params) = @_; + $params ||= {}; return $self->{'flag_types'} if exists $self->{'flag_types'}; return [] if $self->{'error'}; my $vars = { target_type => 'bug', product_id => $self->{product_id}, component_id => $self->{component_id}, - bug_id => $self->bug_id }; + bug_id => $self->bug_id, + %$params }; $self->{'flag_types'} = Bugzilla::Flag->_flag_types($vars); return $self->{'flag_types'}; diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm index 55eeeab25..c637c3a66 100644 --- a/Bugzilla/BugMail.pm +++ b/Bugzilla/BugMail.pm @@ -267,7 +267,12 @@ sub Send { } # Make sure the user isn't in the nomail list, and the dep check passed. - if ($user->email_enabled && $dep_ok) { + # Upstreaming: when we port to 4.2, check the login names of the + # user objects in the bugmail_recipients hook instead. + if ($user->email_enabled && $dep_ok && + ($user->login !~ /bugs$/) && + ($user->login !~ /\.tld$/)) + { # OK, OK, if we must. Email the user. $sent_mail = sendMail( { to => $user, diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm index dc3cc1b9e..ad5166a0f 100644 --- a/Bugzilla/Component.pm +++ b/Bugzilla/Component.pm @@ -371,11 +371,13 @@ sub default_qa_contact { } sub flag_types { - my $self = shift; + my ($self, $params) = @_; + $params ||= {}; if (!defined $self->{'flag_types'}) { my $flagtypes = Bugzilla::FlagType::match({ product_id => $self->product_id, - component_id => $self->id }); + component_id => $self->id, + %$params }); $self->{'flag_types'} = {}; $self->{'flag_types'}->{'bug'} = diff --git a/Bugzilla/Config/Advanced.pm b/Bugzilla/Config/Advanced.pm index faab6bbbd..f5653ee86 100644 --- a/Bugzilla/Config/Advanced.pm +++ b/Bugzilla/Config/Advanced.pm @@ -62,6 +62,12 @@ use constant get_param_list => ( default => 'off', checker => \&check_multi }, + + { + name => 'disable_bug_updates', + type => 'b', + default => 0 + }, ); 1; diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 5c9fecc57..62836d8cc 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -255,7 +255,8 @@ use constant AUTH_NO_SUCH_USER => 5; use constant AUTH_LOCKOUT => 6; # The minimum length a password must have. -use constant USER_PASSWORD_MIN_LENGTH => 6; +# BMO uses 8 characters. +use constant USER_PASSWORD_MIN_LENGTH => 8; use constant LOGIN_OPTIONAL => 0; use constant LOGIN_NORMAL => 1; @@ -424,8 +425,8 @@ use constant MAX_LOGIN_ATTEMPTS => 5; use constant LOGIN_LOCKOUT_INTERVAL => 30; # The maximum number of seconds the Strict-Transport-Security header -# will remain valid. Default is one week. -use constant MAX_STS_AGE => 604800; +# will remain valid. BMO uses one month. +use constant MAX_STS_AGE => 2629744; # Protocols which are considered as safe. use constant SAFE_PROTOCOLS => ('afs', 'cid', 'ftp', 'gopher', 'http', 'https', @@ -438,15 +439,16 @@ use constant LEGAL_CONTENT_TYPES => ('application', 'audio', 'image', 'message', use constant contenttypes => { - "html"=> "text/html" , - "rdf" => "application/rdf+xml" , - "atom"=> "application/atom+xml" , - "xml" => "application/xml" , - "js" => "application/x-javascript" , - "json"=> "application/json" , - "csv" => "text/csv" , - "png" => "image/png" , - "ics" => "text/calendar" , + "html" => "text/html" , + "rdf" => "application/rdf+xml" , + "atom" => "application/atom+xml" , + "xml" => "application/xml" , + "dtd" => "application/xml-dtd" , + "js" => "application/x-javascript" , + "json" => "application/json" , + "csv" => "text/csv" , + "png" => "image/png" , + "ics" => "text/calendar" , }; # Usage modes. Default USAGE_MODE_BROWSER. Use with Bugzilla->usage_mode. diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm index 395cc0dc9..17a7a948a 100644 --- a/Bugzilla/Error.pm +++ b/Bugzilla/Error.pm @@ -26,7 +26,7 @@ package Bugzilla::Error; use strict; use base qw(Exporter); -@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError); +@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError ThrowErrorPage); use Bugzilla::Constants; use Bugzilla::WebService::Constants; @@ -212,6 +212,44 @@ END exit; } +sub ThrowErrorPage { + # BMO customisation for bug 659231 + my ($template_name, $message) = @_; + + my $dbh = Bugzilla->dbh; + $dbh->bz_rollback_transaction() if $dbh->bz_in_transaction(); + + if (Bugzilla->error_mode == ERROR_MODE_DIE) { + die("error: $message"); + } + + if (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT + || Bugzilla->error_mode == ERROR_MODE_JSON_RPC) + { + my $code = ERROR_UNKNOWN_TRANSIENT; + if (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) { + die SOAP::Fault->faultcode($code)->faultstring($message); + } else { + my $server = Bugzilla->_json_server; + $server->raise_error(code => 100000 + $code, + message => $message, + id => $server->{_bz_request_id}, + version => $server->version); + die if _in_eval(); + $server->response($server->error_response_header); + } + } else { + my $cgi = Bugzilla->cgi; + my $template = Bugzilla->template; + my $vars = {}; + $vars->{message} = $message; + print $cgi->header(); + $template->process($template_name, $vars) + || ThrowTemplateError($template->error()); + exit; + } +} + 1; __END__ diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 219172094..e47e92231 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -78,6 +78,8 @@ use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Util; use List::MoreUtils qw(any); +use Bugzilla::Config qw(SetParam write_params); +use Bugzilla::Hook; use Scalar::Util qw(blessed); @@ -916,53 +918,64 @@ sub remove_from_db { ThrowUserError('customfield_not_obsolete', {'name' => $self->name }); } - $dbh->bz_start_transaction(); + # BMO: disable bug updates during field creation + # using an eval as try/finally + eval { + SetParam('disable_bug_updates', 1); + write_params(); - # Check to see if bug activity table has records (should be fast with index) - my $has_activity = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs_activity - WHERE fieldid = ?", undef, $self->id); - if ($has_activity) { - ThrowUserError('customfield_has_activity', {'name' => $name }); - } + $dbh->bz_start_transaction(); + + # Check to see if bug activity table has records (should be fast with index) + my $has_activity = $dbh->selectrow_array("SELECT COUNT(*) FROM bugs_activity + WHERE fieldid = ?", undef, $self->id); + if ($has_activity) { + ThrowUserError('customfield_has_activity', {'name' => $name }); + } - # Check to see if bugs table has records (slow) - my $bugs_query = ""; + # Check to see if bugs table has records (slow) + my $bugs_query = ""; - if ($self->type == FIELD_TYPE_MULTI_SELECT) { - $bugs_query = "SELECT COUNT(*) FROM bug_$name"; - } - else { - $bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL"; - if ($self->type != FIELD_TYPE_BUG_ID && $self->type != FIELD_TYPE_DATETIME) { - $bugs_query .= " AND $name != ''"; + if ($self->type == FIELD_TYPE_MULTI_SELECT) { + $bugs_query = "SELECT COUNT(*) FROM bug_$name"; } - # Ignore the default single select value - if ($self->type == FIELD_TYPE_SINGLE_SELECT) { - $bugs_query .= " AND $name != '---'"; + else { + $bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL"; + if ($self->type != FIELD_TYPE_BUG_ID && $self->type != FIELD_TYPE_DATETIME) { + $bugs_query .= " AND $name != ''"; + } + # Ignore the default single select value + if ($self->type == FIELD_TYPE_SINGLE_SELECT) { + $bugs_query .= " AND $name != '---'"; + } } - } - my $has_bugs = $dbh->selectrow_array($bugs_query); - if ($has_bugs) { - ThrowUserError('customfield_has_contents', {'name' => $name }); - } + my $has_bugs = $dbh->selectrow_array($bugs_query); + if ($has_bugs) { + ThrowUserError('customfield_has_contents', {'name' => $name }); + } - # Once we reach here, we should be OK to delete. - $dbh->do('DELETE FROM fielddefs WHERE id = ?', undef, $self->id); + # Once we reach here, we should be OK to delete. + $dbh->do('DELETE FROM fielddefs WHERE id = ?', undef, $self->id); - my $type = $self->type; + my $type = $self->type; - # the values for multi-select are stored in a seperate table - if ($type != FIELD_TYPE_MULTI_SELECT) { - $dbh->bz_drop_column('bugs', $name); - } + # the values for multi-select are stored in a seperate table + if ($type != FIELD_TYPE_MULTI_SELECT) { + $dbh->bz_drop_column('bugs', $name); + } - if ($self->is_select) { - # Delete the table that holds the legal values for this field. - $dbh->bz_drop_field_tables($self); - } + if ($self->is_select) { + # Delete the table that holds the legal values for this field. + $dbh->bz_drop_field_tables($self); + } - $dbh->bz_commit_transaction() + $dbh->bz_commit_transaction(); + }; + my $error = "$@"; + SetParam('disable_bug_updates', 0); + write_params(); + die $error if $error; } =pod @@ -1014,36 +1027,72 @@ sub create { # the parameter isn't sent to create(). $params->{sortkey} = undef if !exists $params->{sortkey}; $params->{type} ||= 0; - - $dbh->bz_start_transaction(); - $class->check_required_create_fields(@_); - my $field_values = $class->run_create_validators($params); - my $visibility_values = delete $field_values->{visibility_values}; - my $field = $class->insert_create_data($field_values); - - $field->set_visibility_values($visibility_values); - $field->_update_visibility_values(); - - $dbh->bz_commit_transaction(); - if ($field->custom) { - my $name = $field->name; - my $type = $field->type; - if (SQL_DEFINITIONS->{$type}) { - # Create the database column that stores the data for this field. - $dbh->bz_add_column('bugs', $name, SQL_DEFINITIONS->{$type}); + # BMO: disable bug updates during field creation + # using an eval as try/finally + my $field; + eval { + if ($params->{'custom'}) { + SetParam('disable_bug_updates', 1); + write_params(); } - if ($field->is_select) { - # Create the table that holds the legal values for this field. - $dbh->bz_add_field_tables($field); + # Purpose: if the field is active in the fields list before all of the + # data structures are created, anything accessing Bug.pm will crash. So + # stash a copy of the intended obsolete value for later and force it + # to be obsolete on initial creation. + # Upstreaming: https://bugzilla.mozilla.org/show_bug.cgi?id=531243 + my $original_obsolete; + if ($params->{'custom'}) { + $original_obsolete = $params->{'obsolete'}; + $params->{'obsolete'} = 1; } - if ($type == FIELD_TYPE_SINGLE_SELECT) { - # Insert a default value of "---" into the legal values table. - $dbh->do("INSERT INTO $name (value) VALUES ('---')"); + $dbh->bz_start_transaction(); + $class->check_required_create_fields(@_); + my $field_values = $class->run_create_validators($params); + my $visibility_values = delete $field_values->{visibility_values}; + my $field = $class->insert_create_data($field_values); + + $field->set_visibility_values($visibility_values); + $field->_update_visibility_values(); + + $dbh->bz_commit_transaction(); + + if ($field->custom) { + # Restore the obsolete value that got stashed earlier (in memory) + $field->set_obsolete($original_obsolete); + + my $name = $field->name; + my $type = $field->type; + if (SQL_DEFINITIONS->{$type}) { + # Create the database column that stores the data for this field. + $dbh->bz_add_column('bugs', $name, SQL_DEFINITIONS->{$type}); + } + + if ($field->is_select) { + # Create the table that holds the legal values for this field. + $dbh->bz_add_field_tables($field); + } + + if ($type == FIELD_TYPE_SINGLE_SELECT) { + # Insert a default value of "---" into the legal values table. + $dbh->do("INSERT INTO $name (value) VALUES ('---')"); + } + + # Safe to write the original 'obsolete' value to the database now + $field->update; } + }; + + my $error = "$@"; + if ($params->{'custom'}) { + SetParam('disable_bug_updates', 0); + write_params(); } + die $error if $error; + + Bugzilla::Hook::process("field_end_of_create", { field => $field }); return $field; } diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm index b7532fe09..3f521d0f2 100644 --- a/Bugzilla/Group.pm +++ b/Bugzilla/Group.pm @@ -119,9 +119,10 @@ sub _get_members { } sub flag_types { - my $self = shift; + my ($self, $params) = @_; + $params ||= {}; require Bugzilla::FlagType; - $self->{flag_types} ||= Bugzilla::FlagType::match({ group => $self->id }); + $self->{flag_types} ||= Bugzilla::FlagType::match({ group => $self->id, %$params }); return $self->{flag_types}; } diff --git a/Bugzilla/Install.pm b/Bugzilla/Install.pm index ce8fe6bad..60e96766b 100644 --- a/Bugzilla/Install.pm +++ b/Bugzilla/Install.pm @@ -93,6 +93,8 @@ sub SETTINGS { # 2011-06-21 glob@mozilla.com -- Bug 589128 email_format => { options => ['html', 'text_only'], default => 'html' }, + # 2011-06-16 glob@mozilla.com -- Bug 663747 + bugmail_new_prefix => { options => ['on', 'off'], default => 'on' }, } }; diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 5ce3c7a4e..f30e1503b 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -637,6 +637,9 @@ sub update_table_definitions { # 2009-05-07 ghendricks@novell.com - Bug 77193 _add_isactive_to_product_fields(); + # 2009-05-07 ghendricks@novell.com - Bug 77193 + _add_isactive_to_product_fields(); + # 2010-10-09 LpSolit@gmail.com - Bug 505165 $dbh->bz_alter_column('flags', 'setter_id', {TYPE => 'INT3', NOTNULL => 1}); @@ -3207,6 +3210,11 @@ sub _populate_bugs_fulltext { print "Populating bugs_fulltext with $num_bugs entries..."; print " (this can take a long time.)\n"; } + + # As recommended by Monty Widenius for GNOME's upgrade. + # mkanat and justdave concur it'll be helpful for bmo, too. + $dbh->do('SET SESSION myisam_sort_buffer_size = 3221225472'); + my $newline = $dbh->quote("\n"); $dbh->do( qq{$command INTO bugs_fulltext (bug_id, short_desc, comments, @@ -3602,6 +3610,26 @@ sub _rename_tags_to_tag { } } +sub _add_isactive_to_product_fields { + my $dbh = Bugzilla->dbh; + + # If we add the isactive column all values should start off as active + if (!$dbh->bz_column_info('components', 'isactive')) { + $dbh->bz_add_column('components', 'isactive', + {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'}); + } + + if (!$dbh->bz_column_info('versions', 'isactive')) { + $dbh->bz_add_column('versions', 'isactive', + {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'}); + } + + if (!$dbh->bz_column_info('milestones', 'isactive')) { + $dbh->bz_add_column('milestones', 'isactive', + {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'}); + } +} + 1; __END__ diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 15106dab9..e6783bbee 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -169,6 +169,7 @@ sub FILESYSTEM { 'contrib/README' => { perms => OWNER_WRITE }, 'contrib/*/README' => { perms => OWNER_WRITE }, + 'contrib/sendunsentbugmail.pl' => { perms => WS_EXECUTE }, 'docs/bugzilla.ent' => { perms => OWNER_WRITE }, 'docs/makedocs.pl' => { perms => OWNER_EXECUTE }, 'docs/style.css' => { perms => WS_SERVE }, @@ -183,8 +184,10 @@ sub FILESYSTEM { # Directories that we want to set the perms on, but not # recurse through. These are directories we didn't create # in checkesetup.pl. + # + # Purpose of BMO change: unknown. my %non_recurse_dirs = ( - '.' => DIR_WS_SERVE, + '.' => 0755, docs => DIR_WS_SERVE, ); @@ -242,10 +245,13 @@ sub FILESYSTEM { dirs => DIR_WS_SERVE }, "$extensionsdir/*/web" => { files => WS_SERVE, dirs => DIR_WS_SERVE }, - + + # Purpose: allow webserver to read .bzr so we execute bzr commands + # in backticks and look at the result over the web. Used to show + # bzr history. + '.bzr' => { files => WS_SERVE, + dirs => DIR_WS_SERVE }, # Directories only for the owner, not for the webserver. - '.bzr' => { files => OWNER_WRITE, - dirs => DIR_OWNER_WRITE }, t => { files => OWNER_WRITE, dirs => DIR_OWNER_WRITE }, xt => { files => OWNER_WRITE, diff --git a/Bugzilla/Product.pm b/Bugzilla/Product.pm index a0079a033..976804cb0 100644 --- a/Bugzilla/Product.pm +++ b/Bugzilla/Product.pm @@ -779,7 +779,8 @@ sub user_has_access { } sub flag_types { - my $self = shift; + my ($self, $params) = @_; + $params ||= {}; return $self->{'flag_types'} if defined $self->{'flag_types'}; @@ -787,7 +788,7 @@ sub flag_types { my $cache = Bugzilla->request_cache->{flag_types_per_product} ||= {}; $self->{flag_types} = {}; my $prod_id = $self->id; - my $flagtypes = Bugzilla::FlagType::match({ product_id => $prod_id }); + my $flagtypes = Bugzilla::FlagType::match({ product_id => $prod_id, %$params }); foreach my $type ('bug', 'attachment') { my @flags = grep { $_->target_type eq $type } @$flagtypes; diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index d47e0ae99..a1378e540 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -2786,7 +2786,8 @@ sub _changedby { sub IsValidQueryType { my ($queryType) = @_; - if (grep { $_ eq $queryType } qw(specific advanced)) { + # BMO: Added google query type + if (grep { $_ eq $queryType } qw(specific advanced google)) { return 1; } return 0; diff --git a/Bugzilla/Search/Quicksearch.pm b/Bugzilla/Search/Quicksearch.pm index 8425a2be2..1d332e5ae 100644 --- a/Bugzilla/Search/Quicksearch.pm +++ b/Bugzilla/Search/Quicksearch.pm @@ -492,6 +492,9 @@ sub _default_quicksearch_word { addChart('short_desc', 'substring', $word, $negate); addChart('status_whiteboard', 'substring', $word, $negate); addChart('content', 'matches', _matches_phrase($word), $negate) if $fulltext; + + # BMO Bug 664124 - Include the crash signature (sig:) field in default quicksearches + addChart('cf_crash_signature', 'substring', $word, $negate); } sub _handle_urls { diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 527b704b2..433b283b2 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -234,7 +234,8 @@ sub quoteUrls { ~$1$2~igx; # attachment links - $text =~ s~\b(attachment\s*\#?\s*(\d+)(?:\s+\[details\])?) + # BMO: Bug 652332 dkl@mozilla.com 2011-07-20 + $text =~ s~\b(attachment\s*\#?\s*(\d+)(?:\s+\[diff\])?(?:\s+\[details\])?) ~($things[$count++] = get_attachment_link($2, $1)) && ("\0\0" . ($count-1) . "\0\0") ~egmxi; @@ -293,18 +294,20 @@ sub get_attachment_link { $title = html_quote(clean_text($title)); $link_text =~ s/ \[details\]$//; + $link_text =~ s/ \[diff\]$//; my $linkval = "attachment.cgi?id=$attachid"; - # If the attachment is a patch, try to link to the diff rather - # than the text, by default. + # If the attachment is a patch and patch_viewer feature is + # enabled, add link to the diff. my $patchlink = ""; if ($attachment->ispatch and Bugzilla->feature('patch_viewer')) { - $patchlink = '&action=diff'; + $patchlink = qq| [diff]|; } # Whitespace matters here because these links are in
 tags.
         return qq||
-               . qq|$link_text|
+               . qq|$link_text|
+               . qq|${patchlink}|
                . qq| [details]|
                . qq||;
     }
diff --git a/Bugzilla/Token.pm b/Bugzilla/Token.pm
index 86220aa29..4e32436c0 100644
--- a/Bugzilla/Token.pm
+++ b/Bugzilla/Token.pm
@@ -109,6 +109,8 @@ sub IssueEmailChangeToken {
     $vars->{'newemailaddress'} = $new_email . $email_suffix;
     $vars->{'expiration_ts'} = ctime($token_ts + MAX_TOKEN_AGE * 86400);
     $vars->{'token'} = $token;
+    # For SecureMail extension
+    $vars->{'to_user'} = $user;
     $vars->{'emailaddress'} = $old_email . $email_suffix;
 
     my $message;
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index ea186a0fd..8ad84cec7 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -50,6 +50,7 @@ use Bugzilla::Product;
 use Bugzilla::Classification;
 use Bugzilla::Field;
 use Bugzilla::Group;
+use Bugzilla::Hook;
 
 use DateTime::TimeZone;
 use List::Util qw(max);
@@ -708,8 +709,8 @@ sub bless_groups {
     return $self->{'bless_groups'} if defined $self->{'bless_groups'};
     return [] unless $self->id;
 
-    if ($self->in_group('editusers')) {
-        # Users having editusers permissions may bless all groups.
+    if ($self->in_group('admin')) {
+        # Users having admin permissions may bless all groups.
         $self->{'bless_groups'} = [Bugzilla::Group->get_all];
         return $self->{'bless_groups'};
     }
@@ -2293,7 +2294,7 @@ Determines whether or not a user is in the given group by id.
 Returns an arrayref of L objects.
 
 The arrayref consists of the groups the user can bless, taking into account
-that having editusers permissions means that you can bless all groups, and
+that having admin permissions means that you can bless all groups, and
 that you need to be able to see a group in order to bless it.
 
 =item C
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm
index fb2b7b65d..c2083a59f 100644
--- a/Bugzilla/WebService/Bug.pm
+++ b/Bugzilla/WebService/Bug.pm
@@ -439,10 +439,17 @@ sub search {
     delete $match_params{'include_fields'};
     delete $match_params{'exclude_fields'};
 
+    my $count_only = delete $match_params{count_only};
+
     my $bugs = Bugzilla::Bug->match(\%match_params);
     my $visible = Bugzilla->user->visible_bugs($bugs);
-    my @hashes = map { $self->_bug_to_hash($_, $params) } @$visible;
-    return { bugs => \@hashes };
+    if ($count_only) {
+        return { bug_count => scalar @$visible };
+    }
+    else {
+        my @hashes = map { $self->_bug_to_hash($_, $params) } @$visible;
+        return { bugs => \@hashes };
+    }
 }
 
 sub possible_duplicates {
@@ -469,6 +476,12 @@ sub possible_duplicates {
 sub update {
     my ($self, $params) = validate(@_, 'ids');
 
+    # BMO: Don't allow updating of bugs if disabled
+    if (Bugzilla->params->{disable_bug_updates}) {
+        ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+            'Bug updates are currently disabled.');
+    }
+
     my $user = Bugzilla->login(LOGIN_REQUIRED);
     my $dbh = Bugzilla->dbh;
 
@@ -563,6 +576,13 @@ sub update {
 
 sub create {
     my ($self, $params) = @_;
+
+    # BMO: Don't allow updating of bugs if disabled
+    if (Bugzilla->params->{disable_bug_updates}) {
+        ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+            'Bug updates are currently disabled.');
+    }
+
     Bugzilla->login(LOGIN_REQUIRED);
     $params = Bugzilla::Bug::map_fields($params);
     my $bug = Bugzilla::Bug->create($params);
@@ -625,6 +645,12 @@ sub add_attachment {
     my ($self, $params) = validate(@_, 'ids');
     my $dbh = Bugzilla->dbh;
 
+    # BMO: Don't allow updating of bugs if disabled
+    if (Bugzilla->params->{disable_bug_updates}) {
+        ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+            'Bug updates are currently disabled.');
+    }
+
     Bugzilla->login(LOGIN_REQUIRED);
     defined $params->{ids}
         || ThrowCodeError('param_required', { param => 'ids' });
@@ -670,6 +696,12 @@ sub add_attachment {
 sub add_comment {
     my ($self, $params) = @_;
     
+    # BMO: Don't allow updating of bugs if disabled
+    if (Bugzilla->params->{disable_bug_updates}) {
+        ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+            'Bug updates are currently disabled.');
+    }
+
     #The user must login in order add a comment
     Bugzilla->login(LOGIN_REQUIRED);
     
@@ -714,6 +746,12 @@ sub add_comment {
 sub update_see_also {
     my ($self, $params) = @_;
 
+    # BMO: Don't allow updating of bugs if disabled
+    if (Bugzilla->params->{disable_bug_updates}) {
+        ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+            'Bug updates are currently disabled.');
+    }
+
     my $user = Bugzilla->login(LOGIN_REQUIRED);
 
     # Check parameters
@@ -2160,6 +2198,11 @@ C Search the "Status Whiteboard" field on bugs for a substring.
 Works the same as the C field described above, but searches the
 Status Whiteboard field.
 
+=item C
+
+C If count_only set to true, only a single hash key called C 
+will be returned which is the number of bugs that matched the search.
+
 =back
 
 =item B
diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm
index 2d9276cc3..984f41c8a 100644
--- a/Bugzilla/WebService/User.pm
+++ b/Bugzilla/WebService/User.pm
@@ -30,6 +30,7 @@ use Bugzilla::User;
 use Bugzilla::Util qw(trim);
 use Bugzilla::Token;
 use Bugzilla::WebService::Util qw(filter validate);
+use Bugzilla::Hook;
 
 # Don't need auth to login
 use constant LOGIN_EXEMPT => {
@@ -235,6 +236,9 @@ sub get {
             }} @$in_group;
     }
 
+    Bugzilla::Hook::process('webservice_user_get', 
+        { webservice => $self, params => $params, users => \@users });
+
     return { users => \@users };
 }
 
diff --git a/attachment.cgi b/attachment.cgi
index 5eba13611..9fec1b2bd 100755
--- a/attachment.cgi
+++ b/attachment.cgi
@@ -76,6 +76,12 @@ local our $vars = {};
 my $action = $cgi->param('action') || 'view';
 my $format = $cgi->param('format') || '';
 
+# BMO: Don't allow updating of bugs if disabled
+if (Bugzilla->params->{disable_bug_updates} && $cgi->request_method eq 'POST') {
+    ThrowErrorPage('bug/process/updates-disabled.html.tmpl',
+        'Bug updates are currently disabled.');
+}
+
 # You must use the appropriate urlbase/sslbase param when doing anything
 # but viewing an attachment, or a raw diff.
 if ($action ne 'view'
@@ -497,7 +503,8 @@ sub enter {
 
   my $flag_types = Bugzilla::FlagType::match({'target_type'  => 'attachment',
                                               'product_id'   => $bug->product_id,
-                                              'component_id' => $bug->component_id});
+                                              'component_id' => $bug->component_id, 
+                                              'is_active'    => 1});
   $vars->{'flag_types'} = $flag_types;
   $vars->{'any_flags_requesteeble'} =
     grep { $_->is_requestable && $_->is_requesteeble } @$flag_types;
diff --git a/bzr-update.sh b/bzr-update.sh
new file mode 100644
index 000000000..e1d88e5d7
--- /dev/null
+++ b/bzr-update.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+HOST=`hostname -s`
+TAG="current-staging"
+[ "$HOST" == "mradm02" -o "$HOST" == "ip-admin02" ] && TAG="current-production"
+echo "+ bzr pull --overwrite -rtag:$TAG"
+output=`bzr pull --overwrite -rtag:$TAG 2>&1`
+echo "$output"
+echo "$output" | grep "Now on revision" | sed -e 's/Now on revision //' -e 's/\.$//' | xargs -i{} echo bzr pull --overwrite -r{} \# `date` >> `dirname $0`/cvs-update.log
+contrib/fixperms.pl
diff --git a/chart.cgi b/chart.cgi
index e7a0f5e8b..89fefbc3f 100755
--- a/chart.cgi
+++ b/chart.cgi
@@ -274,7 +274,8 @@ sub assertCanCreate {
 
     # Check permission for frequency
     my $min_freq = 7;
-    if ($cgi->param('frequency') < $min_freq && !$user->in_group("admin")) {
+    # Upstreaming: denied, as this min_freq feature is going away.
+    if ($cgi->param('frequency') < $min_freq && !$user->in_group("bz_canusewhines")) {
         ThrowUserError("illegal_frequency", { 'minimum' => $min_freq });
     }
 }
diff --git a/contrib/addcustomfield.pl b/contrib/addcustomfield.pl
new file mode 100644
index 000000000..c7f93c297
--- /dev/null
+++ b/contrib/addcustomfield.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# Contributor(s): Frédéric Buclin 
+#                 David Miller 
+
+use strict;
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Field;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my %types = (
+  'freetext' => FIELD_TYPE_FREETEXT,
+  'single_select' => FIELD_TYPE_SINGLE_SELECT,
+  'multi_select' => FIELD_TYPE_MULTI_SELECT,
+  'textarea' => FIELD_TYPE_TEXTAREA,
+  'datetime' => FIELD_TYPE_DATETIME,
+  'bug_id' => FIELD_TYPE_BUG_ID,
+  'bug_urls' => FIELD_TYPE_BUG_URLS,
+  'keywords' => FIELD_TYPE_KEYWORDS,
+);
+
+my $syntax = 
+    "syntax: addcustomfield.pl  [field type]\n\n" .
+    "valid field types:\n  " . join("\n  ", sort keys %types) . "\n\n" .
+    "the default field type is single_select\n";
+
+my $name = shift || die $syntax;
+my $type = lc(shift || 'single_select');
+exists $types{$type} || die "Invalid field type '$type'.\n\n$syntax";
+$type = $types{$type};
+
+Bugzilla::Field->create({
+    name        => $name,
+    description => 'Please give me a description!',
+    type        => $type,
+    mailhead    => 0,
+    enter_bug   => 0,
+    obsolete    => 1,
+    custom      => 1,
+    buglist     => 1,
+});
+print "Done!\n";
+
+my $urlbase = Bugzilla->params->{urlbase};
+print "Please visit ${urlbase}editfields.cgi?action=edit&name=$name to finish setting up this field.\n";
diff --git a/contrib/fix_comment_text.pl b/contrib/fix_comment_text.pl
new file mode 100644
index 000000000..f17bbc3d4
--- /dev/null
+++ b/contrib/fix_comment_text.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl 
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+# 
+# Software distributed under the License is distributed on an "AS
+# IS" basis,  WITHOUT WARRANTY OF ANY KIND,  either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+# 
+# The Initial Developer of the Original Code is Mozilla Foundation 
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+#         FILE:  fix_comment_text.pl
+#
+#        USAGE:  ./fix_comment_text.pl 
+#
+#  DESCRIPTION:  Updates a comment in Bugzilla with the text after __DATA__
+#
+#      OPTIONS:   - The comment id from longdescs with the comment 
+#                to be replaced.
+# REQUIREMENTS:  ---
+#         BUGS:  ---
+#        NOTES:  ---
+#       AUTHOR:  David Lawrence (:dkl), dkl@mozilla.com
+#      COMPANY:  Mozilla Foundation
+#      VERSION:  1.0
+#      CREATED:  06/20/2011 03:40:22 PM
+#     REVISION:  ---
+#===============================================================================
+
+use strict;
+use warnings;
+
+use lib ".";
+
+use Bugzilla;
+use Bugzilla::Util qw(detaint_natural);
+
+my $comment_id = shift;
+
+if (!detaint_natural($comment_id)) {
+    print "Error: invalid comment id or comment id not provided.\n" .
+          "Usage: ./fix_comment_text.pl \n";
+    exit(1);
+}
+
+my $dbh = Bugzilla->dbh;
+
+my $comment = join("",  );
+
+if ($comment =~ /ENTER NEW COMMENT TEXT HERE/) {
+    print "Please enter the new comment text in the script " .
+          "after the __DATA__ marker.\n";
+    exit(1);
+}
+
+$dbh->bz_start_transaction;
+
+Bugzilla->dbh->do(
+    "UPDATE longdescs SET thetext = ? WHERE comment_id = ?", 
+    undef, $comment, $comment_id);
+
+$dbh->bz_commit_transaction;
+
+exit(0);
+
+__DATA__
+ENTER NEW COMMENT TEXT HERE BELOW THE __DATA__ MARKER!
diff --git a/contrib/moco-ldap-check.pl b/contrib/moco-ldap-check.pl
new file mode 100644
index 000000000..59f515bf2
--- /dev/null
+++ b/contrib/moco-ldap-check.pl
@@ -0,0 +1,224 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is the Mozilla
+# Foundation. Portions created by Mozilla are
+# Copyright (C) 2011 Mozilla Foundation. All Rights Reserved.
+#
+# Contributor(s): Byron Jones 
+
+use strict;
+
+use lib qw(.);
+
+use Net::LDAP;
+use XMLRPC::Lite;
+use HTTP::Cookies;
+use LWP::UserAgent;
+use Term::ReadKey;
+$| = 1;
+
+#
+#
+#
+
+print STDERR <new(file => "cookies.txt", autosave => 1);
+    my $proxy = XMLRPC::Lite->proxy(
+        'https://bugzilla.mozilla.org/xmlrpc.cgi',
+        'cookie_jar' => $cookie_jar);
+    my $response;
+
+    print STDERR "Logging in to Bugzilla...\n";
+    $response = $proxy->call(
+        'User.login',
+        {
+            login => $bugzillaLogin,
+            password => $bugzillaPassword,
+            remember => 1,
+        }
+    );
+    if ($response->fault) {
+        my ($package, $filename, $line) = caller;
+        die $response->faultstring . "\n";
+    }
+
+    my $ua = LWP::UserAgent->new();
+    $ua->cookie_jar($cookie_jar);
+    $response = $ua->get('https://bugzilla.mozilla.org/editusers.cgi?' .
+        'action=list&matchvalue=login_name&matchstr=&matchtype=substr&' .
+        'grouprestrict=1&groupid=42');
+    if (!$response->is_success) {
+        die $response->status_line;
+    }
+
+    print STDERR "Getting user list from Bugzilla...\n";
+    my $content = $response->content;
+    while (
+        $content =~ m#
+            ]*)>[^<]+
+            ([^<]+)[^<]+
+            [^<]+
+            ]*>([^<]+)
+        #gx
+    ) {
+        my ($class, $email, $name) = ($1, $2, $3);
+        next if $class =~ /bz_inactive/;
+        $email =~ s/(^\s+|\s+$)//g;
+        $email =~ s/@/@/;
+        next unless $email =~ /@/;
+        $name =~ s/(^\s+|\s+$)//g;
+        $bugzilla{lc $email} = $name;
+    }
+}
+
+#
+# build list of current mo-co bugmail accounts
+#
+
+my %ldap;
+{
+    print STDERR "Logging into LDAP...\n";
+    my $ldap = Net::LDAP->new('addressbook.mozilla.com',
+        scheme => 'ldaps', onerror => 'die') or die "$@";
+    $ldap->bind("mail=$ldapLogin,o=com,dc=mozilla", password => $ldapPassword);
+    my $result = $ldap->search(
+        base => 'o=com,dc=mozilla',
+        scope => 'sub',
+        filter => '(mail=*)',
+        attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'],
+    );
+    print STDERR "Getting user list from LDAP...\n";
+    foreach my $entry ($result->entries) {
+        my ($name, $bugMail, $mail, $type) =
+            map { $entry->get_value($_) || '' }
+            qw(cn bugzillaEmail mail employeeType);
+        next if $type eq 'DISABLED';
+        $mail = lc $mail;
+        $ldap{$mail}{name} = $name;
+        $ldap{$mail}{bugMail} = lc $bugMail;
+        $ldap{$mail}{alias} = {};
+        foreach my $alias (
+            @{$entry->get_value('emailAlias', asref => 1) || []}
+        ) {
+            $ldap{$mail}{alias}{lc $alias} = 1;
+        }
+    }
+}
+
+#
+# cross-check
+#
+
+my @invalid;
+foreach my $bugzilla (sort keys %bugzilla) {
+    # check for matching bugmail entry
+    my $exists = 0;
+    foreach my $mail (sort keys %ldap) {
+        next unless $ldap{$mail}{bugMail} eq $bugzilla;
+        $exists = 1;
+        last;
+    }
+    next if $exists;
+
+    # check for matching mail
+    $exists = 0;
+    foreach my $mail (sort keys %ldap) {
+        next unless $mail eq $bugzilla;
+        $exists = 1;
+        last;
+    }
+    next if $exists;
+
+    # check for matching email alias
+    $exists = 0;
+    foreach my $mail (sort keys %ldap) {
+        next unless exists $ldap{$mail}{alias}{$bugzilla};
+        $exists = 1;
+        last;
+    }
+    next if $exists;
+
+    push @invalid, $bugzilla;
+}
+
+my $max_length = 0;
+foreach my $email (@invalid) {
+    $max_length = length($email) if length($email) > $max_length;
+}
+foreach my $email (@invalid) {
+    printf "%-${max_length}s %s\n", $email, $bugzilla{$email};
+}
diff --git a/contrib/reorg-tools/README b/contrib/reorg-tools/README
new file mode 100644
index 000000000..4e5d6eb4d
--- /dev/null
+++ b/contrib/reorg-tools/README
@@ -0,0 +1,9 @@
+Upstreaming attempt: https://bugzilla.mozilla.org/show_bug.cgi?id=616499
+
+Included in this directory is a group of tools we've used for moving components
+around in a Bugzilla 3.2 install on bugzilla.mozilla.org.
+
+They may require tweaking if you use them on your own install.  Putting them
+here to make it easier to collaborate on them and keep them up-to-date.
+Hopefully Bugzilla upstream will be able to just do this from the web UI
+eventually.
diff --git a/contrib/reorg-tools/bmo-plan.txt b/contrib/reorg-tools/bmo-plan.txt
new file mode 100644
index 000000000..838ff0ab9
--- /dev/null
+++ b/contrib/reorg-tools/bmo-plan.txt
@@ -0,0 +1,82 @@
+==BMO Reorg Plan==
+
+Do the following things, mostly in order (but see "Timing" at the end):
+
+1) Create new classifications using GUI:
+   Graveyard (Description: "Old, retired products", sort key: )
+
+2) Rename classifications using GUI:
+   Client Support to Other
+
+3) Move products between classification using GUI:
+   Grendel from Client Software to Graveyard
+   CCK from Unclassified to Graveyard
+   Derivatives from Unclassified to Graveyard
+   MozillaClassic from Unclassified to Graveyard
+   UI: "reclassify" link from the top-level classification list
+
+4) Create new products using GUI:
+   Core Graveyard in Graveyard 
+     (desc: "Old, retired Core components", closed for entry, no charts)
+   MailNews Core in Components
+     (desc: "Mail and news components common to Thunderbird and SeaMonkey",
+      open for bug entry, create charts)
+
+5) Rename products using GUI, and fix queries using fixqueries.pl:
+mysql> update series_categories set name="SeaMonkey (2)" where id=32;
+   Mozilla Application Suite to SeaMonkey
+   Sumo to support.mozilla.com
+
+5.5) Rename versions and milestones in Toolkit to match Firefox before step 6
+
+6) Sync milestones, versions and groups between products using
+syncmsandversions.pl:
+   Core -> Core Graveyard (new)
+   Core -> MailNews Core (new)
+   Firefox -> Toolkit
+   Core -> SeaMonkey
+   mozilla.org -> Websites (only 1)
+
+6.5) Sync flag inclusions using syncflags.pl:
+   Core -> Core Graveyard (new)
+   Core -> MailNews Core (new)
+   Core -> SeaMonkey
+   mozilla.org -> Websites (only 1)
+
+6.7) Allow Firefox flags temporarily in Toolkit: 
+    250 | blocking-firefox3       | blocking1.9 - 387
+    419 | blocking-firefox3.1     | blocking1.9.1 - 416
+     63 | blocking0.8             | blocking1.6 - 69
+     76 | blocking0.9             | blocking1.7 - 83
+     36 | review                  | review - 4
+    356 | wanted-firefox3         | wanted1.9 - 357
+    418 | wanted-firefox3.1       | wanted1.9.1 - 417
+
+7) Move components using movecomponent.pl.
+   Any instruction beginning "moved from".
+   Can't fix the queries for this - oh well
+   
+
+8) Rename components using GUI, and fix queries using fixqueries.pl.
+   Any instruction beginning "renamed from" or "MailNews: prefix removed".
+   
+  
+9) Create new components using GUI.
+   Any instruction beginning "new".
+   
+
+10) Move open bugs using GUI:
+    XP Miscellany to Core/General
+  
+11) Merge components by moving bugs using GUI:
+    Any instruction beginning "merge in".
+    Merge all bugs, including closed. Delete empty component when done.
+    
+
+12) Close Core Graveyard (and Grendel if necessary) to new bugs
+
+13) Rename Toolkit versions and milestones back (from 5.5)
+
+14) Execute flag mapping SQL using Reed's mapping to update bugs in Toolkit
+
+15) Disable above-listed flags in point 6.7 in Toolkit again
diff --git a/contrib/reorg-tools/fixgroupqueries.pl b/contrib/reorg-tools/fixgroupqueries.pl
new file mode 100644
index 000000000..1c75edb97
--- /dev/null
+++ b/contrib/reorg-tools/fixgroupqueries.pl
@@ -0,0 +1,119 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham 
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+  print < 
+
+E.g.: fixgroupqueries.pl w-security webtools-security
+will change all occurrences of "w-security" to "webtools-security" in the 
+appropriate places in the namedqueries.
+ 
+Note that all parameters are case-sensitive.
+USAGE
+}
+
+sub do_namedqueries($$) {
+    my ($old, $new) = @_;
+    $old = url_quote($old);
+    $new = url_quote($new);
+
+    my $dbh = Bugzilla->dbh;
+
+    my $replace_count = 0;
+    my $query = $dbh->selectall_arrayref("SELECT id, query FROM namedqueries");
+    if ($query) {
+        my $sth = $dbh->prepare("UPDATE namedqueries SET query = ? 
+                                                     WHERE id = ?");
+        
+        foreach my $row (@$query) {
+            my ($id, $query) = @$row;
+            if (($query =~ /field\d+-\d+-\d+=bug_group/) &&
+                ($query =~ /(?:^|&|;)value\d+-\d+-\d+=$old(?:;|&|$)/)) {
+                $query =~ s/((?:^|&|;)value\d+-\d+-\d+=)$old(;|&|$)/$1$new$2/;
+                $sth->execute($query, $id);
+                $replace_count++;
+            }
+        }
+    }
+
+    print "namedqueries: $replace_count replacements made.\n";
+}
+
+# series
+sub do_series($$) {
+    my ($old, $new) = @_;
+    $old = url_quote($old);
+    $new = url_quote($new);
+
+    my $dbh = Bugzilla->dbh;
+    #$dbh->bz_start_transaction();
+
+    my $replace_count = 0;
+    my $query = $dbh->selectall_arrayref("SELECT series_id, query
+                                          FROM series");
+    if ($query) {
+        my $sth = $dbh->prepare("UPDATE series SET query = ?
+                                               WHERE series_id = ?");
+        foreach my $row (@$query) {
+            my ($series_id, $query) = @$row;
+
+            if (($query =~ /field\d+-\d+-\d+=bug_group/) &&
+                ($query =~ /(?:^|&|;)value\d+-\d+-\d+=$old(?:;|&|$)/)) {
+                $query =~ s/((?:^|&|;)value\d+-\d+-\d+=)$old(;|&|$)/$1$new$2/;
+                $sth->execute($query, $series_id);
+                $replace_count++;
+            }
+        }
+    }
+
+    #$dbh->bz_commit_transaction();
+    print "series:      $replace_count replacements made.\n";
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+    usage();
+    exit();
+}
+
+my ($old, $new) = @ARGV;
+
+print "Changing all instances of '$old' to '$new'.\n\n";
+
+#do_namedqueries($old, $new);
+do_series($old, $new);
+
+exit(0);
diff --git a/contrib/reorg-tools/fixqueries.pl b/contrib/reorg-tools/fixqueries.pl
new file mode 100644
index 000000000..4b862fd72
--- /dev/null
+++ b/contrib/reorg-tools/fixqueries.pl
@@ -0,0 +1,132 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham 
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+  print <  
+
+E.g.: fixqueries.pl product FoodReplicator SeaMonkey
+will change all occurrences of "FoodReplicator" to "Seamonkey" in the 
+appropriate places in the namedqueries, series and series_categories tables.
+ 
+Note that all parameters are case-sensitive.
+USAGE
+}
+
+sub do_namedqueries($$$) {
+    my ($field, $old, $new) = @_;
+    $old = url_quote($old);
+    $new = url_quote($new);
+
+    my $dbh = Bugzilla->dbh;
+    #$dbh->bz_start_transaction();
+
+    my $replace_count = 0;
+    my $query = $dbh->selectall_arrayref("SELECT id, query FROM namedqueries");
+    if ($query) {
+        my $sth = $dbh->prepare("UPDATE namedqueries SET query = ? 
+                                                     WHERE id = ?");
+        
+        foreach my $row (@$query) {
+            my ($id, $query) = @$row;
+            if ($query =~ /(?:^|&|;)$field=$old(?:&|$|;)/) {
+                $query =~ s/((?:^|&|;)$field=)$old(;|&|$)/$1$new$2/;
+                $sth->execute($query, $id);
+                $replace_count++;
+            }
+        }
+    }
+
+    #$dbh->bz_commit_transaction();
+    print "namedqueries: $replace_count replacements made.\n";
+}
+  
+# series
+sub do_series($$$) {
+    my ($field, $old, $new) = @_;
+    $old = url_quote($old);
+    $new = url_quote($new);
+
+    my $dbh = Bugzilla->dbh;
+    #$dbh->bz_start_transaction();
+
+    my $replace_count = 0;
+    my $query = $dbh->selectall_arrayref("SELECT series_id, query 
+                                          FROM series");
+    if ($query) {
+        my $sth = $dbh->prepare("UPDATE series SET query = ?
+                                               WHERE series_id = ?");
+        foreach my $row (@$query) {
+            my ($series_id, $query) = @$row;
+            
+            if ($query =~ /(?:^|&|;)$field=$old(?:&|$|;)/) {
+                $query =~ s/((?:^|&|;)$field=)$old(;|&|$)/$1$new$2/;
+                $replace_count++;
+            }
+            
+            $sth->execute($query, $series_id);
+        }
+    }
+
+    #$dbh->bz_commit_transaction();
+    print "series:      $replace_count replacements made.\n";
+}
+  
+# series_categories
+sub do_series_categories($$) {
+    my ($old, $new) = @_;
+    my $dbh = Bugzilla->dbh;
+
+    $dbh->do("UPDATE series_categories SET name = ? WHERE name = ?", 
+             undef, 
+             ($new, $old));
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 3) {
+    usage();
+    exit();
+}
+
+my ($field, $old, $new) = @ARGV;
+
+print "Changing all instances of '$old' to '$new'.\n\n";
+
+do_namedqueries($field, $old, $new);
+do_series($field, $old, $new);
+do_series_categories($old, $new);
+
+exit(0);
+
diff --git a/contrib/reorg-tools/migrate_crash_signatures.pl b/contrib/reorg-tools/migrate_crash_signatures.pl
new file mode 100644
index 000000000..b12446280
--- /dev/null
+++ b/contrib/reorg-tools/migrate_crash_signatures.pl
@@ -0,0 +1,126 @@
+#!/usr/bin/perl 
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis,  WITHOUT WARRANTY OF ANY KIND,  either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+#         FILE:  migrate_crash_signatures.pl
+#
+#        USAGE:  ./migrate_crash_signatures.pl  
+#
+#  DESCRIPTION:  Migrate current summary data on matched bugs to the
+#                new cf_crash_signature custom fields.
+#
+#      OPTIONS:  No params, then performs dry-run without updating the database.
+#                If a true value is passed as single argument, then the database
+#                is updated.
+# REQUIREMENTS:  None
+#         BUGS:  577724
+#        NOTES:  None
+#       AUTHOR:  David Lawrence (dkl@mozilla.com), 
+#      COMPANY:  Mozilla Corproation
+#      VERSION:  1.0
+#      CREATED:  05/31/2011 03:57:52 PM
+#     REVISION:  1
+#===============================================================================
+
+use strict;
+use warnings;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+use Data::Dumper;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my $UPDATE_DB = shift; # Pass true value as single argument to perform database update
+
+my $dbh = Bugzilla->dbh;
+
+# User to make changes as
+my $user_id = $dbh->selectrow_array(
+    "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'");
+$user_id or die "Can't find user ID for 'nobody\@mozilla.org'\n";
+
+my $field_id = $dbh->selectrow_array(
+    "SELECT id FROM fielddefs WHERE name = 'cf_crash_signature'");
+$field_id or die "Can't find field ID for 'cf_crash_signature' field\n";
+
+# Search criteria
+# a) crash or topcrash keyword,  
+# b) not have [notacrash] in whiteboard,  
+# c) have a properly formulated [@ ...]
+
+# crash and topcrash keyword ids
+my $crash_keyword_id = $dbh->selectrow_array(
+    "SELECT id FROM keyworddefs WHERE name = 'crash'");
+$crash_keyword_id or die "Can't find keyword id for 'crash'\n";
+
+my $topcrash_keyword_id = $dbh->selectrow_array(
+    "SELECT id FROM keyworddefs WHERE name = 'topcrash'");
+$topcrash_keyword_id or die "Can't find keyword id for 'topcrash'\n";
+
+# main search query
+my $bugs = $dbh->selectall_arrayref("
+    SELECT bugs.bug_id, bugs.short_desc
+      FROM bugs LEFT JOIN keywords ON bugs.bug_id = keywords.bug_id
+     WHERE (keywords.keywordid = ? OR keywords.keywordid = ?)
+           AND bugs.status_whiteboard NOT REGEXP '\\\\[notacrash\\\\]'
+           AND bugs.short_desc REGEXP '\\\\[@.+\\\\]'
+           AND (bugs.cf_crash_signature IS NULL OR bugs.cf_crash_signature = '')
+  ORDER BY bugs.bug_id",
+    {'Slice' => {}}, $crash_keyword_id, $topcrash_keyword_id);
+
+my $bug_count = scalar @$bugs;
+$bug_count or die "No bugs were found in matching search criteria.\n";
+
+print "Migrating $bug_count bugs to new crash signature field\n";
+
+$dbh->bz_start_transaction() if $UPDATE_DB;
+
+foreach my $bug (@$bugs) {
+    my $bug_id  = $bug->{'bug_id'};
+    my $summary = $bug->{'short_desc'};
+
+    print "Updating bug $bug_id ...";
+   
+    my @signatures;
+    while ($summary =~ /(\[\@(?:\[.*\]|[^\[])*\])/g) {
+        push(@signatures, $1);
+    }
+ 
+    if (@signatures && $UPDATE_DB) {
+        my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+	    $dbh->do("UPDATE bugs SET cf_crash_signature = ? WHERE bug_id = ?",
+		         undef, join("\n", @signatures), $bug_id);
+    	$dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) " .
+       	         "VALUES (?, ?, ?, ?, '', ?)",
+                 undef, $bug_id, $user_id, $timestamp, $field_id, join("\n", @signatures));
+        $dbh->do("UPDATE bugs SET delta_ts = ?, lastdiffed = ? WHERE bug_id = ?", 
+                 undef, $timestamp, $timestamp, $bug_id);
+    }
+    elsif (@signatures) {
+	    print Dumper(\@signatures);
+    }
+
+    print "done.\n";
+}
+
+$dbh->bz_commit_transaction() if $UPDATE_DB;
diff --git a/contrib/reorg-tools/move_flag_types.pl b/contrib/reorg-tools/move_flag_types.pl
new file mode 100644
index 000000000..a75b7f497
--- /dev/null
+++ b/contrib/reorg-tools/move_flag_types.pl
@@ -0,0 +1,168 @@
+#!/usr/bin/perl 
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+# 
+# Software distributed under the License is distributed on an "AS
+# IS" basis,  WITHOUT WARRANTY OF ANY KIND,  either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+# 
+# The Initial Developer of the Original Code is Mozilla Foundation 
+# Portions created by the Initial Developer are Copyright (C) 2011 the
+# Initial Developer. All Rights Reserved.
+#
+#===============================================================================
+#
+#         FILE:  move_flag_types.pl
+#
+#        USAGE:  ./move_flag_types.pl  
+#
+#  DESCRIPTION:  Move current set flag from one type_id to another
+#                based on product and optionally component.
+#
+#      OPTIONS:  ---
+# REQUIREMENTS:  ---
+#         BUGS:  ---
+#        NOTES:  ---
+#       AUTHOR:  David Lawrence (:dkl), dkl@mozilla.com
+#      COMPANY:  Mozilla Foundation
+#      VERSION:  1.0
+#      CREATED:  08/22/2011 05:18:06 PM
+#     REVISION:  ---
+#===============================================================================
+
+=head1 NAME
+
+move_flag_types.pl - Move currently set flags from one type id to another based
+on product and optionally component.
+
+=head1 SYNOPSIS
+
+This script will move bugs matching a specific product (and optionally a component)
+from one flag type id to another if the bug has the flag set to either +, -, or ?.
+
+./move_flag_types.pl --old-id 4 --new-id 720 --product Firefox --component Installer
+
+=head1 OPTIONS
+
+=over
+
+=item B<--help|-h|?>
+
+Print a brief help message and exits.
+
+=item B<--oldid|-o>
+
+Old flag type id. Use editflagtypes.cgi to determine the type id from the URL.
+
+=item B<--newid|-n>
+
+New flag type id. Use editflagtypes.cgi to determine the type id from the URL.
+
+=item B<--product|-p> 
+
+The product that the bugs most be assigned to.
+
+=item B<--component|-c>
+
+Optional: The component of the given product that the bugs must be assigned to.
+
+=item B<--doit|-d>
+
+Without this argument, changes are not actually committed to the database.
+
+=back
+
+=cut
+
+use strict;
+use warnings;
+
+use lib '.';
+
+use Bugzilla;
+use Getopt::Long;
+use Pod::Usage;
+
+my %params;
+GetOptions(\%params, 'help|h|?', 'oldid|o=s', 'newid|n=s',
+                     'product|p=s', 'component|c:s', 'doit|d') or pod2usage(1);
+
+if ($params{'help'} || !$params{'oldid'}
+    || !$params{'newid'} || !$params{'product'}) {
+    pod2usage({ -message => "Missing required argument", 
+                -exitval => 1 });
+}
+
+# Set defaults
+$params{'doit'} ||= 0;
+$params{'component'} ||= '';
+
+my $dbh = Bugzilla->dbh;
+
+# Get the flag names
+my $old_flag_name = $dbh->selectrow_array(
+    "SELECT name FROM flagtypes WHERE id = ?", 
+    undef,  $params{'oldid'});
+my $new_flag_name = $dbh->selectrow_array(
+    "SELECT name FROM flagtypes WHERE id = ?",   
+    undef,   $params{'newid'});
+
+# Find the product id
+my $product_id = $dbh->selectrow_array(
+    "SELECT id FROM products WHERE name = ?", 
+    undef, $params{'product'});
+
+# Find the component id if not __ANY__
+my $component_id;
+if ($params{'component'}) {
+    $component_id = $dbh->selectrow_array(
+        "SELECT id FROM components WHERE name = ? AND product_id = ?", 
+        undef, $params{'component'}, $product_id);
+}
+
+my @query_args = ($params{'oldid'});
+
+my $flag_query = "SELECT flags.id AS flag_id, flags.bug_id AS bug_id
+                    FROM flags JOIN bugs ON flags.bug_id = bugs.bug_id 
+                   WHERE flags.type_id = ? ";
+
+if ($component_id) {
+    # No need to compare against product_id as component_id is already
+    # tied to a specific product
+    $flag_query .= "AND bugs.component_id = ?";
+    push(@query_args, $component_id);
+}
+else {
+    # All bugs for a product regardless of component
+    $flag_query .= "AND bugs.product_id = ?";
+    push(@query_args, $product_id);
+}
+
+my $flags = $dbh->selectall_arrayref($flag_query, undef, @query_args);
+
+if (@$flags) {
+    print "Moving '" . scalar @$flags . "' flags " . 
+          "from $old_flag_name (" . $params{'oldid'} . ") " .
+          "to $new_flag_name (" . $params{'newid'} . ")...\n";
+
+    if (!$params{'doit'}) {
+        print "Pass the argument --doit or -d to permanently make changes to the database.\n";
+    }  
+    else {
+        my $flag_update_sth = $dbh->prepare("UPDATE flags SET type_id = ? WHERE id = ?");
+
+        foreach my $flag (@$flags) {
+            my ($flag_id, $bug_id) = @$flag;
+            print "Bug: $bug_id Flag: $flag_id\n";
+            $flag_update_sth->execute($params{'newid'}, $flag_id);
+        }
+    }
+}
+else {
+    print "No flags to move\n";
+}
diff --git a/contrib/reorg-tools/movebugs.pl b/contrib/reorg-tools/movebugs.pl
new file mode 100644
index 000000000..33156dad7
--- /dev/null
+++ b/contrib/reorg-tools/movebugs.pl
@@ -0,0 +1,151 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Cwd 'abs_path';
+use File::Basename;
+BEGIN {
+    my $root = abs_path(dirname(__FILE__) . '/../..');
+    chdir($root);
+}
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 4) {
+    die <   
+
+Eg. movebugs.pl mozilla.org bmo bugzilla.mozilla.org admin
+Will move all bugs in the mozilla.org:bmo component to the
+bugzilla.mozilla.org:admin component.
+
+The new product must have matching versions and milestones from the old
+product.
+USAGE
+}
+
+my ($old_product, $old_component, $new_product, $new_component) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+my $old_product_id = $dbh->selectrow_array(
+    "SELECT id FROM products WHERE name=?",
+    undef, $old_product);
+$old_product_id
+    or die "Can't find product ID for '$old_product'.\n";
+
+my $old_component_id = $dbh->selectrow_array(
+    "SELECT id FROM components WHERE name=? AND product_id=?",
+    undef, $old_component, $old_product_id);
+$old_component_id
+    or die "Can't find component ID for '$old_component'.\n";
+
+my $new_product_id = $dbh->selectrow_array(
+    "SELECT id FROM products WHERE name=?",
+    undef, $new_product);
+$new_product_id
+    or die "Can't find product ID for '$new_product'.\n";
+
+my $new_component_id = $dbh->selectrow_array(
+    "SELECT id FROM components WHERE name=? AND product_id=?",
+    undef, $new_component, $new_product_id);
+$new_component_id
+    or die "Can't find component ID for '$new_component'.\n";
+
+my $product_field_id = $dbh->selectrow_array(
+    "SELECT id FROM fielddefs WHERE name = 'product'");
+$product_field_id
+    or die "Can't find field ID for 'product' field\n";
+my $component_field_id = $dbh->selectrow_array(
+    "SELECT id FROM fielddefs WHERE name = 'component'");
+$component_field_id
+    or die "Can't find field ID for 'component' field\n";
+
+my $user_id = $dbh->selectrow_array(
+    "SELECT userid FROM profiles WHERE login_name='nobody\@mozilla.org'");
+$user_id
+    or die "Can't find user ID for 'nobody\@mozilla.org'\n";
+
+$dbh->bz_start_transaction();
+
+# build list of bugs
+my $ra_ids = $dbh->selectcol_arrayref(
+    "SELECT bug_id FROM bugs WHERE product_id=? AND component_id=?",
+    undef, $old_product_id, $old_component_id);
+my $bug_count = scalar @$ra_ids;
+$bug_count
+    or die "No bugs were found in '$old_component'\n";
+my $where_sql = 'bug_id IN (' . join(',', @$ra_ids) . ')';
+
+# check versions
+my @missing_versions;
+my $ra_versions = $dbh->selectcol_arrayref(
+    "SELECT DISTINCT version FROM bugs WHERE $where_sql");
+foreach my $version (@$ra_versions) {
+    my $has_version = $dbh->selectrow_array(
+        "SELECT 1 FROM versions WHERE product_id=? AND value=?",
+        undef, $new_product_id, $version);
+    push @missing_versions, $version unless $has_version;
+}
+
+# check milestones
+my @missing_milestones;
+my $ra_milestones = $dbh->selectcol_arrayref(
+    "SELECT DISTINCT target_milestone FROM bugs WHERE $where_sql");
+foreach my $milestone (@$ra_milestones) {
+    my $has_milestone = $dbh->selectrow_array(
+        "SELECT 1 FROM milestones WHERE product_id=? AND value=?",
+        undef, $new_product_id, $milestone);
+    push @missing_milestones, $milestone unless $has_milestone;
+}
+
+my $missing_error = '';
+if (@missing_versions) {
+    $missing_error .= "'$new_product' is missing the following version(s):\n  " .
+        join("\n  ", @missing_versions) . "\n";
+}
+if (@missing_milestones) {
+    $missing_error .= "'$new_product' is missing the following milestone(s):\n  " .
+        join("\n  ", @missing_milestones) . "\n";
+}
+die $missing_error if $missing_error;
+
+# confirmation
+print < to stop or  to continue...
+EOF
+getc();
+
+print "Moving $bug_count bugs from $old_product:$old_component to $new_product:$new_component\n";
+
+# update bugs
+$dbh->do(
+    "UPDATE bugs SET product_id=?, component_id=? WHERE $where_sql",
+    undef, $new_product_id, $new_component_id);
+
+# touch bugs 
+$dbh->do("UPDATE bugs SET delta_ts=NOW() WHERE $where_sql");
+$dbh->do("UPDATE bugs SET lastdiffed=NOW() WHERE $where_sql");
+
+# update bugs_activity
+$dbh->do(
+    "INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) 
+          SELECT bug_id, ?, delta_ts, ?, ?, ?  FROM bugs WHERE $where_sql",
+    undef,
+    $user_id, $product_field_id, $old_product, $new_product);
+$dbh->do(
+    "INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed, added) 
+          SELECT bug_id, ?, delta_ts, ?, ?, ?  FROM bugs WHERE $where_sql",
+    undef,
+    $user_id, $component_field_id, $old_component, $new_component);
+
+$dbh->bz_commit_transaction();
+
diff --git a/contrib/reorg-tools/movecomponent.pl b/contrib/reorg-tools/movecomponent.pl
new file mode 100644
index 000000000..8f8bc0abc
--- /dev/null
+++ b/contrib/reorg-tools/movecomponent.pl
@@ -0,0 +1,193 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham 
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+#
+
+use strict;
+
+use Cwd 'abs_path';
+use File::Basename;
+BEGIN {
+    my $root = abs_path(dirname(__FILE__) . '/../..');
+    chdir($root);
+}
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+sub usage() {
+    print <   
+
+E.g.: movecomponent.pl ReplicationEngine FoodReplicator SeaMonkey
+will move the component "SeaMonkey" from the product "ReplicationEngine"
+to the product "FoodReplicator".
+
+Important: You must make sure the milestones and versions of the bugs in the
+component are available in the new product. See syncmsandversions.pl.
+
+Pass in a true value for "doit" to make the database changes permament.
+USAGE
+
+    exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 3) {
+    usage();
+    exit();
+}
+
+my ($oldproduct, $newproduct, $component, $doit) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+$dbh->{'AutoCommit'} = 0 unless $doit; # Turn off autocommit by default
+
+# Find product IDs
+my $oldprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $oldproduct);
+if (!$oldprodid) {
+    print "Can't find product ID for '$oldproduct'.\n";
+    exit(1);
+}
+
+my $newprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $newproduct);
+if (!$newprodid) {
+    print "Can't find product ID for '$newproduct'.\n";
+    exit(1);
+}
+
+# Find component ID
+my $compid = $dbh->selectrow_array("SELECT id FROM components 
+                                    WHERE name = ? AND product_id = ?",
+                                   undef, $component, $oldprodid);
+if (!$compid) {
+    print "Can't find component ID for '$component' in product " .            
+          "'$oldproduct'.\n";
+    exit(1);
+}
+
+my $fieldid = $dbh->selectrow_array("SELECT id FROM fielddefs 
+                                     WHERE name = 'product'");
+if (!$fieldid) {
+    print "Can't find field ID for 'product' field!\n";
+    exit(1);
+}
+
+# check versions
+my @missing_versions;
+my $ra_versions = $dbh->selectcol_arrayref(
+    "SELECT DISTINCT version FROM bugs WHERE component_id = ?",
+    undef, $compid);
+foreach my $version (@$ra_versions) {
+    my $has_version = $dbh->selectrow_array(
+        "SELECT 1 FROM versions WHERE product_id = ? AND value = ?",
+        undef, $newprodid, $version);
+    push @missing_versions, $version unless $has_version;
+}
+
+# check milestones
+my @missing_milestones;
+my $ra_milestones = $dbh->selectcol_arrayref(
+    "SELECT DISTINCT target_milestone FROM bugs WHERE component_id = ?",
+    undef, $compid);
+foreach my $milestone (@$ra_milestones) {
+    my $has_milestone = $dbh->selectrow_array(
+        "SELECT 1 FROM milestones WHERE product_id=? AND value=?",
+        undef, $newprodid, $milestone);
+    push @missing_milestones, $milestone unless $has_milestone;
+}
+
+my $missing_error = '';
+if (@missing_versions) {
+    $missing_error .= "'$newproduct' is missing the following version(s):\n  " .
+        join("\n  ", @missing_versions) . "\n";
+}
+if (@missing_milestones) {
+    $missing_error .= "'$newproduct' is missing the following milestone(s):\n  " .
+        join("\n  ", @missing_milestones) . "\n";
+}
+die $missing_error if $missing_error;
+
+# confirmation
+print < to stop or  to continue...
+EOF
+getc();
+
+print "Moving '$component' from '$oldproduct' to '$newproduct'...\n\n";
+$dbh->bz_start_transaction() if $doit;
+
+# Bugs table
+$dbh->do("UPDATE bugs SET product_id = ? WHERE component_id = ?", 
+         undef,
+         ($newprodid, $compid));
+
+# Flags tables
+$dbh->do("UPDATE flaginclusions SET product_id = ? WHERE component_id = ?", 
+         undef,
+         ($newprodid, $compid));
+
+$dbh->do("UPDATE flagexclusions SET product_id = ? WHERE component_id = ?", 
+         undef,
+         ($newprodid, $compid));
+
+# Components
+$dbh->do("UPDATE components SET product_id = ? WHERE id = ?", 
+         undef,
+         ($newprodid, $compid));
+
+# Mark bugs as touched
+$dbh->do("UPDATE bugs SET delta_ts = NOW() 
+          WHERE component_id = ?", undef, $compid);
+$dbh->do("UPDATE bugs SET lastdiffed = NOW() 
+          WHERE component_id = ?", undef, $compid);
+
+# Update bugs_activity
+my $userid = 1; # nobody@mozilla.org
+
+$dbh->do("INSERT INTO bugs_activity(bug_id, who, bug_when, fieldid, removed,
+                                    added) 
+             SELECT bug_id, ?, delta_ts, ?, ?, ? 
+             FROM bugs WHERE component_id = ?",
+         undef,
+         ($userid, $fieldid, $oldproduct, $newproduct, $compid));
+
+$dbh->bz_commit_transaction() if $doit;
+
+exit(0);
+
diff --git a/contrib/reorg-tools/syncflags.pl b/contrib/reorg-tools/syncflags.pl
new file mode 100644
index 000000000..6c5b8293a
--- /dev/null
+++ b/contrib/reorg-tools/syncflags.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham 
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+
+sub usage() {
+    print < 
+
+E.g.: syncflags.pl FoodReplicator SeaMonkey
+will copy any flag inclusions (only) for the product "FoodReplicator"
+so matching inclusions exist for the product "SeaMonkey". This script is 
+normally used prior to moving components from srcproduct to tgtproduct.
+USAGE
+
+    exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+    usage();
+    exit();
+}
+
+my ($srcproduct, $tgtproduct) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+# Find product IDs
+my $srcprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $srcproduct);
+if (!$srcprodid) {
+    print "Can't find product ID for '$srcproduct'.\n";
+    exit(1);
+}
+
+my $tgtprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $tgtproduct);
+if (!$tgtprodid) {
+    print "Can't find product ID for '$tgtproduct'.\n";
+    exit(1);
+}
+
+$dbh->do("INSERT INTO flaginclusions(component_id, type_id, product_id) 
+               SELECT fi1.component_id, fi1.type_id, ? FROM flaginclusions fi1 
+            LEFT JOIN flaginclusions fi2 
+                      ON fi1.type_id = fi2.type_id
+                      AND fi2.product_id = ? 
+                WHERE fi1.product_id = ? 
+                      AND fi2.type_id IS NULL",
+        undef,
+        $tgtprodid, $tgtprodid, $srcprodid);
+
+exit(0);
diff --git a/contrib/reorg-tools/syncmsandversions.pl b/contrib/reorg-tools/syncmsandversions.pl
new file mode 100644
index 000000000..b25b3348b
--- /dev/null
+++ b/contrib/reorg-tools/syncmsandversions.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Gervase Markham 
+
+# See also https://bugzilla.mozilla.org/show_bug.cgi?id=119569
+
+use strict;
+
+use lib qw(. lib);
+
+use Bugzilla;
+use Bugzilla::Constants;
+
+sub usage() {
+    print < 
+
+E.g.: syncmsandversions.pl FoodReplicator SeaMonkey
+will copy any versions and milstones in the product "FoodReplicator"
+which do not exist in product "SeaMonkey" into it. This script is normally
+used prior to moving components from srcproduct to tgtproduct.
+USAGE
+
+    exit(1);
+}
+
+#############################################################################
+# MAIN CODE
+#############################################################################
+
+# This is a pure command line script.
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+if (scalar @ARGV < 2) {
+    usage();
+    exit();
+}
+
+my ($srcproduct, $tgtproduct) = @ARGV;
+
+my $dbh = Bugzilla->dbh;
+
+# Find product IDs
+my $srcprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $srcproduct);
+if (!$srcprodid) {
+    print "Can't find product ID for '$srcproduct'.\n";
+    exit(1);
+}
+
+my $tgtprodid = $dbh->selectrow_array("SELECT id FROM products WHERE name = ?",
+                                      undef, $tgtproduct);
+if (!$tgtprodid) {
+    print "Can't find product ID for '$tgtproduct'.\n";
+    exit(1);
+}
+
+#$dbh->bz_start_transaction();
+
+$dbh->do("INSERT INTO milestones(value, sortkey, product_id) 
+    SELECT m1.value, m1.sortkey, ? FROM milestones m1 
+        LEFT JOIN milestones m2 ON m1.value = m2.value AND 
+                                   m2.product_id = ? 
+        WHERE m1.product_id = ? AND m2.value IS NULL",
+        undef,
+        $tgtprodid, $tgtprodid, $srcprodid);
+
+$dbh->do("INSERT INTO versions(value, product_id) 
+    SELECT v1.value, ? FROM versions v1 
+        LEFT JOIN versions v2 ON v1.value = v2.value AND 
+                                 v2.product_id = ? 
+        WHERE v1.product_id = ? AND v2.value IS NULL",
+        undef,
+        $tgtprodid, $tgtprodid, $srcprodid);
+
+$dbh->do("INSERT INTO group_control_map (group_id, product_id, entry, membercontrol, othercontrol, canedit, editcomponents, editbugs, canconfirm)
+     SELECT g1.group_id, ?, g1.entry, g1.membercontrol, g1.othercontrol, g1.canedit, g1.editcomponents, g1.editbugs, g1.canconfirm
+     FROM group_control_map g1
+     LEFT JOIN group_control_map g2 ON g1.product_id = ? AND
+                                       g2.product_id = ? AND
+                                       g1.group_id = g2.group_id
+     WHERE g1.product_id = ? AND g2.group_id IS NULL",
+     undef,
+     $tgtprodid, $srcprodid, $tgtprodid, $srcprodid);
+
+#$dbh->bz_commit_transaction();
+
+exit(0);
+
diff --git a/contrib/sanitizeme.pl b/contrib/sanitizeme.pl
new file mode 100644
index 000000000..362700be0
--- /dev/null
+++ b/contrib/sanitizeme.pl
@@ -0,0 +1,176 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is the Mozilla
+# Corporation. Portions created by Mozilla are
+# Copyright (C) 2006 Mozilla Foundation. All Rights Reserved.
+#
+# Contributor(s): Myk Melez 
+#                 Alex Brugh 
+#                 Dave Miller 
+#                 Byron Jones 
+
+use strict;
+
+use lib qw(.);
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+
+use Getopt::Long;
+
+my $dbh = Bugzilla->dbh;
+
+# This SQL is designed to sanitize a copy of a Bugzilla database so that it 
+# doesn't contain any information that can't be viewed from a web browser by
+# a user who is not logged in.                                              
+
+# Last validated against Bugzilla version 4.0
+
+my ($dry_run, $from_cron, $keep_attachments, $keep_groups,
+    $keep_passwords, $keep_insider, $trace) = (0, 0, 0, '', 0, 0, 0);
+my $keep_groups_sql = '';
+
+GetOptions(
+    "dry-run" => \$dry_run,
+    "from-cron" => \$from_cron,
+    "keep-attachments" => \$keep_attachments,
+    "keep-passwords" => \$keep_passwords,
+    "keep-insider" => \$keep_insider,
+    "keep-groups:s" => \$keep_groups,
+    "trace" => \$trace,
+) or exit;
+
+if ($keep_groups ne '') {
+    my @groups;
+    foreach my $group_id (split(/\s*,\s*/, $keep_groups)) {
+        my $group;
+        if ($group_id =~ /\D/) {
+            $group = Bugzilla::Group->new({ name => $group_id });
+        } else {
+            $group = Bugzilla::Group->new($group_id);
+        }
+        die "Invalid group '$group_id'\n" unless $group;
+        push @groups, $group->id;
+    }
+    $keep_groups_sql = "NOT IN (" . join(",", @groups) . ")";
+}
+
+$dbh->{TraceLevel} = 1 if $trace;
+
+if ($dry_run) {
+    print "** dry run : no changes to the database will be made **\n";
+    $dbh->bz_start_transaction();
+}
+eval {
+    delete_non_public_products();
+    delete_secure_bugs();
+    delete_insider_comments() unless $keep_insider;
+    delete_security_groups();
+    delete_sensitive_user_data();
+    delete_attachment_data() unless $keep_attachments;
+    print "All done!\n";
+    $dbh->bz_rollback_transaction() if $dry_run;
+};
+if ($@) {
+    $dbh->bz_rollback_transaction() if $dry_run;
+    die "$@" if $@;
+}
+
+sub delete_non_public_products {
+    # Delete all non-public products, and all data associated with them
+    my @products = Bugzilla::Product->get_all();
+    my $mandatory = CONTROLMAPMANDATORY;
+    foreach my $product (@products) {
+        # if there are any mandatory groups on the product, nuke it and
+        # everything associated with it (including the bugs)
+        Bugzilla->params->{'allowbugdeletion'} = 1; # override this in memory for now
+        my $mandatorygroups = $dbh->selectcol_arrayref("SELECT group_id FROM group_control_map WHERE product_id = ? AND (membercontrol = $mandatory)", undef, $product->id);
+        if (0 < scalar(@$mandatorygroups)) {
+            print "Deleting product '" . $product->name . "'...\n";
+            $product->remove_from_db();
+        }
+    }
+}
+
+sub delete_secure_bugs {
+    # Delete all data for bugs in security groups.
+    my $buglist = $dbh->selectall_arrayref(
+        $keep_groups
+        ? "SELECT DISTINCT bug_id FROM bug_group_map  WHERE group_id $keep_groups_sql"
+        : "SELECT DISTINCT bug_id FROM bug_group_map"
+    );
+    $|=1; # disable buffering so the bug progress counter works
+    my $numbugs = scalar(@$buglist);
+    my $bugnum = 0;
+    print "Deleting $numbugs bugs in " . ($keep_groups ? 'non-' : '') . "security groups...\n";
+    foreach my $row (@$buglist) {
+        my $bug_id = $row->[0];
+        $bugnum++;
+        print "\r$bugnum/$numbugs" unless $from_cron;
+        my $bug = new Bugzilla::Bug($bug_id);
+        $bug->remove_from_db();
+    }
+    print "\rDone            \n" unless $from_cron;
+}
+
+sub delete_insider_comments {
+    # Delete all 'insidergroup' comments and attachments
+    print "Deleting 'insidergroup' comments and attachments...\n";
+    $dbh->do("DELETE FROM longdescs WHERE isprivate = 1");
+    $dbh->do("DELETE attach_data FROM attachments JOIN attach_data ON attachments.attach_id = attach_data.id WHERE attachments.isprivate = 1");
+    $dbh->do("DELETE FROM attachments WHERE isprivate = 1");
+    $dbh->do("UPDATE bugs_fulltext SET comments = comments_noprivate");
+}
+
+sub delete_security_groups {
+    # Delete all security groups.
+    print "Deleting " . ($keep_groups ? 'non-' : '') . "security groups...\n";
+    $dbh->do("DELETE user_group_map FROM groups JOIN user_group_map ON groups.id = user_group_map.group_id WHERE groups.isbuggroup = 1");
+    $dbh->do("DELETE group_group_map FROM groups JOIN group_group_map ON (groups.id = group_group_map.member_id OR groups.id = group_group_map.grantor_id) WHERE groups.isbuggroup = 1");
+    $dbh->do("DELETE group_control_map FROM groups JOIN group_control_map ON groups.id = group_control_map.group_id WHERE groups.isbuggroup = 1");
+    $dbh->do("UPDATE flagtypes LEFT JOIN groups ON flagtypes.grant_group_id = groups.id SET grant_group_id = NULL WHERE groups.isbuggroup = 1");
+    $dbh->do("UPDATE flagtypes LEFT JOIN groups ON flagtypes.request_group_id = groups.id SET request_group_id = NULL WHERE groups.isbuggroup = 1");
+    if ($keep_groups) {
+        $dbh->do("DELETE FROM groups WHERE isbuggroup = 1 AND id $keep_groups_sql");
+    } else {
+        $dbh->do("DELETE FROM groups WHERE isbuggroup = 1");
+    }
+}
+
+sub delete_sensitive_user_data {
+    # Remove sensitive user account data.
+    print "Deleting sensitive user account data...\n";
+    $dbh->do("UPDATE profiles SET cryptpassword = 'deleted'") unless $keep_passwords;
+    $dbh->do("DELETE FROM profiles_activity");
+    $dbh->do("DELETE FROM profile_search");
+    $dbh->do("DELETE FROM namedqueries");
+    $dbh->do("DELETE FROM tokens");
+    $dbh->do("DELETE FROM logincookies");
+    $dbh->do("DELETE FROM login_failure");
+    $dbh->do("DELETE FROM ts_error");
+    $dbh->do("DELETE FROM ts_exitstatus");
+    $dbh->do("DELETE FROM ts_funcmap");
+    $dbh->do("DELETE FROM ts_job");
+    $dbh->do("DELETE FROM ts_note");
+}
+
+sub delete_attachment_data {
+    # Delete unnecessary attachment data.
+    print "Removing attachment data to preserve disk space...\n";
+    $dbh->do("UPDATE attach_data SET thedata = ''");
+}
+
diff --git a/contrib/verify-user.pl b/contrib/verify-user.pl
new file mode 100644
index 000000000..d12cd745f
--- /dev/null
+++ b/contrib/verify-user.pl
@@ -0,0 +1,129 @@
+#!/usr/bin/perl -wT
+# -*- Mode: perl; indent-tabs-mode: nil -*-
+#
+# The contents of this file are subject to the Mozilla Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is the Bugzilla Bug Tracking System.
+#
+# The Initial Developer of the Original Code is Netscape Communications
+# Corporation. Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): Myk Melez 
+#                 Dave Miller 
+
+# See if a user account has ever done anything
+
+# ./verify-user.pl foo@baz.com
+
+use strict;
+
+use lib qw(.);
+
+use Bugzilla;
+use Bugzilla::Util;
+use Bugzilla::DB;
+use Bugzilla::Constants;
+
+# Make sure accounts were specified on the command line and exist.
+my $user = $ARGV[0] || die "You must specify an user.\n";
+my $dbh = Bugzilla->dbh;
+my $sth;
+
+#$sth = $dbh->prepare("SELECT name, count(*) as qty from bugs, products where reporter=198524 and product_id=products.id group by name order by qty desc");
+#$sth->execute();
+#my $results = $sth->fetchall_arrayref();
+#use Data::Dumper;
+#print Data::Dumper::Dumper($results);
+#exit;
+
+trick_taint($user);
+if ($user =~ /^\d+$/) { # user ID passed instead of email
+  $sth = $dbh->prepare('SELECT login_name FROM profiles WHERE userid = ?');
+  $sth->execute($user);
+  ($user) = $sth->fetchrow_array || die "The user with ID $ARGV[0] does not exist.\n";
+  print "User $ARGV[0]'s login name is $user.\n";
+}
+$sth = $dbh->prepare("SELECT userid FROM profiles WHERE login_name = ?");
+$sth->execute($user);
+my ($user_id) = $sth->fetchrow_array || die "The user $user does not exist.\n";
+
+print "${user}'s ID is $user_id.\n";
+
+$sth = $dbh->prepare("SELECT DISTINCT ipaddr FROM logincookies WHERE userid = ?");
+$sth->execute($user_id);
+my $iplist = $sth->fetchall_arrayref;
+if (@$iplist > 0) {
+    print "This user has recently connected from the following IP addresses:\n";
+    foreach my $ip (@$iplist) {
+        print $$ip[0] . "\n";
+    }
+}
+
+
+# A list of tables and columns to be checked.
+my $columns = {
+  attachments       => ['submitter_id'] , 
+  bugs              => ['assigned_to', 'reporter', 'qa_contact'] , 
+  bugs_activity     => ['who'] , 
+  cc                => ['who'] , 
+  components        => ['initialowner', 'initialqacontact'] , 
+  flags             => ['setter_id', 'requestee_id'] , 
+  logincookies      => ['userid'] , 
+  longdescs         => ['who'] , 
+  namedqueries      => ['userid'] , 
+  profiles_activity => ['userid', 'who'] , 
+  quips             => ['userid'] , 
+  series            => ['creator'] ,
+  tokens            => ['userid'] , 
+  user_group_map    => ['user_id'] , 
+  votes             => ['who'] , 
+  watch             => ['watcher', 'watched'] , 
+  
+};
+
+my $fields = 0;
+# Check records for user.
+foreach my $table (keys(%$columns)) {
+  foreach my $column (@{$columns->{$table}}) {
+    $sth = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE $column = ?");
+    if ($table eq 'user_group_map') {
+      $sth = $dbh->prepare("SELECT COUNT(*) FROM $table WHERE $column = ? AND grant_type = " . GRANT_DIRECT);
+    }
+    $sth->execute($user_id);
+    my ($val) = $sth->fetchrow_array;
+    $fields++ if $val;
+    print "$table.$column: $val\n" if $val;
+  }
+}
+
+print "The user is mentioned in $fields fields.\n";
+
+if ($::ARGV[1] && $::ARGV[1] eq '-r') {
+    if ($fields == 0) {
+        $sth = $dbh->prepare("SELECT login_name FROM profiles WHERE login_name = ?");
+        my $count = 0;
+        print "Finding an unused recycle ID";
+        do {
+          $count++;
+          $sth->execute(sprintf("reuseme%03d\@bugzilla.org", $count));
+          print ".";
+        } while (my ($match) = $sth->fetchrow_array());
+        printf "\nUsing reuseme%03d\@bugzilla.org.\n", $count;
+        $dbh->do("DELETE FROM user_group_map WHERE user_id=?",undef,$user_id);
+        $dbh->do("UPDATE profiles SET realname='', cryptpassword='randomgarbage' WHERE userid=?",undef,$user_id);
+        $dbh->do("UPDATE profiles SET login_name=? WHERE userid=?",undef,sprintf("reuseme%03d\@bugzilla.org",$count),$user_id);
+    }
+    else {
+        print "Account has been used, so not recycling.\n";
+    }
+}
diff --git a/enter_bug.cgi b/enter_bug.cgi
index ffba2b09f..85e69e535 100755
--- a/enter_bug.cgi
+++ b/enter_bug.cgi
@@ -51,6 +51,7 @@ use Bugzilla::Keyword;
 use Bugzilla::Token;
 use Bugzilla::Field;
 use Bugzilla::Status;
+use Bugzilla::UserAgent;
 
 my $user = Bugzilla->login(LOGIN_REQUIRED);
 
@@ -62,9 +63,21 @@ my $dbh = Bugzilla->dbh;
 my $template = Bugzilla->template;
 my $vars = {};
 
+# BMO add a hook for the guided extension
+Bugzilla::Hook::process('enter_bug_start', { vars => $vars });
+
 # All pages point to the same part of the documentation.
 $vars->{'doc_section'} = 'bugreports.html';
 
+if (!$vars->{'disable_guided'}) {
+    # Purpose: force guided format for newbies
+    $cgi->param(-name=>'format', -value=>'guided') 
+        if !$cgi->param('format') && !$user->in_group('canconfirm');
+
+    $cgi->delete('format') 
+        if ($cgi->param('format') && ($cgi->param('format') eq "__default__"));
+}
+
 my $product_name = trim($cgi->param('product') || '');
 # Will contain the product object the bug is created in.
 my $product;
@@ -74,8 +87,14 @@ if ($product_name eq '') {
     my @enterable_products = @{$user->get_enterable_products};
     ThrowUserError('no_products') unless scalar(@enterable_products);
 
-    my $classification = Bugzilla->params->{'useclassification'} ?
-        scalar($cgi->param('classification')) : '__all';
+    # MOZILLA CUSTOMIZATION
+    # skip the classification selection page
+    my $classification;
+    if (Bugzilla->params->{'useclassification'}) {
+        $classification = scalar($cgi->param('classification')) || '__all';
+    } else {
+        $classification = '__all';
+    }
 
     # Unless a real classification name is given, we sort products
     # by classification.
@@ -166,195 +185,6 @@ sub formvalue {
     return Bugzilla->cgi->param($name) || $default || "";
 }
 
-# Takes the name of a field and a list of possible values for that 
-# field. Returns the first value in the list that is actually a 
-# valid value for that field.
-# The field should be named after its DB table.
-# Returns undef if none of the platforms match.
-sub pick_valid_field_value (@) {
-    my ($field, @values) = @_;
-    my $dbh = Bugzilla->dbh;
-
-    foreach my $value (@values) {
-        return $value if $dbh->selectrow_array(
-            "SELECT 1 FROM $field WHERE value = ?", undef, $value); 
-    }
-    return undef;
-}
-
-sub pickplatform {
-    return formvalue("rep_platform") if formvalue("rep_platform");
-
-    my @platform;
-
-    if (Bugzilla->params->{'defaultplatform'}) {
-        @platform = Bugzilla->params->{'defaultplatform'};
-    } else {
-        # If @platform is a list, this function will return the first
-        # item in the list that is a valid platform choice. If
-        # no choice is valid, we return "Other".
-        for ($ENV{'HTTP_USER_AGENT'}) {
-        #PowerPC
-            /\(.*PowerPC.*\)/i && do {push @platform, ("PowerPC", "Macintosh");};
-        #AMD64, Intel x86_64
-            /\(.*amd64.*\)/ && do {push @platform, ("AMD64", "x86_64", "PC");};
-            /\(.*x86_64.*\)/ && do {push @platform, ("AMD64", "x86_64", "PC");};
-        #Intel Itanium
-            /\(.*IA64.*\)/ && do {push @platform, "IA64";};
-        #Intel x86
-            /\(.*Intel.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-            /\(.*[ix0-9]86.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-        #Versions of Windows that only run on Intel x86
-            /\(.*Win(?:dows |)[39M].*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-            /\(.*Win(?:dows |)16.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-        #Sparc
-            /\(.*sparc.*\)/ && do {push @platform, ("Sparc", "Sun");};
-            /\(.*sun4.*\)/ && do {push @platform, ("Sparc", "Sun");};
-        #Alpha
-            /\(.*AXP.*\)/i && do {push @platform, ("Alpha", "DEC");};
-            /\(.*[ _]Alpha.\D/i && do {push @platform, ("Alpha", "DEC");};
-            /\(.*[ _]Alpha\)/i && do {push @platform, ("Alpha", "DEC");};
-        #MIPS
-            /\(.*IRIX.*\)/i && do {push @platform, ("MIPS", "SGI");};
-            /\(.*MIPS.*\)/i && do {push @platform, ("MIPS", "SGI");};
-        #68k
-            /\(.*68K.*\)/ && do {push @platform, ("68k", "Macintosh");};
-            /\(.*680[x0]0.*\)/ && do {push @platform, ("68k", "Macintosh");};
-        #HP
-            /\(.*9000.*\)/ && do {push @platform, ("PA-RISC", "HP");};
-        #ARM
-            /\(.*ARM.*\)/ && do {push @platform, ("ARM", "PocketPC");};
-        #PocketPC intentionally before PowerPC
-            /\(.*Windows CE.*PPC.*\)/ && do {push @platform, ("ARM", "PocketPC");};
-        #PowerPC
-            /\(.*PPC.*\)/ && do {push @platform, ("PowerPC", "Macintosh");};
-            /\(.*AIX.*\)/ && do {push @platform, ("PowerPC", "Macintosh");};
-        #Stereotypical and broken
-            /\(.*Windows CE.*\)/ && do {push @platform, ("ARM", "PocketPC");};
-            /\(.*Macintosh.*\)/ && do {push @platform, ("68k", "Macintosh");};
-            /\(.*Mac OS [89].*\)/ && do {push @platform, ("68k", "Macintosh");};
-            /\(.*Win64.*\)/ && do {push @platform, "IA64";};
-            /\(Win.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-            /\(.*Win(?:dows[ -])NT.*\)/ && do {push @platform, ("IA32", "x86", "PC");};
-            /\(.*OSF.*\)/ && do {push @platform, ("Alpha", "DEC");};
-            /\(.*HP-?UX.*\)/i && do {push @platform, ("PA-RISC", "HP");};
-            /\(.*IRIX.*\)/i && do {push @platform, ("MIPS", "SGI");};
-            /\(.*(SunOS|Solaris).*\)/ && do {push @platform, ("Sparc", "Sun");};
-        #Braindead old browsers who didn't follow convention:
-            /Amiga/ && do {push @platform, ("68k", "Macintosh");};
-            /WinMosaic/ && do {push @platform, ("IA32", "x86", "PC");};
-        }
-    }
-
-    return pick_valid_field_value('rep_platform', @platform) || "Other";
-}
-
-sub pickos {
-    if (formvalue('op_sys') ne "") {
-        return formvalue('op_sys');
-    }
-
-    my @os = ();
-
-    if (Bugzilla->params->{'defaultopsys'}) {
-        @os = Bugzilla->params->{'defaultopsys'};
-    } else {
-        # This function will return the first
-        # item in @os that is a valid platform choice. If
-        # no choice is valid, we return "Other".
-        for ($ENV{'HTTP_USER_AGENT'}) {
-            /\(.*IRIX.*\)/ && do {push @os, "IRIX";};
-            /\(.*OSF.*\)/ && do {push @os, "OSF/1";};
-            /\(.*Linux.*\)/ && do {push @os, "Linux";};
-            /\(.*Solaris.*\)/ && do {push @os, "Solaris";};
-            /\(.*SunOS.*\)/ && do {
-              /\(.*SunOS 5.11.*\)/ && do {push @os, ("OpenSolaris", "Opensolaris", "Solaris 11");};
-              /\(.*SunOS 5.10.*\)/ && do {push @os, "Solaris 10";};
-              /\(.*SunOS 5.9.*\)/ && do {push @os, "Solaris 9";};
-              /\(.*SunOS 5.8.*\)/ && do {push @os, "Solaris 8";};
-              /\(.*SunOS 5.7.*\)/ && do {push @os, "Solaris 7";};
-              /\(.*SunOS 5.6.*\)/ && do {push @os, "Solaris 6";};
-              /\(.*SunOS 5.5.*\)/ && do {push @os, "Solaris 5";};
-              /\(.*SunOS 5.*\)/ && do {push @os, "Solaris";};
-              /\(.*SunOS.*sun4u.*\)/ && do {push @os, "Solaris";};
-              /\(.*SunOS.*i86pc.*\)/ && do {push @os, "Solaris";};
-              /\(.*SunOS.*\)/ && do {push @os, "SunOS";};
-            };
-            /\(.*HP-?UX.*\)/ && do {push @os, "HP-UX";};
-            /\(.*BSD.*\)/ && do {
-              /\(.*BSD\/(?:OS|386).*\)/ && do {push @os, "BSDI";};
-              /\(.*FreeBSD.*\)/ && do {push @os, "FreeBSD";};
-              /\(.*OpenBSD.*\)/ && do {push @os, "OpenBSD";};
-              /\(.*NetBSD.*\)/ && do {push @os, "NetBSD";};
-            };
-            /\(.*BeOS.*\)/ && do {push @os, "BeOS";};
-            /\(.*AIX.*\)/ && do {push @os, "AIX";};
-            /\(.*OS\/2.*\)/ && do {push @os, "OS/2";};
-            /\(.*QNX.*\)/ && do {push @os, "Neutrino";};
-            /\(.*VMS.*\)/ && do {push @os, "OpenVMS";};
-            /\(.*Win.*\)/ && do {
-              /\(.*Windows XP.*\)/ && do {push @os, "Windows XP";};
-              /\(.*Windows NT 6\.1.*\)/ && do {push @os, "Windows 7";};
-              /\(.*Windows NT 6\.0.*\)/ && do {push @os, "Windows Vista";};
-              /\(.*Windows NT 5\.2.*\)/ && do {push @os, "Windows Server 2003";};
-              /\(.*Windows NT 5\.1.*\)/ && do {push @os, "Windows XP";};
-              /\(.*Windows 2000.*\)/ && do {push @os, "Windows 2000";};
-              /\(.*Windows NT 5.*\)/ && do {push @os, "Windows 2000";};
-              /\(.*Win.*9[8x].*4\.9.*\)/ && do {push @os, "Windows ME";};
-              /\(.*Win(?:dows |)M[Ee].*\)/ && do {push @os, "Windows ME";};
-              /\(.*Win(?:dows |)98.*\)/ && do {push @os, "Windows 98";};
-              /\(.*Win(?:dows |)95.*\)/ && do {push @os, "Windows 95";};
-              /\(.*Win(?:dows |)16.*\)/ && do {push @os, "Windows 3.1";};
-              /\(.*Win(?:dows[ -]|)NT.*\)/ && do {push @os, "Windows NT";};
-              /\(.*Windows.*NT.*\)/ && do {push @os, "Windows NT";};
-            };
-            /\(.*Mac OS X.*\)/ && do {
-              /\(.*Mac OS X (?:|Mach-O |\()10.6.*\)/ && do {push @os, "Mac OS X 10.6";};
-              /\(.*Mac OS X (?:|Mach-O |\()10.5.*\)/ && do {push @os, "Mac OS X 10.5";};
-              /\(.*Mac OS X (?:|Mach-O |\()10.4.*\)/ && do {push @os, "Mac OS X 10.4";};
-              /\(.*Mac OS X (?:|Mach-O |\()10.3.*\)/ && do {push @os, "Mac OS X 10.3";};
-              /\(.*Mac OS X (?:|Mach-O |\()10.2.*\)/ && do {push @os, "Mac OS X 10.2";};
-              /\(.*Mac OS X (?:|Mach-O |\()10.1.*\)/ && do {push @os, "Mac OS X 10.1";};
-        # Unfortunately, OS X 10.4 was the first to support Intel. This is
-        # fallback support because some browsers refused to include the OS
-        # Version.
-              /\(.*Intel.*Mac OS X.*\)/ && do {push @os, "Mac OS X 10.4";};
-        # OS X 10.3 is the most likely default version of PowerPC Macs
-        # OS X 10.0 is more for configurations which didn't setup 10.x versions
-              /\(.*Mac OS X.*\)/ && do {push @os, ("Mac OS X 10.3", "Mac OS X 10.0", "Mac OS X");};
-            };
-            /\(.*32bit.*\)/ && do {push @os, "Windows 95";};
-            /\(.*16bit.*\)/ && do {push @os, "Windows 3.1";};
-            /\(.*Mac OS \d.*\)/ && do {
-              /\(.*Mac OS 9.*\)/ && do {push @os, ("Mac System 9.x", "Mac System 9.0");};
-              /\(.*Mac OS 8\.6.*\)/ && do {push @os, ("Mac System 8.6", "Mac System 8.5");};
-              /\(.*Mac OS 8\.5.*\)/ && do {push @os, "Mac System 8.5";};
-              /\(.*Mac OS 8\.1.*\)/ && do {push @os, ("Mac System 8.1", "Mac System 8.0");};
-              /\(.*Mac OS 8\.0.*\)/ && do {push @os, "Mac System 8.0";};
-              /\(.*Mac OS 8[^.].*\)/ && do {push @os, "Mac System 8.0";};
-              /\(.*Mac OS 8.*\)/ && do {push @os, "Mac System 8.6";};
-            };
-            /\(.*Darwin.*\)/ && do {push @os, ("Mac OS X 10.0", "Mac OS X");};
-        # Silly
-            /\(.*Mac.*\)/ && do {
-              /\(.*Mac.*PowerPC.*\)/ && do {push @os, "Mac System 9.x";};
-              /\(.*Mac.*PPC.*\)/ && do {push @os, "Mac System 9.x";};
-              /\(.*Mac.*68k.*\)/ && do {push @os, "Mac System 8.0";};
-            };
-        # Evil
-            /Amiga/i && do {push @os, "Other";};
-            /WinMosaic/ && do {push @os, "Windows 95";};
-            /\(.*PowerPC.*\)/ && do {push @os, "Mac System 9.x";};
-            /\(.*PPC.*\)/ && do {push @os, "Mac System 9.x";};
-            /\(.*68K.*\)/ && do {push @os, "Mac System 8.0";};
-        }
-    }
-
-    push(@os, "Windows") if grep(/^Windows /, @os);
-    push(@os, "Mac OS") if grep(/^Mac /, @os);
-
-    return pick_valid_field_value('op_sys', @os) || "Other";
-}
 ##############################################################################
 # End of subroutines
 ##############################################################################
@@ -469,8 +299,8 @@ else {
     $default{'component_'}    = formvalue('component');
     $default{'priority'}      = formvalue('priority', Bugzilla->params->{'defaultpriority'});
     $default{'bug_severity'}  = formvalue('bug_severity', Bugzilla->params->{'defaultseverity'});
-    $default{'rep_platform'}  = pickplatform();
-    $default{'op_sys'}        = pickos();
+    $default{'rep_platform'}  = detect_platform();
+    $default{'op_sys'}        = detect_op_sys();
 
     $vars->{'alias'}          = formvalue('alias');
     $vars->{'short_desc'}     = formvalue('short_desc');
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
index 79edaad3e..c800ade3d 100644
--- a/extensions/BMO/Extension.pm
+++ b/extensions/BMO/Extension.pm
@@ -42,6 +42,7 @@ use DateTime;
 use Bugzilla::Extension::BMO::FakeBug;
 use Bugzilla::Extension::BMO::Data qw($cf_visible_in_products
                                       $cf_flags
+                                      $cf_disabled_flags
                                       %group_to_cc_map
                                       $blocking_trusted_setters
                                       $blocking_trusted_requesters
@@ -51,7 +52,8 @@ use Bugzilla::Extension::BMO::Data qw($cf_visible_in_products
                                       %always_fileable_group
                                       %product_sec_groups);
 use Bugzilla::Extension::BMO::Reports qw(user_activity_report
-                                         triage_reports);
+                                         triage_reports
+                                         group_admins);
 
 our $VERSION = '0.1';
 
@@ -69,6 +71,7 @@ sub template_before_process {
     my $vars = $args->{'vars'};
     
     $vars->{'cf_hidden_in_product'} = \&cf_hidden_in_product;
+    $vars->{'cf_flag_disabled'} = \&cf_flag_disabled;
     
     if ($file =~ /^list\/list/) {
         # Purpose: enable correct sorting of list table
@@ -155,8 +158,8 @@ sub page_before_template {
         # that our hook template can see. 
         Bugzilla->request_cache->{'bmo_fields_page'} = 1;
     }
-    elsif ($page eq 'remo-form-payment.html') {
-        _remo_form_payment($vars);
+    elsif ($page eq 'group_admins.html') {
+        group_admins($vars);
     }
 }
 
@@ -242,6 +245,13 @@ sub cf_hidden_in_product {
     return 0;
 }
 
+sub cf_flag_disabled {
+    my ($field_name, $bug) = @_;
+    return 0 unless grep { $field_name eq $_ } @$cf_disabled_flags;
+    my $value = $bug->{$field_name};
+    return $value eq '---' || $value eq '';
+}
+
 # Purpose: CC certain email addresses on bugmail when a bug is added or 
 # removed from a particular group.
 sub bugmail_recipients {
@@ -440,6 +450,19 @@ sub _link_hg {
     return qq{$text};
 }
 
+sub _link_bzr {
+    my $args = shift;
+    my $preamble = html_quote($args->{matches}->[0]);
+    my $url = html_quote($args->{matches}->[1]);
+    my $text = html_quote($args->{matches}->[2]);
+    my $id = html_quote($args->{matches}->[3]);
+
+    $url =~ s/\s+$//;
+    $url =~ s/\/$//;
+
+    return qq{$preamble$text};
+}
+
 sub bug_format_comment {
     my ($self, $args) = @_;
     my $regexes = $args->{'regexes'};
@@ -466,6 +489,13 @@ sub bug_format_comment {
         replace => \&_link_svn
     });
 
+    push (@$regexes, {
+        match => qr/\b(Committing\sto:\sbzr\+ssh:\/\/
+                    (?:[^\@]+\@)?(bzr\.mozilla\.org[^\n]+)\n.*?\nCommitted\s)
+                    (revision\s(\d+))\./sx,
+        replace => \&_link_bzr
+    });
+
     # Note: for grouping in this regexp, always use non-capturing parentheses.
     my $hgrepos = join('|', qw!(?:releases/)?comm-[\w.]+ 
                                (?:releases/)?mozilla-[\w.]+
@@ -597,146 +627,6 @@ sub install_update_db {
     }
 }
 
-sub _remo_form_payment {
-    my ($vars) = @_;
-    my $input = Bugzilla->input_params;
-
-    my $user = Bugzilla->login(LOGIN_REQUIRED);
-
-    if ($input->{'action'} eq 'commit') {
-        my $template = Bugzilla->template;
-        my $cgi      = Bugzilla->cgi;
-        my $dbh      = Bugzilla->dbh;
-
-        my $bug_id = $input->{'bug_id'};
-        detaint_natural($bug_id);
-        my $bug = Bugzilla::Bug->check($bug_id);
-
-        # Detect if the user already used the same form to submit again
-        my $token = trim($input->{'token'});
-        if ($token) {
-            my ($creator_id, $date, $old_attach_id) = Bugzilla::Token::GetTokenData($token);
-            if (!$creator_id 
-                || $creator_id != $user->id 
-                || $old_attach_id !~ "^remo_form_payment:")
-            {
-                # The token is invalid.
-                ThrowUserError('token_does_not_exist');
-            }
-
-            $old_attach_id =~ s/^remo_form_payment://;
-            if ($old_attach_id) {
-                ThrowUserError('remo_payment_cancel_dupe', 
-                               { bugid => $bug_id, attachid => $old_attach_id });
-            }
-        }
-
-        # Make sure the user can attach to this bug
-        if (!$bug->user->{'canedit'}) {
-            ThrowUserError("remo_payment_bug_edit_denied", 
-                           { bug_id => $bug->id });
-        }
-
-        # Make sure the bug is under the correct product/component
-        if ($bug->product ne 'Mozilla Reps' 
-            || $bug->component ne 'Budget Requests') 
-        {
-            ThrowUserError('remo_payment_invalid_product');    
-        }
-
-        my ($timestamp) = $dbh->selectrow_array("SELECT NOW()");
-
-        $dbh->bz_start_transaction;
-    
-        # Create the comment to be added based on the form fields from rep-payment-form
-        my $comment;
-        $template->process("pages/comment-remo-form-payment.txt.tmpl", $vars, \$comment)
-            || ThrowTemplateError($template->error());
-        $bug->add_comment($comment, { isprivate => 0 });
-
-        # Attach expense report
-        # FIXME: Would be nice to be able to have the above prefilled comment and
-        # the following attachments all show up under a single comment. But the longdescs
-        # table can only handle one attach_id per comment currently. At least only one
-        # email is sent the way it is done below.
-        my $attachment;
-        if (defined $cgi->upload('expenseform')) {
-            # Determine content-type
-            my $content_type = $cgi->uploadInfo($cgi->param('expenseform'))->{'Content-Type'};
- 
-            $attachment = Bugzilla::Attachment->create(
-                { bug           => $bug, 
-                  creation_ts   => $timestamp, 
-                  data          => $cgi->upload('expenseform'), 
-                  description   => 'Expense Form', 
-                  filename      => scalar $cgi->upload('expenseform'), 
-                  ispatch       => 0, 
-                  isprivate     => 0, 
-                  isurl         => 0, 
-                  mimetype      => $content_type, 
-                  store_in_file => 0, 
-            });
-
-            # Insert comment for attachment
-            $bug->add_comment('', { isprivate  => 0, 
-                                    type       => CMT_ATTACHMENT_CREATED, 
-                                    extra_data => $attachment->id });
-        }
-
-        # Attach receipts file
-        if (defined $cgi->upload("receipts")) {
-            # Determine content-type
-            my $content_type = $cgi->uploadInfo($cgi->param("receipts"))->{'Content-Type'};
-
-            $attachment = Bugzilla::Attachment->create(
-                { bug           => $bug, 
-                  creation_ts   => $timestamp, 
-                  data          => $cgi->upload('receipts'), 
-                  description   => "Receipts", 
-                  filename      => scalar $cgi->upload("receipts"), 
-                  ispatch       => 0, 
-                  isprivate     => 0, 
-                  isurl         => 0, 
-                  mimetype      => $content_type, 
-                  store_in_file => 0, 
-            });
-
-            # Insert comment for attachment
-            $bug->add_comment('', { isprivate  => 0, 
-                                    type       => CMT_ATTACHMENT_CREATED, 
-                                    extra_data => $attachment->id });
-        }
-
-        $bug->update($timestamp);
-
-        if ($token) {
-            trick_taint($token);
-            $dbh->do('UPDATE tokens SET eventdata = ? WHERE token = ?', undef,
-                     ("remo_form_payment:" . $attachment->id, $token));
-        }
-
-        $dbh->bz_commit_transaction;
-    
-        # Define the variables and functions that will be passed to the UI template.
-        $vars->{'attachment'} = $attachment;
-        $vars->{'bugs'} = [ new Bugzilla::Bug($bug_id) ];
-        $vars->{'header_done'} = 1;
-        $vars->{'contenttypemethod'} = 'autodetect';
- 
-        my $recipients = { 'changer' => $user };
-        $vars->{'sent_bugmail'} = Bugzilla::BugMail::Send($bug_id, $recipients);
-        
-        print $cgi->header();
-        # Generate and return the UI (HTML page) from the appropriate template.
-        $template->process("attachment/created.html.tmpl", $vars)
-            || ThrowTemplateError($template->error()); 
-        exit;
-    }
-    else {
-        $vars->{'token'} = issue_session_token('remo_form_payment:');
-    }
-}
-
 sub _last_closed_date {
     my ($self) = @_;
     my $dbh = Bugzilla->dbh;
@@ -796,4 +686,61 @@ sub webservice {
     $dispatch->{BMO} = "Bugzilla::Extension::BMO::WebService";
 }
 
+our $search_content_matches;
+BEGIN {
+    $search_content_matches = \&Bugzilla::Search::_content_matches;
+}
+
+sub search_operator_field_override {
+    my ($self, $args) = @_;
+    my $search = $args->{'search'};
+    my $operators = $args->{'operators'};
+
+    my $cgi = Bugzilla->cgi;
+    my @comments = $cgi->param('comments');
+    my $exclude_comments = scalar(@comments) && !grep { $_ eq '1' } @comments;
+
+    if ($cgi->param('query_format') eq 'specific' && $exclude_comments) {
+        # use the non-comment operator
+        $operators->{'content'}->{matches} = \&_short_desc_matches;
+        $operators->{'content'}->{notmatches} = \&_short_desc_matches;
+
+    } else {
+        # restore default content operator
+        $operators->{'content'}->{matches} = $search_content_matches;
+        $operators->{'content'}->{notmatches} = $search_content_matches;
+    }
+}
+
+sub _short_desc_matches {
+    # copy of Bugzilla::Search::_content_matches
+
+    my $self = shift;
+    my %func_args = @_;
+    my ($chartid, $supptables, $term, $groupby, $fields, $t, $v) =
+        @func_args{qw(chartid supptables term groupby fields t v)};
+    my $dbh = Bugzilla->dbh;
+
+    # Add the fulltext table to the query so we can search on it.
+    my $table = "bugs_fulltext_$$chartid";
+    push(@$supptables, "LEFT JOIN bugs_fulltext AS $table " .
+                       "ON bugs.bug_id = $table.bug_id");
+
+    # Create search terms to add to the SELECT and WHERE clauses.
+    my ($term1, $rterm1) = $dbh->sql_fulltext_search("$table.short_desc", $$v, 1);
+    $rterm1 = $term1 if !$rterm1;
+
+    # The term to use in the WHERE clause.
+    $$term = $term1;
+    if ($$t =~ /not/i) {
+        $$term = "NOT($$term)";
+    }
+
+    my $current = Bugzilla::Search::COLUMNS->{'relevance'}->{name};
+    $current = $current ? "$current + " : '';
+    # For NOT searches, we just add 0 to the relevance.
+    my $select_term = $$t =~ /not/ ? 0 : "($current$rterm1)";
+    Bugzilla::Search::COLUMNS->{'relevance'}->{name} = $select_term;
+}
+
 __PACKAGE__->NAME;
diff --git a/extensions/BMO/lib/Data.pm b/extensions/BMO/lib/Data.pm
index 17b84a37e..ccc729a6d 100644
--- a/extensions/BMO/lib/Data.pm
+++ b/extensions/BMO/lib/Data.pm
@@ -27,7 +27,7 @@ use base qw(Exporter);
 use Tie::IxHash;
 
 our @EXPORT_OK = qw($cf_visible_in_products
-                    $cf_flags
+                    $cf_flags $cf_disabled_flags
                     %group_to_cc_map
                     $blocking_trusted_setters
                     $blocking_trusted_requesters
@@ -78,7 +78,6 @@ tie(%$cf_visible_in_products, "Tie::IxHash",
         "Add-on SDK"            => [],
         "addons.mozilla.org"    => [],
         "AUS"                   => [],
-        "Camino"                => [],
         "Core Graveyard"        => [],
         "Core"                  => [],
         "Directory"             => [],
@@ -108,6 +107,9 @@ tie(%$cf_visible_in_products, "Tie::IxHash",
             "Server Operations: Security",
         ],
     },
+    qw/^cf_office$/ => {
+        "mozilla.org"           => ["Server Operations: Desktop Issues"],
+    },
     qr/^cf_crash_signature$/ => {
         "addons.mozilla.org"    => [], 
         "Add-on SDK"            => [], 
@@ -136,6 +138,9 @@ tie(%$cf_visible_in_products, "Tie::IxHash",
         "Mozilla Labs"          => [],
         "mozilla.org"           => [], 
         "Tech Evangelism"       => [],  
+    },
+    qw/^cf_due_date$/ => {
+        "Mozilla Reps" => [],
     }, 
 );
 
@@ -144,6 +149,28 @@ our $cf_flags = [
     qr/^cf_(?:blocking|tracking|status)_/,
 ];
 
+# List of disabled fields.
+# Temp kludge until custom fields can be disabled correctly upstream.
+# Disabled fields are hidden unless they have a value set
+our $cf_disabled_flags = [
+    'cf_blocking_20',
+    'cf_status_20',
+    'cf_tracking_firefox5',
+    'cf_status_firefox5',
+    'cf_blocking_thunderbird32',
+    'cf_status_thunderbird32',
+    'cf_blocking_thunderbird30',
+    'cf_status_thunderbird30',
+    'cf_blocking_seamonkey21',
+    'cf_status_seamonkey21',
+    'cf_tracking_seamonkey22',
+    'cf_status_seamonkey22',
+    'cf_tracking_firefox6',
+    'cf_status_firefox6',
+    'cf_tracking_thunderbird6',
+    'cf_status_thunderbird6',
+];
+
 # Who to CC on particular bugmails when certain groups are added or removed.
 our %group_to_cc_map = (
   'bugzilla-security'        => 'security@bugzilla.org',
diff --git a/extensions/BMO/lib/FakeBug.pm b/extensions/BMO/lib/FakeBug.pm
index d8cebe379..5610f5433 100644
--- a/extensions/BMO/lib/FakeBug.pm
+++ b/extensions/BMO/lib/FakeBug.pm
@@ -1,7 +1,5 @@
 package Bugzilla::Extension::BMO::FakeBug;
 
-use strict;
-
 # hack to allow the bug entry templates to use check_can_change_field to see if
 # various field values should be available to the current user
 
diff --git a/extensions/BMO/lib/Reports.pm b/extensions/BMO/lib/Reports.pm
index d1f979beb..f291e72e7 100644
--- a/extensions/BMO/lib/Reports.pm
+++ b/extensions/BMO/lib/Reports.pm
@@ -31,7 +31,8 @@ use DateTime;
 use base qw(Exporter);
 
 our @EXPORT_OK = qw(user_activity_report
-                    triage_reports);
+                    triage_reports
+                    group_admins);
 
 sub user_activity_report {
     my ($vars) = @_;
@@ -303,14 +304,16 @@ sub triage_reports {
 
         # load product and components from input
 
-        my $product = Bugzilla::Product->new({ name => $input->{'product'} });
+        my $product = Bugzilla::Product->new({ name => $input->{'product'} })
+            || ThrowUserError('invalid_object', { object => 'Product', value => $input->{'product'} });
 
         my @component_ids;
         if ($input->{'component'} ne '') {
             my $ra_components = ref($input->{'component'})
                 ? $input->{'component'} : [ $input->{'component'} ];
             foreach my $component_name (@$ra_components) {
-                my $component = Bugzilla::Component->new({ name => $component_name, product => $product });
+                my $component = Bugzilla::Component->new({ name => $component_name, product => $product })
+                    || ThrowUserError('invalid_object', { object => 'Component', value => $component_name });
                 push @component_ids, $component->id;
             }
         }
@@ -319,15 +322,22 @@ sub triage_reports {
 
         my $filter_commenter = $input->{'filter_commenter'};
         my $filter_commenter_on = $input->{'commenter'};
+        my $filter_last = $input->{'filter_last'};
+        my $filter_last_period = $input->{'last'};
+
+        if (!$filter_commenter || $filter_last) {
+            $filter_commenter = '1';
+            $filter_commenter_on = 'reporter';
+        }
+
         my $filter_commenter_id;
         if ($filter_commenter && $filter_commenter_on eq 'is') {
             Bugzilla::User::match_field({ 'commenter_is' => {'type' => 'single'} });
-            my $user = Bugzilla::User->new({ name => $input->{'commenter_is'} });
+            my $user = Bugzilla::User->new({ name => $input->{'commenter_is'} })
+                || ThrowUserError('invalid_object', { object => 'User', value => $input->{'commenter_is'} });
             $filter_commenter_id = $user ? $user->id : 0;
         }
 
-        my $filter_last = $input->{'filter_last'};
-        my $filter_last_period = $input->{'last'};
         my $filter_last_time;
         if ($filter_last) {
             if ($filter_last_period eq 'is') {
@@ -338,11 +348,10 @@ sub triage_reports {
                     $filter_last_period = 14 if $filter_last_period < 14;
             }
         }
-        my $now = (time);
-        $filter_commenter = 1 unless $filter_commenter || $filter_last;
 
         # form sql queries
 
+        my $now = (time);
         my $bugs_sql = "
               SELECT bug_id, short_desc, reporter, creation_ts
                 FROM bugs
@@ -473,4 +482,41 @@ sub triage_reports {
     $vars->{'input'} = $input;
 }
 
+sub group_admins {
+    my ($vars, $filter) = @_;
+    my $dbh = Bugzilla->dbh;
+    my $user = Bugzilla->user;
+
+    $user->in_group('editusers')
+        || ThrowUserError('auth_failure', { group  => 'editusers', 
+                                            action => 'run', 
+                                            object => 'group_admins' });
+
+    my $query = "
+        SELECT groups.name, " .
+               $dbh->sql_group_concat('profiles.login_name', "','", 1) . "
+          FROM groups
+               LEFT JOIN user_group_map
+                    ON user_group_map.group_id = groups.id
+                    AND user_group_map.isbless = 1
+                    AND user_group_map.grant_type = 0
+               LEFT JOIN profiles
+                    ON user_group_map.user_id = profiles.userid
+         WHERE groups.isbuggroup = 1
+      GROUP BY groups.name";
+    
+    my @groups;
+    foreach my $group (@{ $dbh->selectall_arrayref($query) }) {
+        my @admins;
+        if ($group->[1]) {
+            foreach my $admin (split(/,/, $group->[1])) {
+                push(@admins, Bugzilla::User->new({ name => $admin }));
+            }
+        }
+        push(@groups, { name => $group->[0], admins => \@admins });
+    }
+
+    $vars->{'groups'} = \@groups;
+}
+
 1;
diff --git a/extensions/BMO/template/en/default/account/create.html.tmpl b/extensions/BMO/template/en/default/account/create.html.tmpl
index 275df01f8..47355cf00 100644
--- a/extensions/BMO/template/en/default/account/create.html.tmpl
+++ b/extensions/BMO/template/en/default/account/create.html.tmpl
@@ -122,17 +122,17 @@ function onSubmit() {
   
  1. Please consider reading our - [% terms.bug %] writing guidelines. + bug writing guidelines.
  2. - [% terms.Bugzilla %] is a public place, so what you type and your email address will be visible + Bugzilla is a public place, so what you type and your email address will be visible to all logged-in users. Some people use an alternative email address for this reason.
  3. Please give us an email address you want to use. Once we confirm that it works, - you'll be asked to set a password and then you can start filing [% terms.bugs %] and helping fix them. + you'll be asked to set a password and then you can start filing bugs and helping fix them.
@@ -158,9 +158,9 @@ function onSubmit() {

- If you think there's something wrong with [% terms.Bugzilla %], you can + If you think there's something wrong with Bugzilla, you can send an email to the admins, but - remember, they can't file [% terms.bugs %] for you, or solve tech support problems. + remember, they can't file bugs for you, or solve tech support problems.

[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-mozreps.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mozreps.txt.tmpl deleted file mode 100644 index 6c9d7c6b7..000000000 --- a/extensions/BMO/template/en/default/bug/create/comment-mozreps.txt.tmpl +++ /dev/null @@ -1,81 +0,0 @@ -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the BMO Bugzilla Extension. - # - # The Initial Developer of the Original Code is the Mozilla Foundation - # Portions created by the Initial Developers are Copyright (C) 2011 the - # Initial Developer. All Rights Reserved. - # - # Contributor(s): Byron Jones - #%] -[% USE Bugzilla %] -[% cgi = Bugzilla.cgi %] -First Name: -[%+ cgi.param('first_name') %] - -Last Name: -[%+ cgi.param('last_name') %] - -Under 18 years old: -[%+ IF cgi.param('underage') %]Yes[% ELSE %]No[% END %] - -Sex: -[%+ cgi.param('sex') %] - -City: -[%+ cgi.param('city') %] - -Country: -[%+ cgi.param('country') %] - -Local Community: -[% IF cgi.param('community') %] -[%+ cgi.param('community') %] -[% ELSE %] -- -[% END %] - -IM: -[% IF cgi.param('im') %] -[%+ cgi.param('im') %] -[% ELSE %] -- -[% END %] - -References: -[% IF cgi.param('references') %] -[%+ cgi.param('references') %] -[% ELSE %] -- -[% END %] - -Currently Involved with Mozilla: -[% IF cgi.param('involved') %] -[%+ cgi.param('involved') %] -[% ELSE %] -- -[% END %] - -Languages Spoken: -[%+ cgi.param('languages') %] - -How did you lean about Mozilla Reps: -[%+ cgi.param('learn') %] - -What motivates you most about joining Mozilla Reps: -[%+ cgi.param('motivation') %] - -Comments: -[% IF cgi.param('comments') %] -[%+ cgi.param('comments') %] -[% ELSE %] -- -[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl deleted file mode 100644 index 9486c56fe..000000000 --- a/extensions/BMO/template/en/default/bug/create/comment-remo-budget.txt.tmpl +++ /dev/null @@ -1,64 +0,0 @@ -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the Bugzilla Bug Tracking System. - # - # The Initial Developer of the Original Code is Netscape Communications - # Corporation. Portions created by Netscape are - # Copyright (C) 1998 Netscape Communications Corporation. All - # Rights Reserved. - # - # Contributor(s): Gervase Markham - #%] -[%# INTERFACE: - # This template has no interface. - # - # Form variables from a bug submission (i.e. the fields on a template from - # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to - # pull out various custom fields and format an initial Description entry - # from them. - #%] -[% USE Bugzilla %] -[% cgi = Bugzilla.cgi %] - -Requester info: - -Requester: [% cgi.param('firstname') %] [%+ cgi.param('lastname') %] -Wiki user profile: [% cgi.param('wikiprofile') %] -Event wiki page: [% cgi.param('wikipage') %] -Advance payment needed: [% IF cgi.param('advancepayment') %]Yes[% ELSE %]No[% END %] - -Budget breakdown: - -Total amount requested in $USD: [% cgi.param('budgettotal') %] -Costs per service: -Service 1: [% cgi.param('service1') %] Cost: [% cgi.param('cost1') %] -Service 2: [% cgi.param('service2') %] Cost: [% cgi.param('cost2') %] -Service 3: [% cgi.param('service3') %] Cost: [% cgi.param('cost3') %] -Service 4: [% cgi.param('service4') %] Cost: [% cgi.param('cost4') %] -Service 5: [% cgi.param('service5') %] Cost: [% cgi.param('cost5') %] - -Additional costs: (add comment box) -[% cgi.param('costadditional') %] - -Success measurement: - -How will the event help push the Mozilla project forward? -[%+ cgi.param('successmeasure') %] - -Metric 1: [% cgi.param('metric1') %] Success scenario: [% cgi.param('success1') %] -Metric 2: [% cgi.param('metric2') %] Success scenario: [% cgi.param('success2') %] -Metric 3: [% cgi.param('metric3') %] Success scenario: [% cgi.param('success3') %] - -Additional information: -[%+ cgi.param('successadditional') %] - -[%+ cgi.param("comment") IF cgi.param("comment") %] - diff --git a/extensions/BMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl deleted file mode 100644 index 0b98178b2..000000000 --- a/extensions/BMO/template/en/default/bug/create/comment-remo-swag.txt.tmpl +++ /dev/null @@ -1,68 +0,0 @@ -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the Bugzilla Bug Tracking System. - # - # The Initial Developer of the Original Code is Netscape Communications - # Corporation. Portions created by Netscape are - # Copyright (C) 1998 Netscape Communications Corporation. All - # Rights Reserved. - # - # Contributor(s): Gervase Markham - #%] -[%# INTERFACE: - # This template has no interface. - # - # Form variables from a bug submission (i.e. the fields on a template from - # enter_bug.cgi) can be access via Bugzilla.cgi.param. It can be used to - # pull out various custom fields and format an initial Description entry - # from them. - #%] -[% USE Bugzilla %] -[% cgi = Bugzilla.cgi %] - -Requester info: - -Requester name: [% cgi.param('firstname') %][% " " %][% cgi.param('lastname') %] -Wiki user profile: [% cgi.param('wikiprofile') %] -Event wiki page: [% cgi.param('wikipage') %] -Estimated Attendance: [% cgi.param('attendance') %] - -Shipping details: - -Ship swag before: [% cgi.param('shipdate') %] - -[%+ cgi.param("shiptofirstname") +%] [%+ cgi.param("shiptolastname") +%] -[%+ cgi.param("shiptoaddress") +%] -[%+ cgi.param("shiptoaddress2") +%] -[%+ cgi.param("shiptocity") +%] [%+ cgi.param("shiptostate") +%] [%+ cgi.param("shiptopcode") +%] -[%+ cgi.param("shiptocountry") %] - -Phone: [% cgi.param("shiptophone") %] -[%+ IF cgi.param("shiptoidrut") %]Personal ID/RUT: [% cgi.param("shiptoidrut") %][% END %] - -Addition information for delivery person: -[%+ cgi.param('shipadditional') %] - -Swag requested: - -Stickers: [% IF cgi.param('stickers') %]Yes[% ELSE %]No[% END %] -Buttons: [% IF cgi.param('buttons') %]Yes[% ELSE %]No[% END %] -Posters: [% IF cgi.param('posters') %]Yes[% ELSE %]No[% END %] -Lanyards: [% IF cgi.param('lanyards') %]Yes[% ELSE %]No[% END %] -T-shirts: [% IF cgi.param('tshirts') %]Yes[% ELSE %]No[% END %] -Roll-up banners: [% IF cgi.param('rollupbanners') %]Yes[% ELSE %]No[% END %] -Horizontal banners: [% IF cgi.param('horizontalbanners') %]Yes[% ELSE %]No[% END %] -Booth cloth: [% IF cgi.param('boothcloth') %]Yes[% ELSE %]No[% END %] -Pens: [% IF cgi.param('pens') %]Yes[% ELSE %]No[% END %] -Other: [% IF cgi.param('otherswag') %][% cgi.param('otherswag') %][% ELSE %]No[% END %] - -[%+ cgi.param("comment") IF cgi.param("comment") %] - diff --git a/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl index 72d520dd4..e4c6cabfb 100644 --- a/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl @@ -80,17 +80,16 @@ function trySubmit() {
- - - - - - - - - - - + + + + + + + + + + @@ -98,6 +97,7 @@ function trySubmit() { + @@ -146,7 +146,7 @@ function trySubmit() { - + @@ -171,14 +171,14 @@ function trySubmit() { - - + + - - + + @@ -198,11 +198,12 @@ function trySubmit() { -
Archive this?Archive this?
Need IT to help run A/V?Need IT to help run A/V?
: Please briefly describe the brownbag and any specific needs you might have.
+
+
diff --git a/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl index d2f30475d..08207fd8c 100644 --- a/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl @@ -32,7 +32,7 @@ [% USE Bugzilla %]

Please use this form for IT requests only!

-

If you have a [% terms.bug %] to file, go here.

+

If you have a bug to file, go here.

@@ -75,12 +75,12 @@ @@ -96,13 +96,16 @@
-
- +
+
- -
+ +
+ +

+ Mailing list requests should be filed here instead. @@ -169,7 +172,7 @@
- +
(please uncheck this box if it isn't)

diff --git a/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl index 92354eac3..d6b6c188f 100644 --- a/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl @@ -91,18 +91,19 @@ function validateAndSubmit() { - - - - - - - - - - - + + + + + + + + + + + + @@ -287,7 +287,7 @@
First Name: * diff --git a/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl index 0a2edb5ee..138f1754b 100644 --- a/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl @@ -88,21 +88,21 @@ var listName = document.getElementById('listName').value; var listAdmin = document.getElementById('listAdmin').value; var listTypeRadio = document.getElementsByName('listType'); - var listType = ""; + var listType = ""; - for (var i = 0; i < listTypeRadio.length; i++) { - if (listTypeRadio[i].checked) { - listType = listTypeRadio[i].value; - } - } + for (var i = 0; i < listTypeRadio.length; i++) { + if (listTypeRadio[i].checked) { + listType = listTypeRadio[i].value; + } + } var alert_text = ""; var short_desc = ""; - if (listType) { + if (listType) { if (listType == "lists.mozilla.org") { document.getElementById('component').value = "Discussion Forums"; - short_desc = "Discussion Forum: " + listName; + short_desc = "Discussion Forum: " + listName; } else if (listType == "mozilla.com" ) { document.getElementById('component').value = "Server Operations: Desktop Issues"; short_desc = "[Zimbra Distribution List Request] " + listName + "@" + listType; @@ -112,7 +112,7 @@ } } else { alert_text += "Please select a list type\n"; - } + } if (!isFilledOut('listName')) { alert_text += "Please enter the list name\n"; @@ -127,7 +127,7 @@ return false; } - document.getElementById('short_desc').value = short_desc; + document.getElementById('short_desc').value = short_desc; return true; } @@ -220,8 +220,8 @@
Note:The list administrator is also initially considered to be the list moderator and will be responsible for moderation tasks unless delegated to someone else. For - convenience, [% terms.Bugzilla %] user accounts will autocomplete. The administrator is not required - to have a [% terms.Bugzilla %] account, and you can enter an address that doesn't autocomplete if + convenience, Bugzilla user accounts will autocomplete. The administrator is not required + to have a Bugzilla account, and you can enter an address that doesn't autocomplete if necessary.
- - - + + + @@ -335,18 +333,17 @@ TUI_hide_default('expert_fields'); %] - [% IF product.flag_types.bug.size > 0 %] + [% IF product.flag_types(is_active=>1).bug.size > 0 %] [% display_flag_headers = 0 %] [% any_flags_requesteeble = 0 %] - [% FOREACH flag_type = product.flag_types.bug %] - [% NEXT UNLESS flag_type.is_active %] + [% FOREACH flag_type = product.flag_types(is_active=>1).bug %] [% display_flag_headers = 1 %] [% SET any_flags_requesteeble = 1 IF flag_type.is_requestable && flag_type.is_requesteeble %] [% END %] [% IF display_flag_headers %] - [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types.bug + [% PROCESS "flag/list.html.tmpl" flag_types = product.flag_types(is_active=>1).bug any_flags_requesteeble = any_flags_requesteeble flag_table_id = "bug_flags" %] @@ -469,7 +466,7 @@ TUI_hide_default('expert_fields'); [% defaultcontent = BLOCK %] [% IF cloned_bug_id %] -+++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id FILTER html %] +++ ++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id %] +++ [% END %] @@ -526,7 +523,7 @@ TUI_hide_default('expert_fields'); Add an attachment [% PROCESS attachment/createformcontents.html.tmpl - flag_types = product.flag_types.attachment + flag_types = product.flag_types(is_active=>1).attachment any_flags_requesteeble = 1 flag_table_id ="attachment_flags" %]
@@ -555,7 +552,7 @@ TUI_hide_default('expert_fields'); Status Whiteboard: + value="[% status_whiteboard %]"> @@ -592,10 +589,10 @@ TUI_hide_default('expert_fields'); [% FOREACH g = group %]      - -
+
[% END %] diff --git a/extensions/BMO/template/en/default/bug/create/create-mozreps.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozreps.html.tmpl deleted file mode 100644 index 914e1f54d..000000000 --- a/extensions/BMO/template/en/default/bug/create/create-mozreps.html.tmpl +++ /dev/null @@ -1,204 +0,0 @@ -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the BMO Bugzilla Extension. - # - # The Initial Developer of the Original Code is the Mozilla Foundation - # Portions created by the Initial Developers are Copyright (C) 2011 the - # Initial Developer. All Rights Reserved. - # - # Contributor(s): Byron Jones - #%] - -[% PROCESS global/variables.none.tmpl %] - -[% PROCESS global/header.html.tmpl - title = "Mozilla Reps - Application Form" - style_urls = [ "extensions/BMO/web/styles/moz_reps.css" ] -%] - -[% USE Bugzilla %] -[% mandatory = '*' %] - - - - - -

Mozilla Reps - Application Form

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
First Name:[% mandatory FILTER html %]
Last Name:[% mandatory FILTER html %]
Are you under 18 years old?:
Sex:[% mandatory FILTER html %] - -
City:[% mandatory FILTER html %]
Country:[% mandatory FILTER html %]
Local Community you participate in:
IM (specify service):
- References: -
- -
- How are you involved with Mozilla? -
- -
Languages Spoken:[% mandatory FILTER html %]
How did you learn about Mozilla Reps?[% mandatory FILTER html %]
What motivates you most about joining Mozilla Reps?[% mandatory FILTER html %]
Comments:
- I have read the - Mozilla Privacy Policy:[% mandatory FILTER html %] -
 
- - - -[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl index 584b14912..cdbce5c8c 100644 --- a/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl @@ -86,7 +86,7 @@ function trySubmit() { - + @@ -142,7 +142,7 @@ function trySubmit() { - + diff --git a/extensions/BMO/template/en/default/bug/create/create-remo-budget.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-remo-budget.html.tmpl deleted file mode 100644 index 0aa18e41d..000000000 --- a/extensions/BMO/template/en/default/bug/create/create-remo-budget.html.tmpl +++ /dev/null @@ -1,248 +0,0 @@ -[%# 1.0@bugzilla.org %] -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the Bugzilla Bug Tracking System. - # - # The Initial Developer of the Original Code is Mozilla Corporation. - # Portions created by Mozilla are Copyright (C) 2008 Mozilla - # Corporation. All Rights Reserved. - # - # Contributor(s): Reed Loden - # David Tran - #%] - -[% PROCESS global/variables.none.tmpl %] - -[% PROCESS global/header.html.tmpl - title = "Mozilla Reps Budget Request Form" - style_urls = [ 'extensions/BMO/web/styles/moz_reps.css' ] - javascript_urls = [ 'extensions/BMO/web/js/form_validate.js', - 'js/util.js', - 'js/field.js' ] -%] - -

These requests will only be visible to the person who submitted the request, -any persons designated in the CC line, and authorized members of the Mozilla -Rep team.

- - - -

Mozilla Reps - Budget Request Form

- -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
First Name: * - -
Last Name: * - -
Wiki user profile:* - -
Event wiki page: * - -
  
- Is advance payment needed? - - -
  
- Budget breakdown:
- Total amount requested in $USD: * -
- Costs per service: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Service 1: *Cost 1: *
Service 2:Cost 2:
Service 3:Cost 3:
Service 4:Cost 4:
Service 5:Cost 5:
- Additional costs:
- -
  
- Success measurement:
- How will the event help push the Mozilla project forward? - *
- - - - - - - - - - - - - - -
Metric 1: * - Success scenario: * -
Metric 2: - Success scenario: -
Metric 3: - Success scenario: -
- Additional information:
- -
  - -
- - - -

- * - Required field
- Thanks for contacting us. -

- -[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-remo-swag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-remo-swag.html.tmpl deleted file mode 100644 index 0b15240fd..000000000 --- a/extensions/BMO/template/en/default/bug/create/create-remo-swag.html.tmpl +++ /dev/null @@ -1,292 +0,0 @@ -[%# 1.0@bugzilla.org %] -[%# The contents of this file are subject to the Mozilla Public - # License Version 1.1 (the "License"); you may not use this file - # except in compliance with the License. You may obtain a copy of - # the License at http://www.mozilla.org/MPL/ - # - # Software distributed under the License is distributed on an "AS - # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - # implied. See the License for the specific language governing - # rights and limitations under the License. - # - # The Original Code is the Bugzilla Bug Tracking System. - # - # The Initial Developer of the Original Code is Mozilla Corporation. - # Portions created by Mozilla are Copyright (C) 2008 Mozilla - # Corporation. All Rights Reserved. - # - # Contributor(s): Reed Loden - # David Tran - #%] - -[% PROCESS global/variables.none.tmpl %] - -[% PROCESS global/header.html.tmpl - title = "Mozilla Reps Swag Request Form" - javascript_urls = [ 'extensions/BMO/web/js/swag.js', - 'extensions/BMO/web/js/form_validate.js', - 'js/field.js', - 'js/util.js' ] - style_urls = [ "extensions/BMO/web/styles/moz_reps.css", - "skins/custom/calendar.css" ] - yui = [ 'calendar' ] -%] - -

These requests will only be visible to the person who submitted the request, -any persons designated in the CC line, and authorized members of the Mozilla Rep team.

- - - -

Mozilla Reps - Swag Request Form

- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
First Name: * - -
Last Name: * - -
Wiki User Profile: * - -
Event Wiki Page: * - -
Estimated Attendance: * - -
  
Shipping Details:
Ship Before: - - - -
-
First Name: *
Last Name: *
Address: *
Address 2:
City: *
State:
Country: *
Postal Code: *
Contact Number: *
Personal ID/RUT:
(if your country requires this)
- Addition information for delivery person:
- -
  
Swag Requested:
Stickers:
Buttons:
Posters:
Lanyards:
T-Shirts:
Roll-Up Banners:
Horizontal Banner:
Booth Cloth:
Pens:
Other: (please specify)
  - -
- -

- Quantities of different swag items requested that will actually be shipped - depend on stock availability and number of attendees. Mozilla cannot guarantee - that all items requested will be in stock at the time of shipment and you will - be notified in case an item cannot be shipped. Please request swag at least 1 - month before desired delivery date. -

- -

- * - Required field
- Thanks for contacting us. - You will be notified by email of any progress made in resolving your request. -

- - - -[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl index b2698ae72..f7edccbe1 100644 --- a/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl +++ b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl @@ -34,7 +34,7 @@

Swag Request: Please use this form to file a request for swag.

    -
  1. You first need submit a Event Request Form. You'll be asked for the [% terms.bug %] number below.
  2. +
  3. You first need submit a Event Request Form. You'll be asked for the bug number below.
  4. Complete and submit request below.
  5. Your request will be reviewed by the appropriate person in the Engagement team.
  6. Your swag request will be reviewed and if approved shipped to you from @@ -70,7 +70,7 @@ function validateAndSubmit() { var alert_text = ''; if(!isFilledOut('firstname')) alert_text += "Please enter your first name\n"; if(!isFilledOut('lastname')) alert_text += "Please enter your last name\n"; - if(!isFilledOut('dependson')) alert_text += "Please enter the [% terms.bug %] number for your Event Request Form\n"; + if(!isFilledOut('dependson')) alert_text += "Please enter the bug number for your Event Request Form\n"; if(!isValidEmail(document.getElementById('email').value)) alert_text += "Please enter a valid email address\n"; //Everything required is filled out..try to submit the form! @@ -88,25 +88,25 @@ function validateAndSubmit() { - - - - - - - - - - - + + + + + + + + + + + + - - + 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 70a51b9ab..e7cea5d2b 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 @@ -62,9 +62,9 @@ the full product list.

    The product you have chosen is for [% terms.bug %] reports and enhancement requests for the -[% terms.Bugzilla %] [% terms.bug %] tracking software only. -If your [% terms.bug %] is not reporting that [% terms.Bugzilla %] is broken or that you'd like -a new feature in [% terms.Bugzilla %], your [% terms.bug %] report does not belong in this product. +Bugzilla [% terms.bug %] tracking software only. +If your [% terms.bug %] is not reporting that Bugzilla is broken or that you'd like +a new feature in Bugzilla, your [% terms.bug %] report does not belong in this product. [% IF format == "guided" %] See the instructions next to the stop sign above. [% ELSE %] @@ -72,22 +72,22 @@ a new feature in [% terms.Bugzilla %], your [% terms.bug %] report does not belo [% END %]

    -

    We WILL NOT accept [% terms.bug %] reports for [% terms.Bugzilla %] -installed via the Debian packaging system. If you obtained [% terms.Bugzilla %] from Debian, +

    We WILL NOT accept [% terms.bug %] reports for Bugzilla +installed via the Debian packaging system. If you obtained Bugzilla from Debian, please visit the Debian Support page, -or file a [% terms.bug %] on the Debian -[% terms.Bug %] Tracker. The Debian package maintainer will then determine whether the [% terms.bug %] -is specific to the package or not, and can move the [% terms.bug %] "upstream" if needed.

    +or file a bug on the Debian +Bug Tracker. The Debian package maintainer will then determine whether the bug +is specific to the package or not, and can move the bug "upstream" if needed.

    -[% terms.Bugs %] specific to bugzilla.mozilla.org, rather than the [% terms.Bugzilla %] software in +Bugs specific to bugzilla.mozilla.org, rather than the Bugzilla software in general (which is used by many sites), should be filed in the mozilla.org product.

    Please do not file test [% terms.bugs %] or support requests here! You -can test [% terms.Bugzilla %] at +can test Bugzilla at landfill.bugzilla.org and ask for support in the @@ -106,7 +106,7 @@ support-bugzilla@lists.mozilla.org mailing list, or [% UNLESS cloned_bug_id %] Consider using the -[% terms.Bugzilla %] Helper instead of this form. +Bugzilla Helper instead of this form. [% END +%] Before reporting a [% terms.bug %], make sure you've read our diff --git a/extensions/BMO/template/en/default/global/choose-product.html.tmpl b/extensions/BMO/template/en/default/global/choose-product.html.tmpl index c957edca7..a65605a93 100644 --- a/extensions/BMO/template/en/default/global/choose-product.html.tmpl +++ b/extensions/BMO/template/en/default/global/choose-product.html.tmpl @@ -42,8 +42,7 @@


    -

    Looking for technical support or help getting your site to work with Mozilla? Visit the -mozilla.org support page before filing [% terms.bugs %].

    +

    Looking for technical support or help getting your site to work with Mozilla? Visit the mozilla.org support page before filing bugs.


    @@ -147,7 +146,7 @@ mozilla.org support page before filing [% terms.bugs %].


    [% IF target == "enter_bug.cgi" AND user.settings.product_chooser.value != 'full_product_chooser' %] -

    You can choose to get this screen by default when you click "New [% terms.Bug %]" by changing your preferences.

    +

    You can choose to get this screen by default when you click "New Bug" by changing your preferences.

    [% END %] [% END %]
    diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl index 5b58a9637..ee88aac7c 100644 --- a/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl +++ b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl @@ -1,4 +1,4 @@ - + diff --git a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl index ba6eeb78c..0c68d8e72 100644 --- a/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl +++ b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl @@ -49,6 +49,7 @@ [% FOREACH field = Bugzilla.active_custom_fields %] [% NEXT IF NOT user.id AND field.value == "---" %] [% NEXT IF cf_hidden_in_product(field.name, bug.product, bug.component, 2) %] + [% NEXT IF cf_flag_disabled(field.name, bug) %] [% custom_flags.push(field.name) %] diff --git a/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl index 05276d5f7..0277f3e7e 100644 --- a/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl +++ b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl @@ -21,7 +21,7 @@ [% IF bug %] - + [% END %] + + +buggie +
    +

    [% terms.Bug %] Updates Temporarily Suspended

    + +

    +We are currently adding a field to [% terms.Bugzilla %]. This requires us to +prevent updates to [% terms.bugs %] for the duration of the database schema +change to add the field (usually 3 to 5 minutes). +

    + +

    +You should be able to leave this page open, wait a minute or two, then hit +reload or refresh in your browser (and OK any request to re-send the form +data) to complete your [% terms.bug %] change. Once this maintenance is +complete, your change will succeed and you won't get this page any more. +

    + +

    +Only updates to [% terms.bugs %] are being blocked by this page, any other +activities in [% terms.Bugzilla %] are still fair game. Open [% terms.Bugzilla %] in a new tab/window if you'd +like, to continue working on other things while waiting. +

    +
    + + diff --git a/template/en/default/bug/show-multiple.html.tmpl b/template/en/default/bug/show-multiple.html.tmpl index 33dde14a3..03ce294c5 100644 --- a/template/en/default/bug/show-multiple.html.tmpl +++ b/template/en/default/bug/show-multiple.html.tmpl @@ -180,6 +180,7 @@ [% USE Bugzilla %] [% field_counter = 0 %] [% FOREACH field = Bugzilla.active_custom_fields %] + [% NEXT IF cf_hidden_in_product(field.name, bug.product, bug.component) %] [% field_counter = field_counter + 1 %] [%# Odd-numbered fields get an opening %] [% '' IF field_counter % 2 %] diff --git a/template/en/default/bug/show.xml.tmpl b/template/en/default/bug/show.xml.tmpl index dae207f26..cb323d229 100644 --- a/template/en/default/bug/show.xml.tmpl +++ b/template/en/default/bug/show.xml.tmpl @@ -20,8 +20,10 @@ # #%] [% PROCESS bug/time.html.tmpl %] +[% USE Bugzilla %] +[% cgi = Bugzilla.cgi %] - + [%- val FILTER xml %] [% END %] diff --git a/template/en/default/config.rdf.tmpl b/template/en/default/config.rdf.tmpl index 15f784ce8..d7b282776 100644 --- a/template/en/default/config.rdf.tmpl +++ b/template/en/default/config.rdf.tmpl @@ -171,9 +171,8 @@ [% IF show_flags %] - [% flag_types = component.flag_types.bug.merge(component.flag_types.attachment) %] + [% flag_types = component.flag_types(is_active=>1).bug.merge(component.flag_types(is_active=>1).attachment) %] [% FOREACH flag_type = flag_types %] - [% NEXT UNLESS flag_type.is_active %] [% all_visible_flag_types.${flag_type.id} = flag_type %]
  7. diff --git a/template/en/default/email/bugmail.txt.tmpl b/template/en/default/email/bugmail.txt.tmpl index 2d20aff7c..7c0bace4a 100644 --- a/template/en/default/email/bugmail.txt.tmpl +++ b/template/en/default/email/bugmail.txt.tmpl @@ -22,9 +22,15 @@ [% PROCESS "global/field-descs.none.tmpl" %] [% PROCESS "global/reason-descs.none.tmpl" %] +[% show_new = isnew + && (to_user.settings.bugmail_new_prefix.value == 'on') %] [% isnew = bug.lastdiffed ? 0 : 1 %] +[% UNLESS to_user.settings.product_chooser.value == 'full_product_chooser' %] +Do not reply to this email. You can add comments to this [% terms.bug %] at +[% END %] + [%+ PROCESS generate_diffs -%] [% FOREACH comment = new_comments %] diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl index a7449883f..480197431 100644 --- a/template/en/default/global/header.html.tmpl +++ b/template/en/default/global/header.html.tmpl @@ -239,8 +239,7 @@ [%# Required for the 'Autodiscovery' feature in Firefox 2 and IE 7. %] - + title="[% terms.BugzillaTitle %]" href="./search_plugin.cgi"> [% Hook.process("additional_header") %] @@ -265,7 +264,7 @@
  8. First Name: *
    Last Name: * @@ -143,7 +143,7 @@ function validateAndSubmit() {
    [% terms.Bug %] number assigned to previously-   
    submitted Event Request Form: *
    Bug number assigned to previously-   
    submitted Event Request Form: *
    Security
     
    diff --git a/template/en/default/global/setting-descs.none.tmpl b/template/en/default/global/setting-descs.none.tmpl index a0b11f048..52d1c9803 100644 --- a/template/en/default/global/setting-descs.none.tmpl +++ b/template/en/default/global/setting-descs.none.tmpl @@ -52,6 +52,7 @@ "email_format" => "Preferred email format", "html" => "HTML", "text_only" => "Text Only", + "bugmail_new_prefix" => "Add 'New:' to subject line of email sent when a new $terms.bug is filed", } %] diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index 35640b220..5310952f2 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -1342,6 +1342,40 @@ [% END %] + [% ELSIF error == "password_not_complex" %] + [% title = "Password Fails Requirements" %] + [% passregex = Param('password_complexity') %] + Password must contain at least one: +
      + [% IF passregex.search('letters') %] +
    • UPPERCASE letter
    • +
    • lowercase letter
    • + [% END %] + [% IF passregex.search('numbers') %] +
    • digit
    • + [% END %] + [% IF passregex.search('specialchars') %] +
    • special character
    • + [% END %] +
    + + [% ELSIF error == "password_not_complex" %] + [% title = "Password Fails Requirements" %] + [% passregex = Param('password_complexity') %] + Password must contain at least one: +
      + [% IF passregex.search('letters') %] +
    • UPPERCASE letter
    • +
    • lowercase letter
    • + [% END %] + [% IF passregex.search('numbers') %] +
    • digit
    • + [% END %] + [% IF passregex.search('specialchars') %] +
    • special character
    • + [% END %] +
    + [% ELSIF error == "product_access_denied" %] [% title = "Product Access Denied" %] Either the product diff --git a/template/en/default/global/user.html.tmpl b/template/en/default/global/user.html.tmpl index df902b451..a6be5eee9 100644 --- a/template/en/default/global/user.html.tmpl +++ b/template/en/default/global/user.html.tmpl @@ -27,6 +27,9 @@ [% FILTER collapse %] [% IF user.id %] | Feed | + [%- title FILTER url_quote %]&ctype=atom">Feed | iCalendar | +
    -

    [% terms.Bugzilla %] +

    [% terms.BugzillaTitle %] [% " – $header" IF header %]

    + [% IF dotweak %] [% END %] - + [% END %] [% BLOCK columnheader %] -
      + @@ -112,7 +115,7 @@ [% FOREACH id = displaycolumns %] [% NEXT IF loop.count() % 2 == 0 %] [% column = columns.$id %] - [% PROCESS columnheader %] + [% PROCESS columnheader key=loop.count() %] [% END %] [% ELSE %] @@ -125,10 +128,13 @@ [% END %]
    + [% FOREACH bug = bugs %] [% count = loop.count() %] @@ -193,7 +200,17 @@ [% FOREACH column = displaycolumns %] + class="bz_[% column FILTER css_class_quote %]_column" + [% SWITCH column %] + [% CASE 'opendate' %] + sorttable_customkey="[% bug.opentime FILTER html %]" + [% CASE 'changeddate' %] + sorttable_customkey="[% bug.changedtime FILTER html %]" + [% CASE columns_sortkey.keys %] + [% SET sortkey = columns_sortkey.$column.${bug.$column} %] + sorttable_customkey="[% sortkey FILTER html %]" + [% END %] + > [% IF abbrev.$column.maxlength %] [% END %] @@ -228,6 +245,7 @@ [% END %] [% END %] +
    diff --git a/template/en/default/pages/bugzilla.dtd.tmpl b/template/en/default/pages/bugzilla.dtd.tmpl new file mode 100644 index 000000000..f7fc1b4ad --- /dev/null +++ b/template/en/default/pages/bugzilla.dtd.tmpl @@ -0,0 +1,179 @@ +[%# The contents of this file are subject to the Mozilla Public + # License Version 1.1 (the "License"); you may not use this file + # except in compliance with the License. You may obtain a copy of + # the License at http://www.mozilla.org/MPL/ + # + # Software distributed under the License is distributed on an "AS + # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + # implied. See the License for the specific language governing + # rights and limitations under the License. + # + # The Original Code is the Bugzilla Bug Tracking System. + # + # The Initial Developer of the Original Code is Netscape Communications + # Corporation. Portions created by Netscape are + # Copyright (C) 1998 Netscape Communications Corporation. All + # Rights Reserved. + # + # Contributor(s): Dawn Endico + # Dave Miller + # Bradley Baetz + # Myk Mylez + # Colin Ogilvie + # Joel Peshkin + # Frédéric Buclin + # Gervase Markham + # Max Kanat-Alexander + # David Lawrence + # + #%] +[% USE Bugzilla %] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[% FOREACH field = Bugzilla.active_custom_fields %] + +[% END %] + + + + + + + + + + + + + + + + + + + + + diff --git a/template/en/default/pages/fields.html.tmpl b/template/en/default/pages/fields.html.tmpl index 2794e1cc4..568245653 100644 --- a/template/en/default/pages/fields.html.tmpl +++ b/template/en/default/pages/fields.html.tmpl @@ -62,34 +62,41 @@
    This [% terms.bug %] has recently been added to the database. - Nobody has confirmed that this [% terms.bug %] is valid. Users + Nobody has validated that this [% terms.bug %] is true. Users who have the "canconfirm" permission set may confirm - this [% terms.bug %], changing its state to - [% display_value("bug_status", "CONFIRMED") FILTER html %]. - Or, it may be directly resolved and marked + this [% terms.bug %], changing its state to [% display_value("bug_status", "NEW") FILTER html %]. Or, it may be + directly resolved and marked [% display_value("bug_status", "RESOLVED") FILTER html %]. +
    +
    + [% display_value("bug_status", "NEW") FILTER html %] +
    +
    + This [% terms.bug %] has recently been added to the assignee's + list of [% terms.bugs %] and must be processed. [% terms.Bugs %] in + this state may be accepted, and become [% display_value("bug_status", "ASSIGNED") FILTER html %], passed + on to someone else, and remain [% display_value("bug_status", "NEW") FILTER html %], or resolved and marked [% display_value("bug_status", "RESOLVED") FILTER html %].
    -
    - [% display_value("bug_status", "CONFIRMED") FILTER html %] +
    + [% display_value("bug_status", "ASSIGNED") FILTER html %]
    -
    - This [% terms.bug %] is valid and has recently been filed. - [%+ terms.Bugs %] in this state become - [% display_value("bug_status", "IN_PROGRESS") FILTER html %] - when somebody is working on them, or become resolved and marked - [% display_value("bug_status", "RESOLVED") FILTER html %]. +
    + This [% terms.bug %] is not yet resolved, but is assigned to the + proper person. From here [% terms.bugs %] can be given to another + person and become [% display_value("bug_status", "NEW") FILTER html %], or + resolved and become [% display_value("bug_status", "RESOLVED") FILTER html %].
    -
    - [% display_value("bug_status", "IN_PROGRESS") FILTER html %] +
    + [% display_value("bug_status", "REOPENED") FILTER html %]
    -
    - This [% terms.bug %] is not yet resolved, but is assigned to the - proper person who is working on the [% terms.bug %]. From here, - [%+ terms.bugs %] can be given to another person and become - [% display_value("bug_status", "CONFIRMED") FILTER html %], or - resolved and become +
    + This [% terms.bug %] was once resolved, but the resolution was + deemed incorrect. For example, a [% display_value("resolution", "WORKSFORME") FILTER html %] [% terms.bug %] is + [% display_value("bug_status", "REOPENED") FILTER html %] when more information shows up and + the [% terms.bug %] is now reproducible. From here [% terms.bugs %] are + either marked [% display_value("bug_status", "ASSIGNED") FILTER html %] or [% display_value("bug_status", "RESOLVED") FILTER html %].
    @@ -124,9 +131,10 @@ [% display_value("bug_status", "VERIFIED") FILTER html %]
    - QA has looked at the [% terms.bug %] and the resolution and - agrees that the appropriate resolution has been taken. This is - the final status for [% terms.bugs %]. + QA has looked at the [% terms.bug %] and the resolution and + agrees that the appropriate resolution has been taken. + Any zombie [% terms.bugs %] who choose to walk the earth again must + do so by becoming [% display_value("bug_status", "REOPENED") FILTER html %].
    [% Hook.process('closed-status') %] @@ -163,10 +171,9 @@
    The problem is a duplicate of an existing [% terms.bug %]. - When [% terms.abug %] is marked as a - [% display_value("resolution", "DUPLICATE") FILTER html %], - you will see which [% terms.bug %] it is a duplicate of, - next to the resolution. + Marking [% terms.abug %] duplicate requires the [% terms.bug %]# + of the duplicating [% terms.bug %] and will at least put + that [% terms.bug %] number in the description field.
    diff --git a/template/en/default/request/email.txt.tmpl b/template/en/default/request/email.txt.tmpl index fb957484b..989e0c4e3 100644 --- a/template/en/default/request/email.txt.tmpl +++ b/template/en/default/request/email.txt.tmpl @@ -25,7 +25,8 @@ [% bugidsummary = bug.bug_id _ ': ' _ bug.short_desc %] [% attidsummary = attachment.id _ ': ' _ attachment.description %] [% flagtype_name = flag ? flag.type.name : old_flag.type.name %] -[% statuses = { '+' => "granted" , '-' => 'denied' , 'X' => "canceled" , +[%# Upstreaming: denied (bug 621883) %] +[% statuses = { '+' => "granted" , '-' => 'not granted' , 'X' => "canceled" , '?' => "asked" } %] [% to_identity = "" %] diff --git a/template/en/default/search/field.html.tmpl b/template/en/default/search/field.html.tmpl index defc94cc3..19f199692 100644 --- a/template/en/default/search/field.html.tmpl +++ b/template/en/default/search/field.html.tmpl @@ -115,7 +115,7 @@ + + + + +
    + +[% END %] + +[% PROCESS global/footer.html.tmpl %] + diff --git a/template/en/default/search/search-specific.html.tmpl b/template/en/default/search/search-specific.html.tmpl index 31d950ec5..277a90960 100644 --- a/template/en/default/search/search-specific.html.tmpl +++ b/template/en/default/search/search-specific.html.tmpl @@ -98,7 +98,7 @@ for "crash secure SSL flash". - + +   + + + + + + diff --git a/template/en/default/search/tabs.html.tmpl b/template/en/default/search/tabs.html.tmpl index 119b30fde..6a2f7f70a 100644 --- a/template/en/default/search/tabs.html.tmpl +++ b/template/en/default/search/tabs.html.tmpl @@ -27,7 +27,9 @@ tabs = [ { name => 'specific', label => "Simple Search", link => "query.cgi?format=specific" }, { name => 'advanced', label => "Advanced Search", - link => "query.cgi?format=advanced" } ] + link => "query.cgi?format=advanced" }, + { name => 'google', label => 'Google Search', + link => "query.cgi?format=google" } ] current_tab_name = query_format || format || "advanced" %] -- cgit v1.2.3-24-g4f1b