summaryrefslogtreecommitdiffstats
path: root/extensions/BMO
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/BMO')
-rw-r--r--extensions/BMO/Config.pm38
-rw-r--r--extensions/BMO/Extension.pm746
-rw-r--r--extensions/BMO/lib/Data.pm266
-rw-r--r--extensions/BMO/lib/FakeBug.pm40
-rw-r--r--extensions/BMO/lib/Reports.pm522
-rw-r--r--extensions/BMO/lib/WebService.pm207
-rw-r--r--extensions/BMO/template/en/default/account/create.html.tmpl181
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl48
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl44
-rw-r--r--extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl48
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl221
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl187
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl216
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl250
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl306
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl651
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl85
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl217
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl221
-rw-r--r--extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl87
-rw-r--r--extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl38
-rw-r--r--extensions/BMO/template/en/default/bug/create/user-message.html.tmpl140
-rw-r--r--extensions/BMO/template/en/default/global/choose-product.html.tmpl182
-rw-r--r--extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl1
-rw-r--r--extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl7
-rw-r--r--extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl18
-rw-r--r--extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl22
-rw-r--r--extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl83
-rw-r--r--extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl114
-rw-r--r--extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl27
-rw-r--r--extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl1
-rw-r--r--extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl60
-rw-r--r--extensions/BMO/template/en/default/hook/global/header-start.html.tmpl3
-rw-r--r--extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl5
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl3
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl40
-rw-r--r--extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl29
-rw-r--r--extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl3
-rw-r--r--extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl10
-rw-r--r--extensions/BMO/template/en/default/hook/index-intro.html.tmpl2
-rw-r--r--extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl13
-rw-r--r--extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl13
-rw-r--r--extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl41
-rw-r--r--extensions/BMO/template/en/default/list/list.microsummary.tmpl29
-rw-r--r--extensions/BMO/template/en/default/list/server-push.html.tmpl52
-rw-r--r--extensions/BMO/template/en/default/pages/bug-writing.html.tmpl25
-rw-r--r--extensions/BMO/template/en/default/pages/etiquette.html.tmpl147
-rw-r--r--extensions/BMO/template/en/default/pages/get_help.html.tmpl42
-rw-r--r--extensions/BMO/template/en/default/pages/group_admins.html.tmpl53
-rw-r--r--extensions/BMO/template/en/default/pages/triage_reports.html.tmpl199
-rw-r--r--extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl304
-rw-r--r--extensions/BMO/template/en/default/pages/user_activity.html.tmpl180
-rw-r--r--extensions/BMO/template/en/default/search/search-plugin.xml.tmpl24
-rw-r--r--extensions/BMO/web/images/background.pngbin0 -> 1695 bytes
-rw-r--r--extensions/BMO/web/images/bugzilla.pngbin0 -> 1242 bytes
-rw-r--r--extensions/BMO/web/images/groups/bugzilla-approvers.pngbin0 -> 829 bytes
-rw-r--r--extensions/BMO/web/images/groups/calendar-drivers.pngbin0 -> 744 bytes
-rw-r--r--extensions/BMO/web/images/mozchomp.gifbin0 -> 89485 bytes
-rw-r--r--extensions/BMO/web/images/presshat.pngbin0 -> 23450 bytes
-rw-r--r--extensions/BMO/web/images/stop-sign.gifbin0 -> 3227 bytes
-rw-r--r--extensions/BMO/web/js/edit_bug.js71
-rw-r--r--extensions/BMO/web/js/edituser_menu.js26
-rw-r--r--extensions/BMO/web/js/form_validate.js21
-rw-r--r--extensions/BMO/web/js/sorttable.js709
-rw-r--r--extensions/BMO/web/js/swag.js60
-rw-r--r--extensions/BMO/web/js/triage_reports.js83
-rw-r--r--extensions/BMO/web/producticons/camino.pngbin0 -> 6060 bytes
-rw-r--r--extensions/BMO/web/producticons/dino.pngbin0 -> 3375 bytes
-rw-r--r--extensions/BMO/web/producticons/fennec.pngbin0 -> 9023 bytes
-rw-r--r--extensions/BMO/web/producticons/firefox.pngbin0 -> 9395 bytes
-rw-r--r--extensions/BMO/web/producticons/idea.pngbin0 -> 6189 bytes
-rw-r--r--extensions/BMO/web/producticons/input.pngbin0 -> 8333 bytes
-rw-r--r--extensions/BMO/web/producticons/labs.pngbin0 -> 4085 bytes
-rw-r--r--extensions/BMO/web/producticons/mozilla.pngbin0 -> 10808 bytes
-rw-r--r--extensions/BMO/web/producticons/other.pngbin0 -> 6654 bytes
-rw-r--r--extensions/BMO/web/producticons/seamonkey.pngbin0 -> 5255 bytes
-rw-r--r--extensions/BMO/web/producticons/sunbird.pngbin0 -> 10462 bytes
-rw-r--r--extensions/BMO/web/producticons/thunderbird.pngbin0 -> 9939 bytes
-rw-r--r--extensions/BMO/web/styles/create_account.css62
-rw-r--r--extensions/BMO/web/styles/edit_bug.css32
-rw-r--r--extensions/BMO/web/styles/reports.css37
-rw-r--r--extensions/BMO/web/styles/triage_reports.css23
83 files changed, 7617 insertions, 0 deletions
diff --git a/extensions/BMO/Config.pm b/extensions/BMO/Config.pm
new file mode 100644
index 000000000..0ad817768
--- /dev/null
+++ b/extensions/BMO/Config.pm
@@ -0,0 +1,38 @@
+# -*- 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 BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Gervase Markham
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+
+package Bugzilla::Extension::BMO;
+use strict;
+
+use constant NAME => 'BMO';
+
+use constant REQUIRED_MODULES => [
+ {
+ package => 'Tie-IxHash',
+ module => 'Tie::IxHash',
+ version => 0
+ }
+];
+
+use constant OPTIONAL_MODULES => [
+];
+
+__PACKAGE__->NAME;
diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm
new file mode 100644
index 000000000..c800ade3d
--- /dev/null
+++ b/extensions/BMO/Extension.pm
@@ -0,0 +1,746 @@
+# -*- 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 BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Gervase Markham.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+# David Lawrence <dkl@mozilla.com>
+# Byron Jones <glob@mozilla.com>
+
+package Bugzilla::Extension::BMO;
+use strict;
+use base qw(Bugzilla::Extension);
+
+use Bugzilla::Field;
+use Bugzilla::Constants;
+use Bugzilla::Status;
+use Bugzilla::User;
+use Bugzilla::User::Setting;
+use Bugzilla::Util qw(html_quote trick_taint trim datetime_from detaint_natural);
+use Bugzilla::Token;
+use Bugzilla::Error;
+use Bugzilla::Mailer;
+
+use Scalar::Util qw(blessed);
+use Date::Parse;
+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
+ $status_trusted_wanters
+ $status_trusted_setters
+ $other_setters
+ %always_fileable_group
+ %product_sec_groups);
+use Bugzilla::Extension::BMO::Reports qw(user_activity_report
+ triage_reports
+ group_admins);
+
+our $VERSION = '0.1';
+
+#
+# Monkey-patched methods
+#
+
+BEGIN {
+ *Bugzilla::Bug::last_closed_date = \&_last_closed_date;
+}
+
+sub template_before_process {
+ my ($self, $args) = @_;
+ my $file = $args->{'file'};
+ 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
+ # Matched to changes in list/table.html.tmpl
+ my %db_order_column_name_map = (
+ 'map_components.name' => 'component',
+ 'map_products.name' => 'product',
+ 'map_reporter.login_name' => 'reporter',
+ 'map_assigned_to.login_name' => 'assigned_to',
+ 'delta_ts' => 'opendate',
+ 'creation_ts' => 'changeddate',
+ );
+
+ my @orderstrings = split(/,\s*/, $vars->{'order'});
+
+ # contains field names of the columns being used to sort the table.
+ my @order_columns;
+ foreach my $o (@orderstrings) {
+ $o =~ s/bugs.//;
+ $o = $db_order_column_name_map{$o} if
+ grep($_ eq $o, keys(%db_order_column_name_map));
+ next if (grep($_ eq $o, @order_columns));
+ push(@order_columns, $o);
+ }
+
+ $vars->{'order_columns'} = \@order_columns;
+
+ # fields that have a custom sortkey. (So they are correctly sorted
+ # when using js)
+ my @sortkey_fields = qw(bug_status resolution bug_severity priority
+ rep_platform op_sys);
+
+ my %columns_sortkey;
+ foreach my $field (@sortkey_fields) {
+ $columns_sortkey{$field} = _get_field_values_sort_key($field);
+ }
+ $columns_sortkey{'target_milestone'} = _get_field_values_sort_key('milestones');
+
+ $vars->{'columns_sortkey'} = \%columns_sortkey;
+ }
+ elsif ($file =~ /^bug\/create\/create[\.-]/) {
+ if (!$vars->{'cloned_bug_id'}) {
+ # Allow status whiteboard values to be bookmarked
+ $vars->{'status_whiteboard'} =
+ Bugzilla->cgi->param('status_whiteboard') || "";
+ }
+
+ # Purpose: for pretty product chooser
+ $vars->{'format'} = Bugzilla->cgi->param('format');
+
+ # Data needed for "this is a security bug" checkbox
+ $vars->{'sec_groups'} = \%product_sec_groups;
+ }
+
+
+ if ($file =~ /^list\/list/ || $file =~ /^bug\/create\/create[\.-]/) {
+ # 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.
+ $vars->{'default'} = Bugzilla::Extension::BMO::FakeBug->new($vars->{'default'} || {});
+ }
+}
+
+sub page_before_template {
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ if ($page eq 'user_activity.html') {
+ user_activity_report($vars);
+
+ } elsif ($page eq 'triage_reports.html') {
+ triage_reports($vars);
+
+ } elsif ($page eq 'upgrade-3.6.html') {
+ $vars->{'bzr_history'} = sub {
+ return `cd /data/www/bugzilla.mozilla.org; /usr/bin/bzr log -n0 -rlast:10..`;
+ };
+ }
+ elsif ($page eq 'fields.html') {
+ # Recently global/field-descs.none.tmpl and bug/field-help.none.tmpl
+ # were changed for better performance and are now only loaded once.
+ # I have not found an easy way to allow our hook template to check if
+ # it is called from pages/fields.html.tmpl. So we set a value in request_cache
+ # that our hook template can see.
+ Bugzilla->request_cache->{'bmo_fields_page'} = 1;
+ }
+ elsif ($page eq 'group_admins.html') {
+ group_admins($vars);
+ }
+}
+
+sub _get_field_values_sort_key {
+ my ($field) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $fields = $dbh->selectall_arrayref(
+ "SELECT value, sortkey FROM $field
+ ORDER BY sortkey, value");
+
+ my %field_values;
+ foreach my $field (@$fields) {
+ my ($value, $sortkey) = @$field;
+ $field_values{$value} = $sortkey;
+ }
+ return \%field_values;
+}
+
+sub cf_hidden_in_product {
+ my ($field_name, $product_name, $component_name, $custom_flag_mode) = @_;
+
+ # If used in buglist.cgi, we pass in one_product which is a Bugzilla::Product
+ # elsewhere, we just pass the name of the product.
+ $product_name = blessed($product_name) ? $product_name->name
+ : $product_name;
+
+ # Also in buglist.cgi, we pass in a list of components instead
+ # of a single compoent name everywhere else.
+ my $component_list = ref $component_name ? $component_name
+ : [ $component_name ];
+
+ if ($custom_flag_mode) {
+ if ($custom_flag_mode == 1) {
+ # skip custom flags
+ foreach my $flag_re (@$cf_flags) {
+ return 1 if $field_name =~ $flag_re;
+ }
+ } elsif ($custom_flag_mode == 2) {
+ # custom flags only
+ my $found = 0;
+ foreach my $flag_re (@$cf_flags) {
+ if ($field_name =~ $flag_re) {
+ $found = 1;
+ last;
+ }
+ }
+ return 1 unless $found;
+ }
+ }
+
+ foreach my $field_re (keys %$cf_visible_in_products) {
+ if ($field_name =~ $field_re) {
+ # If no product given, for example more than one product
+ # in buglist.cgi, then hide field by default
+ return 1 if !$product_name;
+
+ my $products = $cf_visible_in_products->{$field_re};
+ foreach my $product (keys %$products) {
+ my $components = $products->{$product};
+
+ my $found_component = 0;
+ if (@$components) {
+ foreach my $component (@$components) {
+ if (grep($_ eq $component, @$component_list)) {
+ $found_component = 1;
+ last;
+ }
+ }
+ }
+
+ # If product matches and at at least one component matches
+ # from component_list (if a matching component was required),
+ # we allow the field to be seen
+ if ($product eq $product_name && (!@$components || $found_component)) {
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+ }
+
+ 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 {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+ my $recipients = $args->{'recipients'};
+ my $diffs = $args->{'diffs'};
+
+ if (@$diffs) {
+ # Changed bug
+ foreach my $ref (@$diffs) {
+ my ($who, $whoname, $what, $when,
+ $old, $new, $attachid, $fieldname) = (@$ref);
+
+ if ($fieldname eq "bug_group") {
+ _cc_if_special_group($old, $recipients);
+ _cc_if_special_group($new, $recipients);
+ }
+ }
+ } else {
+ # Determine if it's a new bug, or a comment without a field change
+ my $comment_count = scalar @{$bug->comments};
+ if ($comment_count == 1) {
+ # New bug
+ foreach my $group (@{ $bug->groups_in }) {
+ _cc_if_special_group($group->{'name'}, $recipients);
+ }
+ }
+ }
+}
+
+sub _cc_if_special_group {
+ my ($group, $recipients) = @_;
+
+ return if !$group;
+
+ if ($group_to_cc_map{$group}) {
+ my $id = login_to_id($group_to_cc_map{$group});
+ $recipients->{$id}->{+REL_CC} = Bugzilla::BugMail::BIT_DIRECT();
+ }
+}
+
+sub _check_trusted {
+ my ($field, $trusted, $priv_results) = @_;
+
+ my $needed_group = $trusted->{'_default'} || "";
+ foreach my $dfield (keys %$trusted) {
+ if ($field =~ $dfield) {
+ $needed_group = $trusted->{$dfield};
+ }
+ }
+ if ($needed_group && !Bugzilla->user->in_group($needed_group)) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+}
+
+sub _is_field_set {
+ my $value = shift;
+ return $value ne '---' && $value ne '?';
+}
+
+sub bug_check_can_change_field {
+ my ($self, $args) = @_;
+ my $bug = $args->{'bug'};
+ my $field = $args->{'field'};
+ my $new_value = $args->{'new_value'};
+ my $old_value = $args->{'old_value'};
+ my $priv_results = $args->{'priv_results'};
+ my $user = Bugzilla->user;
+
+ # Only users in the appropriate drivers group can change the
+ # cf_blocking_* fields or cf_tracking_* fields
+
+ if ($field =~ /^cf_(?:blocking|tracking)_/) {
+ # 0 -> 1 is used by show_bug, always allow so we skip this whole part
+ if (!($old_value eq '0' && $new_value eq '1')) {
+ # require privileged access to set a flag
+ if (_is_field_set($new_value)) {
+ _check_trusted($field, $blocking_trusted_setters, $priv_results);
+ }
+
+ # require editbugs to clear or re-nominate a set flag
+ elsif (_is_field_set($old_value)
+ && !$user->in_group('editbugs', $bug->{'product_id'}))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+
+ if ($new_value eq '?') {
+ _check_trusted($field, $blocking_trusted_requesters, $priv_results);
+ }
+ if ($user->id) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field =~ /^cf_status_/) {
+ # Only drivers can set wanted.
+ if ($new_value eq 'wanted') {
+ _check_trusted($field, $status_trusted_wanters, $priv_results);
+ } elsif (_is_field_set($new_value)) {
+ _check_trusted($field, $status_trusted_setters, $priv_results);
+ }
+ if ($user->id) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field =~ /^cf/ && !@$priv_results && $new_value ne '---') {
+ # "other" custom field setters restrictions
+ if (exists $other_setters->{$field}) {
+ my $in_group = 0;
+ foreach my $group (@{$other_setters->{$field}}) {
+ if ($user->in_group($group, $bug->product_id)) {
+ $in_group = 1;
+ last;
+ }
+ }
+ if (!$in_group) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+
+ } elsif ($field eq 'resolution' && $new_value eq 'EXPIRED') {
+ # The EXPIRED resolution should only be settable by gerv.
+ if ($user->login ne 'gerv@mozilla.org') {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+
+ } elsif ($field eq 'resolution' && $new_value eq 'FIXED') {
+ # You need at least canconfirm to mark a bug as FIXED
+ if (!$user->in_group('canconfirm', $bug->{'product_id'})) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+
+ } elsif ($user->in_group('canconfirm', $bug->{'product_id'})) {
+ # Canconfirm is really "cantriage"; users with canconfirm can also mark
+ # bugs as DUPLICATE, WORKSFORME, and INCOMPLETE.
+ if ($field eq 'bug_status'
+ && is_open_state($old_value)
+ && !is_open_state($new_value))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+ elsif ($field eq 'resolution' &&
+ ($new_value eq 'DUPLICATE' ||
+ $new_value eq 'WORKSFORME' ||
+ $new_value eq 'INCOMPLETE'))
+ {
+ push (@$priv_results, PRIVILEGES_REQUIRED_NONE);
+ }
+
+ } elsif ($field eq 'bug_status') {
+ # Disallow reopening of bugs which have been resolved for > 1 year
+ if (is_open_state($new_value)
+ && !is_open_state($old_value)
+ && $bug->resolution eq 'FIXED')
+ {
+ my $days_ago = DateTime->now(time_zone => Bugzilla->local_timezone);
+ $days_ago->subtract(days => 365);
+ my $last_closed = datetime_from($bug->last_closed_date);
+ if ($last_closed lt $days_ago) {
+ push (@$priv_results, PRIVILEGES_REQUIRED_EMPOWERED);
+ }
+ }
+ }
+}
+
+# Purpose: link up various Mozilla-specific strings.
+sub _link_uuid {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+
+ return qq{<a href="https://crash-stats.mozilla.com/report/index/$match">bp-$match</a>};
+}
+
+sub _link_cve {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+
+ return qq{<a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=$match">$match</a>};
+}
+
+sub _link_svn {
+ my $args = shift;
+ my $match = html_quote($args->{matches}->[0]);
+
+ return qq{<a href="http://viewvc.svn.mozilla.org/vc?view=rev&amp;revision=$match">r$match</a>};
+}
+
+sub _link_hg {
+ my $args = shift;
+ my $text = html_quote($args->{matches}->[0]);
+ my $repo = html_quote($args->{matches}->[1]);
+ my $id = html_quote($args->{matches}->[2]);
+
+ return qq{<a href="https://hg.mozilla.org/$repo/rev/$id">$text</a>};
+}
+
+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<a href="http://$url/revision/$id">$text</a>};
+}
+
+sub bug_format_comment {
+ my ($self, $args) = @_;
+ my $regexes = $args->{'regexes'};
+
+ # Only match if not already in an URL using the negative lookbehind (?<!\/)
+ push (@$regexes, {
+ match => qr/(?<!\/)\b(?:UUID\s+|bp\-)([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-
+ [a-f0-9]{4}\-[a-f0-9]{12})\b/x,
+ replace => \&_link_uuid
+ });
+
+ push (@$regexes, {
+ match => qr/(?<!\/)\b((?:CVE|CAN)-\d{4}-\d{4})\b/,
+ replace => \&_link_cve
+ });
+
+ push (@$regexes, {
+ match => qr/\b((?:CVE|CAN)-\d{4}-\d{4})\b/,
+ replace => \&_link_cve
+ });
+
+ push (@$regexes, {
+ match => qr/\br(\d{4,})\b/,
+ 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.]+
+ (?:releases/)?mobile-[\w.]+
+ tracemonkey
+ tamarin-[\w.]+
+ camino!);
+
+ push (@$regexes, {
+ match => qr/\b(($hgrepos)\s+changeset:?\s+(?:\d+:)?([0-9a-fA-F]{12}))\b/,
+ replace => \&_link_hg
+ });
+}
+
+# Purpose: make it always possible to file bugs in certain groups.
+sub bug_check_groups {
+ my ($self, $args) = @_;
+ my $group_names = $args->{'group_names'};
+ my $add_groups = $args->{'add_groups'};
+
+ $group_names = ref $group_names
+ ? $group_names
+ : [ map { trim($_) } split(',', $group_names) ];
+
+ foreach my $name (@$group_names) {
+ if ($always_fileable_group{$name}) {
+ my $group = new Bugzilla::Group({ name => $name }) or next;
+ $add_groups->{$group->id} = $group;
+ }
+ }
+}
+
+# Purpose: generically handle generating pretty blocking/status "flags" from
+# custom field names.
+sub quicksearch_map {
+ my ($self, $args) = @_;
+ my $map = $args->{'map'};
+
+ foreach my $name (keys %$map) {
+ if ($name =~ /^cf_(blocking|tracking|status)_([a-z]+)?(\d+)?$/) {
+ my $type = $1;
+ my $product = $2;
+ my $version = $3;
+
+ if ($version) {
+ $version = join('.', split(//, $version));
+ }
+
+ my $pretty_name = $type;
+ if ($product) {
+ $pretty_name .= "-" . $product;
+ }
+ if ($version) {
+ $pretty_name .= $version;
+ }
+
+ $map->{$pretty_name} = $name;
+ }
+ elsif ($name =~ /cf_crash_signature$/) {
+ $map->{'sig'} = $name;
+ }
+ }
+}
+
+# Restrict content types attachable by non-privileged people
+my @mimetype_whitelist = ('^image\/', 'application\/pdf');
+
+sub object_end_of_create_validators {
+ my ($self, $args) = @_;
+ my $class = $args->{'class'};
+
+ if ($class->isa('Bugzilla::Attachment')) {
+ my $params = $args->{'params'};
+ my $bug = $params->{'bug'};
+ if (!Bugzilla->user->in_group('editbugs', $bug->product_id)) {
+ my $mimetype = $params->{'mimetype'};
+ if (!grep { $mimetype =~ /$_/ } @mimetype_whitelist ) {
+ # Need to neuter MIME type to something non-executable
+ if ($mimetype =~ /^text\//) {
+ $params->{'mimetype'} = "text/plain";
+ }
+ else {
+ $params->{'mimetype'} = "application/octet-stream";
+ }
+ }
+ }
+ }
+}
+
+sub install_before_final_checks {
+ my ($self, $args) = @_;
+
+ # Add product chooser setting (although it was added long ago, so add_setting
+ # will just return every time).
+ add_setting('product_chooser',
+ ['pretty_product_chooser', 'full_product_chooser'],
+ 'pretty_product_chooser');
+
+ # Migrate from 'gmail_threading' setting to 'bugmail_new_prefix'
+ my $dbh = Bugzilla->dbh;
+ if ($dbh->selectrow_array("SELECT 1 FROM setting WHERE name='gmail_threading'")) {
+ $dbh->bz_start_transaction();
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='on-temp'
+ WHERE setting_name='gmail_threading' AND setting_value='Off'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='off'
+ WHERE setting_name='gmail_threading' AND setting_value='On'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_value='on'
+ WHERE setting_name='gmail_threading' AND setting_value='on-temp'");
+ $dbh->do("UPDATE profile_setting
+ SET setting_name='bugmail_new_prefix'
+ WHERE setting_name='gmail_threading'");
+ $dbh->do("DELETE FROM setting WHERE name='gmail_threading'");
+ $dbh->bz_commit_transaction();
+ }
+}
+
+# Migrate old is_active stuff to new patch (is in core in 4.2), The old column
+# name was 'is_active', the new one is 'isactive' (no underscore).
+sub install_update_db {
+ my $dbh = Bugzilla->dbh;
+
+ if ($dbh->bz_column_info('milestones', 'is_active')) {
+ $dbh->do("UPDATE milestones SET isactive = 0 WHERE is_active = 0;");
+ $dbh->bz_drop_column('milestones', 'is_active');
+ $dbh->bz_drop_column('milestones', 'is_searchable');
+ }
+}
+
+sub _last_closed_date {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ return $self->{'last_closed_date'} if defined $self->{'last_closed_date'};
+
+ my $closed_statuses = "'" . join("','", map { $_->name } closed_bug_statuses()) . "'";
+ my $status_field_id = get_field_id('bug_status');
+
+ $self->{'last_closed_date'} = $dbh->selectrow_array("
+ SELECT bugs_activity.bug_when
+ FROM bugs_activity
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.added IN ($closed_statuses)
+ AND bugs_activity.bug_id = ?
+ ORDER BY bugs_activity.bug_when DESC " . $dbh->sql_limit(1),
+ undef, $status_field_id, $self->id
+ );
+
+ return $self->{'last_closed_date'};
+}
+
+sub field_end_of_create {
+ my ($self, $args) = @_;
+ my $field = $args->{'field'};
+
+ # email mozilla's DBAs so they can update the grants for metrics
+ # this really should create a bug in mozilla.org/Server Operations: Database
+
+ if (Bugzilla->params->{'urlbase'} ne 'https://bugzilla.mozilla.org/') {
+ return;
+ }
+
+ if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) {
+ print "Emailing notification to infra-dbnotices\@mozilla.com\n";
+ }
+
+ my $name = $field->name;
+ my @message;
+ push @message, 'To: infra-dbnotices@mozilla.com';
+ push @message, "Subject: custom field '$name' added to bugzilla.mozilla.org";
+ push @message, 'From: ' . Bugzilla->params->{mailfrom};
+ push @message, '';
+ push @message, "The custom field '$name' has been added to the BMO database.";
+ push @message, '';
+ push @message, 'Please run the following on tm-bugs01-master01:';
+ push @message, " GRANT SELECT ON `bugs`.`$name` TO 'metrics'\@'10.2.70.20_';";
+ push @message, " GRANT SELECT ($name) ON `bugs`.`bugs` TO 'metrics'\@'10.2.70.20_';";
+ push @message, '';
+ MessageToMTA(join("\n", @message));
+}
+
+sub webservice {
+ my ($self, $args) = @_;
+
+ my $dispatch = $args->{dispatch};
+ $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
new file mode 100644
index 000000000..ccc729a6d
--- /dev/null
+++ b/extensions/BMO/lib/Data.pm
@@ -0,0 +1,266 @@
+# -*- 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 BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010 the
+# Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Gervase Markham <gerv@gerv.net>
+# Reed Loden <reed@reedloden.com>
+
+package Bugzilla::Extension::BMO::Data;
+use strict;
+
+use base qw(Exporter);
+use Tie::IxHash;
+
+our @EXPORT_OK = qw($cf_visible_in_products
+ $cf_flags $cf_disabled_flags
+ %group_to_cc_map
+ $blocking_trusted_setters
+ $blocking_trusted_requesters
+ $status_trusted_wanters
+ $status_trusted_setters
+ $other_setters
+ %always_fileable_group
+ %product_sec_groups);
+
+# Which custom fields are visible in which products and components.
+#
+# By default, custom fields are visible in all products. However, if the name
+# of the field matches any of these regexps, it is only visible if the
+# product (and component if necessary) is a member of the attached hash. []
+# for component means "all".
+#
+# IxHash keeps them in insertion order, and so we get regexp priorities right.
+our $cf_visible_in_products;
+tie(%$cf_visible_in_products, "Tie::IxHash",
+ qr/^cf_blocking_fennec/ => {
+ "addons.mozilla.org" => [],
+ "AUS" => [],
+ "Core" => [],
+ "Fennec" => [],
+ "mozilla.org" => ["Release Engineering"],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "support.mozilla.com" => [],
+ "Toolkit" => [],
+ "Tech Evangelism" => [],
+ "Mozilla Localizations" => [],
+ },
+ qr/^cf_tracking_thunderbird|cf_blocking_thunderbird|cf_status_thunderbird/ => {
+ "support.mozillamessaging.com" => [],
+ "Thunderbird" => [],
+ "MailNews Core" => [],
+ "Mozilla Messaging" => [],
+ "Websites" => ["www.mozillamessaging.com"],
+ },
+ qr/^(cf_(blocking|tracking)_seamonkey|cf_status_seamonkey)/ => {
+ "Composer" => [],
+ "MailNews Core" => [],
+ "Mozilla Localizations" => [],
+ "Other Applications" => [],
+ "SeaMonkey" => [],
+ },
+ qr/^cf_blocking_|cf_tracking_|cf_status/ => {
+ "Add-on SDK" => [],
+ "addons.mozilla.org" => [],
+ "AUS" => [],
+ "Core Graveyard" => [],
+ "Core" => [],
+ "Directory" => [],
+ "Fennec" => [],
+ "Firefox" => [],
+ "MailNews Core" => [],
+ "mozilla.org" => ["Release Engineering"],
+ "Mozilla Localizations" => [],
+ "Mozilla Services" => [],
+ "NSPR" => [],
+ "NSS" => [],
+ "Other Applications" => [],
+ "SeaMonkey" => [],
+ "support.mozilla.com" => [],
+ "Tech Evangelism" => [],
+ "Testing" => [],
+ "Toolkit" => [],
+ "Websites" => ["getpersonas.com"],
+ "Webtools" => [],
+ "Plugins" => [],
+ },
+ qr/^cf_colo_site$/ => {
+ "mozilla.org" => [
+ "Server Operations",
+ "Server Operations: Projects",
+ "Server Operations: RelEng",
+ "Server Operations: Security",
+ ],
+ },
+ qw/^cf_office$/ => {
+ "mozilla.org" => ["Server Operations: Desktop Issues"],
+ },
+ qr/^cf_crash_signature$/ => {
+ "addons.mozilla.org" => [],
+ "Add-on SDK" => [],
+ "Calendar" => [],
+ "Camino" => [],
+ "Composer" => [],
+ "Fennec" => [],
+ "Firefox" => [],
+ "Mozilla Localizations" => [],
+ "Mozilla Services" => [],
+ "Other Applications" => [],
+ "Penelope" => [],
+ "SeaMonkey" => [],
+ "Thunderbird" => [],
+ "Core" => [],
+ "Directory" => [],
+ "JSS" => [],
+ "MailNews Core" => [],
+ "NSPR" => [],
+ "NSS" => [],
+ "Plugins" => [],
+ "Rhino" => [],
+ "Tamarin" => [],
+ "Testing" => [],
+ "Toolkit" => [],
+ "Mozilla Labs" => [],
+ "mozilla.org" => [],
+ "Tech Evangelism" => [],
+ },
+ qw/^cf_due_date$/ => {
+ "Mozilla Reps" => [],
+ },
+);
+
+# Which custom fields are acting as flags (ie. custom flags)
+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',
+ 'client-services-security' => 'amo-admins@mozilla.org',
+ 'core-security' => 'security@mozilla.org',
+ 'tamarin-security' => 'tamarinsecurity@adobe.com',
+ 'websites-security' => 'website-drivers@mozilla.org',
+ 'webtools-security' => 'webtools-security@mozilla.org',
+);
+
+# Only users in certain groups can change certain custom fields in
+# certain ways.
+#
+# Who can set cf_blocking_* or cf_tracking_* to +/-
+our $blocking_trusted_setters = {
+ 'cf_blocking_fennec' => 'fennec-drivers',
+ 'cf_blocking_20' => 'mozilla-next-drivers',
+ qr/^cf_tracking_firefox/ => 'mozilla-next-drivers',
+ qr/^cf_blocking_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_tracking_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_tracking_seamonkey/ => 'seamonkey-council',
+ qr/^cf_blocking_seamonkey/ => 'seamonkey-council',
+ '_default' => 'mozilla-stable-branch-drivers',
+};
+
+# Who can request cf_blocking_* or cf_tracking_*
+our $blocking_trusted_requesters = {
+ qr/^cf_blocking_thunderbird/ => 'thunderbird-trusted-requesters',
+ '_default' => 'everyone',
+};
+
+# Who can set cf_status_* to "wanted"?
+our $status_trusted_wanters = {
+ 'cf_status_20' => 'mozilla-next-drivers',
+ qr/^cf_status_thunderbird/ => 'thunderbird-drivers',
+ qr/^cf_status_seamonkey/ => 'seamonkey-council',
+ '_default' => 'mozilla-stable-branch-drivers',
+};
+
+# Who can set cf_status_* to values other than "wanted"?
+our $status_trusted_setters = {
+ qr/^cf_status_thunderbird/ => 'editbugs',
+ '_default' => 'canconfirm',
+};
+
+# Who can set other custom flags (use full field names only, not regex's)
+our $other_setters = {
+ 'cf_colo_site' => ['infra', 'build'],
+};
+
+# Groups in which you can always file a bug, whoever you are.
+our %always_fileable_group = (
+ 'bugzilla-security' => 1,
+ 'client-services-security' => 1,
+ 'consulting' => 1,
+ 'core-security' => 1,
+ 'infra' => 1,
+ 'marketing-private' => 1,
+ 'mozilla-confidential' => 1,
+ 'mozilla-corporation-confidential' => 1,
+ 'mozilla-messaging-confidential' => 1,
+ 'tamarin-security' => 1,
+ 'websites-security' => 1,
+ 'webtools-security' => 1,
+);
+
+# Mapping of products to their security bits
+our %product_sec_groups = (
+ "mozilla.org" => 'mozilla-confidential',
+ "Webtools" => 'webtools-security',
+ "Marketing" => 'marketing-private',
+ "addons.mozilla.org" => 'client-services-security',
+ "AUS" => 'client-services-security',
+ "Mozilla Services" => 'client-services-security',
+ "Mozilla Corporation" => 'mozilla-corporation-confidential',
+ "Mozilla Metrics" => 'metrics-private',
+ "Legal" => 'legal',
+ "Mozilla Messaging" => 'mozilla-messaging-confidential',
+ "Websites" => 'websites-security',
+ "Mozilla Developer Network" => 'websites-security',
+ "support.mozilla.com" => 'websites-security',
+ "quality.mozilla.org" => 'websites-security',
+ "Skywriter" => 'websites-security',
+ "support.mozillamessaging.com" => 'websites-security',
+ "Bugzilla" => 'bugzilla-security',
+ "bugzilla.mozilla.org" => 'bugzilla-security',
+ "Testopia" => 'bugzilla-security',
+ "Tamarin" => 'tamarin-security',
+ "Mozilla PR" => 'pr-private',
+ "_default" => 'core-security'
+);
+
+1;
diff --git a/extensions/BMO/lib/FakeBug.pm b/extensions/BMO/lib/FakeBug.pm
new file mode 100644
index 000000000..5610f5433
--- /dev/null
+++ b/extensions/BMO/lib/FakeBug.pm
@@ -0,0 +1,40 @@
+package Bugzilla::Extension::BMO::FakeBug;
+
+# 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
+
+use Bugzilla::Bug;
+
+our $AUTOLOAD;
+
+sub new {
+ my $class = shift;
+ my $self = shift;
+ bless $self, $class;
+ return $self;
+}
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $name = $AUTOLOAD;
+ $name =~ s/.*://;
+ return exists $self->{$name} ? $self->{$name} : undef;
+}
+
+sub check_can_change_field {
+ my $self = shift;
+ return Bugzilla::Bug::check_can_change_field($self, @_)
+}
+
+sub _changes_everconfirmed {
+ my $self = shift;
+ return Bugzilla::Bug::_changes_everconfirmed($self, @_)
+}
+
+sub everconfirmed {
+ my $self = shift;
+ return ($self->{'status'} == 'UNCONFIRMED') ? 0 : 1;
+}
+
+1;
+
diff --git a/extensions/BMO/lib/Reports.pm b/extensions/BMO/lib/Reports.pm
new file mode 100644
index 000000000..f291e72e7
--- /dev/null
+++ b/extensions/BMO/lib/Reports.pm
@@ -0,0 +1,522 @@
+# -*- 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 BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Byron Jones. Portions created
+# by the Initial Developer are Copyright (C) 2011 the Mozilla Foundation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Byron Jones <glob@mozilla.com>
+
+package Bugzilla::Extension::BMO::Reports;
+use strict;
+
+use Bugzilla::User;
+use Bugzilla::Util qw(trim detaint_natural);
+use Bugzilla::Error;
+use Bugzilla::Constants;
+
+use Date::Parse;
+use DateTime;
+
+use base qw(Exporter);
+
+our @EXPORT_OK = qw(user_activity_report
+ triage_reports
+ group_admins);
+
+sub user_activity_report {
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+
+ my @who = ();
+ my $from = trim($input->{'from'});
+ my $to = trim($input->{'to'});
+
+ if ($input->{'action'} eq 'run') {
+ if ($input->{'who'} eq '') {
+ ThrowUserError('user_activity_missing_username');
+ }
+ Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} });
+
+ ThrowUserError('user_activity_missing_from_date') unless $from;
+ my $from_time = str2time($from)
+ or ThrowUserError('user_activity_invalid_date', { date => $from });
+ my $from_dt = DateTime->from_epoch(epoch => $from_time)
+ ->set_time_zone('local')
+ ->truncate(to => 'day');
+ $from = $from_dt->ymd();
+
+ ThrowUserError('user_activity_missing_to_date') unless $to;
+ my $to_time = str2time($to)
+ or ThrowUserError('user_activity_invalid_date', { date => $to });
+ my $to_dt = DateTime->from_epoch(epoch => $to_time)
+ ->set_time_zone('local')
+ ->truncate(to => 'day');
+ $to = $to_dt->ymd();
+ # add one day to include all activity that happened on the 'to' date
+ $to_dt->add(days => 1);
+
+ my ($activity_joins, $activity_where) = ('', '');
+ my ($attachments_joins, $attachments_where) = ('', '');
+ if (Bugzilla->params->{"insidergroup"}
+ && !Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'}))
+ {
+ $activity_joins = "LEFT JOIN attachments
+ ON attachments.attach_id = bugs_activity.attach_id";
+ $activity_where = "AND COALESCE(attachments.isprivate, 0) = 0";
+ $attachments_where = $activity_where;
+ }
+
+ my @who_bits;
+ foreach my $who (
+ ref $input->{'who'}
+ ? @{$input->{'who'}}
+ : $input->{'who'}
+ ) {
+ push @who, $who;
+ push @who_bits, '?';
+ }
+ my $who_bits = join(',', @who_bits);
+
+ if (!@who) {
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+ my $vars = {};
+ $vars->{'script'} = $cgi->url(-relative => 1);
+ $vars->{'fields'} = {};
+ $vars->{'matches'} = [];
+ $vars->{'matchsuccess'} = 0;
+ $vars->{'matchmultiple'} = 1;
+ print $cgi->header();
+ $template->process("global/confirm-user-match.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
+
+ $from_dt = $from_dt->ymd() . ' 00:00:00';
+ $to_dt = $to_dt->ymd() . ' 23:59:59';
+ my @params;
+ for (1..4) {
+ push @params, @who;
+ push @params, ($from_dt, $to_dt);
+ }
+
+ my $comment_filter = '';
+ if (!Bugzilla->user->is_insider) {
+ $comment_filter = 'AND longdescs.isprivate = 0';
+ }
+
+ my $query = "
+ SELECT
+ fielddefs.name,
+ bugs_activity.bug_id,
+ bugs_activity.attach_id,
+ ".$dbh->sql_date_format('bugs_activity.bug_when', '%Y.%m.%d %H:%i:%s')." AS ts,
+ bugs_activity.removed,
+ bugs_activity.added,
+ profiles.login_name,
+ bugs_activity.comment_id,
+ bugs_activity.bug_when
+ FROM bugs_activity
+ $activity_joins
+ LEFT JOIN fielddefs
+ ON bugs_activity.fieldid = fielddefs.id
+ INNER JOIN profiles
+ ON profiles.userid = bugs_activity.who
+ WHERE profiles.login_name IN ($who_bits)
+ AND bugs_activity.bug_when >= ? AND bugs_activity.bug_when <= ?
+ $activity_where
+
+ UNION ALL
+
+ SELECT
+ 'bug_id' AS name,
+ bugs.bug_id,
+ NULL AS attach_id,
+ ".$dbh->sql_date_format('bugs.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ '(new bug)' AS removed,
+ bugs.short_desc AS added,
+ profiles.login_name,
+ NULL AS comment_id,
+ bugs.creation_ts AS bug_when
+ FROM bugs
+ INNER JOIN profiles
+ ON profiles.userid = bugs.reporter
+ WHERE profiles.login_name IN ($who_bits)
+ AND bugs.creation_ts >= ? AND bugs.creation_ts <= ?
+
+ UNION ALL
+
+ SELECT
+ 'longdesc' AS name,
+ longdescs.bug_id,
+ NULL AS attach_id,
+ DATE_FORMAT(longdescs.bug_when, '%Y.%m.%d %H:%i:%s') AS ts,
+ '' AS removed,
+ '' AS added,
+ profiles.login_name,
+ longdescs.comment_id AS comment_id,
+ longdescs.bug_when
+ FROM longdescs
+ INNER JOIN profiles
+ ON profiles.userid = longdescs.who
+ WHERE profiles.login_name IN ($who_bits)
+ AND longdescs.bug_when >= ? AND longdescs.bug_when <= ?
+ $comment_filter
+
+ UNION ALL
+
+ SELECT
+ 'attachments.filename' AS name,
+ attachments.bug_id,
+ attachments.attach_id,
+ ".$dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ '' AS removed,
+ attachments.description AS added,
+ profiles.login_name,
+ NULL AS comment_id,
+ attachments.creation_ts AS bug_when
+ FROM attachments
+ INNER JOIN profiles
+ ON profiles.userid = attachments.submitter_id
+ WHERE profiles.login_name IN ($who_bits)
+ AND attachments.creation_ts >= ? AND attachments.creation_ts <= ?
+ $attachments_where
+
+ ORDER BY bug_when ";
+
+ my $list = $dbh->selectall_arrayref($query, undef, @params);
+
+ my @operations;
+ my $operation = {};
+ my $changes = [];
+ my $incomplete_data = 0;
+
+ foreach my $entry (@$list) {
+ my ($fieldname, $bugid, $attachid, $when, $removed, $added, $who,
+ $comment_id) = @$entry;
+ my %change;
+ my $activity_visible = 1;
+
+ next unless Bugzilla->user->can_see_bug($bugid);
+
+ # check if the user should see this field's activity
+ if ($fieldname eq 'remaining_time'
+ || $fieldname eq 'estimated_time'
+ || $fieldname eq 'work_time'
+ || $fieldname eq 'deadline')
+ {
+ $activity_visible = Bugzilla->user->is_timetracker;
+ }
+ elsif ($fieldname eq 'longdescs.isprivate'
+ && !Bugzilla->user->is_insider
+ && $added)
+ {
+ $activity_visible = 0;
+ }
+ else {
+ $activity_visible = 1;
+ }
+
+ if ($activity_visible) {
+ # Check for the results of an old Bugzilla data corruption bug
+ if (($added eq '?' && $removed eq '?')
+ || ($added =~ /^\? / || $removed =~ /^\? /)) {
+ $incomplete_data = 1;
+ }
+
+ # An operation, done by 'who' at time 'when', has a number of
+ # 'changes' associated with it.
+ # If this is the start of a new operation, store the data from the
+ # previous one, and set up the new one.
+ if ($operation->{'who'}
+ && ($who ne $operation->{'who'}
+ || $when ne $operation->{'when'}))
+ {
+ $operation->{'changes'} = $changes;
+ push (@operations, $operation);
+ $operation = {};
+ $changes = [];
+ }
+
+ $operation->{'bug'} = $bugid;
+ $operation->{'who'} = $who;
+ $operation->{'when'} = $when;
+
+ $change{'fieldname'} = $fieldname;
+ $change{'attachid'} = $attachid;
+ $change{'removed'} = $removed;
+ $change{'added'} = $added;
+
+ if ($comment_id) {
+ $change{'comment'} = Bugzilla::Comment->new($comment_id);
+ next if $change{'comment'}->count == 0;
+ }
+
+ push (@$changes, \%change);
+ }
+ }
+
+ if ($operation->{'who'}) {
+ $operation->{'changes'} = $changes;
+ push (@operations, $operation);
+ }
+
+ $vars->{'incomplete_data'} = $incomplete_data;
+ $vars->{'operations'} = \@operations;
+
+ } else {
+
+ if ($from eq '') {
+ my ($yy, $mm) = (localtime)[5, 4];
+ $from = sprintf("%4d-%02d-01", $yy + 1900, $mm + 1);
+ }
+ if ($to eq '') {
+ my ($yy, $mm, $dd) = (localtime)[5, 4, 3];
+ $to = sprintf("%4d-%02d-%02d", $yy + 1900, $mm + 1, $dd);
+ }
+ }
+
+ $vars->{'action'} = $input->{'action'};
+ $vars->{'who'} = join(',', @who);
+ $vars->{'from'} = $from;
+ $vars->{'to'} = $to;
+}
+
+sub triage_reports {
+ my ($vars, $filter) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ if ($input->{'action'} eq 'run' && $input->{'product'}) {
+
+ # load product and components from input
+
+ 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 })
+ || ThrowUserError('invalid_object', { object => 'Component', value => $component_name });
+ push @component_ids, $component->id;
+ }
+ }
+
+ # determine which comment filters to run
+
+ 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'} })
+ || ThrowUserError('invalid_object', { object => 'User', value => $input->{'commenter_is'} });
+ $filter_commenter_id = $user ? $user->id : 0;
+ }
+
+ my $filter_last_time;
+ if ($filter_last) {
+ if ($filter_last_period eq 'is') {
+ $filter_last_period = -1;
+ $filter_last_time = str2time($input->{'last_is'} . " 00:00:00") || 0;
+ } else {
+ detaint_natural($filter_last_period);
+ $filter_last_period = 14 if $filter_last_period < 14;
+ }
+ }
+
+ # form sql queries
+
+ my $now = (time);
+ my $bugs_sql = "
+ SELECT bug_id, short_desc, reporter, creation_ts
+ FROM bugs
+ WHERE product_id = ?
+ AND bug_status = 'UNCONFIRMED'";
+ if (@component_ids) {
+ $bugs_sql .= " AND component_id IN (" . join(',', @component_ids) . ")";
+ }
+ $bugs_sql .= "
+ ORDER BY creation_ts
+ ";
+
+ my $comment_count_sql = "
+ SELECT COUNT(*)
+ FROM longdescs
+ WHERE bug_id = ?
+ ";
+
+ my $comment_sql = "
+ SELECT who, bug_when, type, thetext, extra_data
+ FROM longdescs
+ WHERE bug_id = ?
+ ";
+ if (!Bugzilla->user->is_insider) {
+ $comment_sql .= " AND isprivate = 0 ";
+ }
+ $comment_sql .= "
+ ORDER BY bug_when DESC
+ LIMIT 1
+ ";
+
+ my $attach_sql = "
+ SELECT description, isprivate
+ FROM attachments
+ WHERE attach_id = ?
+ ";
+
+ # work on an initial list of bugs
+
+ my $list = $dbh->selectall_arrayref($bugs_sql, undef, $product->id);
+ my @bugs;
+
+ foreach my $entry (@$list) {
+ my ($bug_id, $summary, $reporter_id, $creation_ts) = @$entry;
+
+ next unless $user->can_see_bug($bug_id);
+
+ # get last comment information
+
+ my ($comment_count) = $dbh->selectrow_array($comment_count_sql, undef, $bug_id);
+ my ($commenter_id, $comment_ts, $type, $comment, $extra)
+ = $dbh->selectrow_array($comment_sql, undef, $bug_id);
+ my $commenter = 0;
+
+ # apply selected filters
+
+ if ($filter_commenter) {
+ next if $comment_count <= 1;
+
+ if ($filter_commenter_on eq 'reporter') {
+ next if $commenter_id != $reporter_id;
+
+ } elsif ($filter_commenter_on eq 'noconfirm') {
+ $commenter = Bugzilla::User->new($commenter_id);
+ next if $commenter_id != $reporter_id
+ || $commenter->in_group('canconfirm');
+
+ } elsif ($filter_commenter_on eq 'is') {
+ next if $commenter_id != $filter_commenter_id;
+ }
+ } else {
+ $input->{'commenter'} = '';
+ $input->{'commenter_is'} = '';
+ }
+
+ if ($filter_last) {
+ my $comment_time = str2time($comment_ts)
+ or next;
+ if ($filter_last_period == -1) {
+ next if $comment_time >= $filter_last_time;
+ } else {
+ next if $now - $comment_time <= 60 * 60 * 24 * $filter_last_period;
+ }
+ } else {
+ $input->{'last'} = '';
+ $input->{'last_is'} = '';
+ }
+
+ # get data for attachment comments
+
+ if ($comment eq '' && $type == CMT_ATTACHMENT_CREATED) {
+ my ($description, $is_private) = $dbh->selectrow_array($attach_sql, undef, $extra);
+ next if $is_private && !Bugzilla->user->is_insider;
+ $comment = "(Attachment) " . $description;
+ }
+
+ # truncate long comments
+
+ if (length($comment) > 80) {
+ $comment = substr($comment, 0, 80) . '...';
+ }
+
+ # build bug hash for template
+
+ my $bug = {};
+ $bug->{id} = $bug_id;
+ $bug->{summary} = $summary;
+ $bug->{reporter} = Bugzilla::User->new($reporter_id);
+ $bug->{creation_ts} = $creation_ts;
+ $bug->{commenter} = $commenter || Bugzilla::User->new($commenter_id);
+ $bug->{comment_ts} = $comment_ts;
+ $bug->{comment} = $comment;
+ $bug->{comment_count} = $comment_count;
+ push @bugs, $bug;
+ }
+
+ @bugs = sort { $b->{comment_ts} cmp $a->{comment_ts} } @bugs;
+
+ $vars->{bugs} = \@bugs;
+ } else {
+ $input->{action} = '';
+ }
+
+ if (!$input->{filter_commenter} && !$input->{filter_last}) {
+ $input->{filter_commenter} = 1;
+ }
+
+ $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/lib/WebService.pm b/extensions/BMO/lib/WebService.pm
new file mode 100644
index 000000000..95bdcbdf3
--- /dev/null
+++ b/extensions/BMO/lib/WebService.pm
@@ -0,0 +1,207 @@
+# -*- 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 BMO Bugzilla Extension.
+#
+# The Initial Developer of the Original Code is Mozilla Foundation. Portions created
+# by the Initial Developer are Copyright (C) 2011 the Mozilla Foundation. All
+# Rights Reserved.
+#
+# Contributor(s):
+# Dave Lawrence <dkl@mozilla.com>
+
+package Bugzilla::Extension::BMO::WebService;
+
+use strict;
+use warnings;
+
+use base qw(Bugzilla::WebService);
+
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::WebService::Util qw(validate);
+use Bugzilla::Field;
+
+sub getBugsConfirmer {
+ my ($self, $params) = validate(@_, 'names');
+ my $dbh = Bugzilla->dbh;
+
+ defined($params->{names})
+ || ThrowCodeError('params_required',
+ { function => 'BMO.getBugsConfirmer', params => ['names'] });
+
+ my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} };
+
+ # start filtering to remove duplicate user ids
+ @user_objects = values %{{ map { $_->id => $_ } @user_objects }};
+
+ my $fieldid = get_field_id('bug_status');
+
+ my $query = "SELECT DISTINCT bugs_activity.bug_id
+ FROM bugs_activity
+ LEFT JOIN bug_group_map
+ ON bugs_activity.bug_id = bug_group_map.bug_id
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.added = 'NEW'
+ AND bugs_activity.removed = 'UNCONFIRMED'
+ AND bugs_activity.who = ?
+ AND bug_group_map.bug_id IS NULL
+ ORDER BY bugs_activity.bug_id";
+
+ my %users;
+ foreach my $user (@user_objects) {
+ my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id);
+ $users{$user->login} = $bugs;
+ }
+
+ return \%users;
+}
+
+sub getBugsVerifier {
+ my ($self, $params) = validate(@_, 'names');
+ my $dbh = Bugzilla->dbh;
+
+ defined($params->{names})
+ || ThrowCodeError('params_required',
+ { function => 'BMO.getBugsVerifier', params => ['names'] });
+
+ my @user_objects = map { Bugzilla::User->check($_) } @{ $params->{names} };
+
+ # start filtering to remove duplicate user ids
+ @user_objects = values %{{ map { $_->id => $_ } @user_objects }};
+
+ my $fieldid = get_field_id('bug_status');
+
+ my $query = "SELECT DISTINCT bugs_activity.bug_id
+ FROM bugs_activity
+ LEFT JOIN bug_group_map
+ ON bugs_activity.bug_id = bug_group_map.bug_id
+ WHERE bugs_activity.fieldid = ?
+ AND bugs_activity.removed = 'RESOLVED'
+ AND bugs_activity.added = 'VERIFIED'
+ AND bugs_activity.who = ?
+ AND bug_group_map.bug_id IS NULL
+ ORDER BY bugs_activity.bug_id";
+
+ my %users;
+ foreach my $user (@user_objects) {
+ my $bugs = $dbh->selectcol_arrayref($query, undef, $fieldid, $user->id);
+ $users{$user->login} = $bugs;
+ }
+
+ return \%users;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bugzilla::Extension::BMO::Webservice - The BMO WebServices API
+
+=head1 DESCRIPTION
+
+This module contains API methods that are useful to user's of bugzilla.mozilla.org.
+
+=head1 METHODS
+
+See L<Bugzilla::WebService> for a description of how parameters are passed,
+and what B<STABLE>, B<UNSTABLE>, and B<EXPERIMENTAL> mean.
+
+=head2 getBugsConfirmer
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+This method returns public bug ids that a given user has confirmed (changed from
+C<UNCONFIRMED> to C<NEW>).
+
+=item B<Params>
+
+You pass a field called C<names> that is a list of Bugzilla login names to find bugs for.
+
+=over
+
+=item C<names> (array) - An array of strings representing Bugzilla login names.
+
+=back
+
+=item B<Returns>
+
+=over
+
+A hash of Bugzilla login names. Each name points to an array of bug ids that the user has confirmed.
+
+=back
+
+=item B<Errors>
+
+=over
+
+=back
+
+=item B<History>
+
+=over
+
+=item Added in BMO Bugzilla B<4.0>.
+
+=back
+
+=back
+
+=head2 getBugsVerifier
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+This method returns public bug ids that a given user has verified (changed from
+C<RESOLVED> to C<VERIFIED>).
+
+=item B<Params>
+
+You pass a field called C<names> that is a list of Bugzilla login names to find bugs for.
+
+=over
+
+=item C<names> (array) - An array of strings representing Bugzilla login names.
+
+=back
+
+=item B<Returns>
+
+=over
+
+A hash of Bugzilla login names. Each name points to an array of bug ids that the user has verified.
+
+=back
+
+=item B<Errors>
+
+=over
+
+=back
+
+=item B<History>
+
+=over
+
+=item Added in BMO Bugzilla B<4.0>.
+
+=back
+
+=back
diff --git a/extensions/BMO/template/en/default/account/create.html.tmpl b/extensions/BMO/template/en/default/account/create.html.tmpl
new file mode 100644
index 000000000..47355cf00
--- /dev/null
+++ b/extensions/BMO/template/en/default/account/create.html.tmpl
@@ -0,0 +1,181 @@
+[%# 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 <gerv@gerv.net>
+ # Byron Jones <glob@mozilla.com>
+ #%]
+
+[%# INTERFACE
+ # none
+ #
+ # Param("maintainer") is used to display the maintainer's email.
+ # Param("emailsuffix") is used to pre-fill the email field.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% title = BLOCK %]
+ Create a new [% terms.Bugzilla %] account
+[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = title
+ style_urls = [ 'extensions/BMO/web/styles/create_account.css' ]
+%]
+
+<script type="text/javascript">
+function onSubmit() {
+ var email = document.getElementById('login').value;
+ if (email == '') {
+ alert('You must enter your email address.');
+ return false;
+ }
+ var isValid =
+ email.match(/@/)
+ && email.match(/@.+\./)
+ && !email.match(/\.$/)
+ && !email.match(/[\\()&<>,'"\[\]]/)
+ ;
+ if (!isValid) {
+ alert(
+ "The e-mail address doesn't pass our syntax checking for a legal " +
+ "email address.\n\nA legal address must contain exactly one '@', and " +
+ "at least one '.' after the @.\n\nIt must also not contain any of " +
+ "these special characters: \ ( ) & < > , ; : \" [ ], or any whitespace."
+ );
+ return false;
+ }
+ return true;
+}
+</script>
+
+<table border="0" id="create-account">
+<tr>
+
+<td width="50%" id="create-account-left" valign="top">
+
+ <h2 class="column-header">I need help using a Mozilla Product</h2>
+
+ <table border="0" id="product-list">
+ [% INCLUDE product
+ icon = "firefox"
+ name = "Firefox Support"
+ url = "http://support.mozilla.com/"
+ desc = "Support for the Firefox web browser."
+ %]
+ [% INCLUDE product
+ icon = "firefox"
+ name = "Firefox for Mobile Support"
+ url = "http://support.mozilla.com/mobile"
+ desc = "Support for the Firefox Mobile web browser."
+ %]
+ [% INCLUDE product
+ icon = "thunderbird"
+ name = "Thunderbird Support"
+ url = "http://www.mozillamessaging.com/support/"
+ desc = "Support for Thunderbird email client."
+ %]
+ [% INCLUDE product
+ icon = "other"
+ name = "Support for other products"
+ url = "http://www.mozilla.org/support/"
+ desc = "Support for products not listed here."
+ %]
+ [% INCLUDE product
+ icon = "input"
+ name = "Feedback"
+ url = "http://input.mozilla.com/feedback"
+ desc = "Report issues with web site you use, or provide quick feedback for Firefox."
+ %]
+ [% INCLUDE product
+ icon = "idea"
+ name = "Ideas"
+ url = "http://input.mozilla.com/idea"
+ desc = "Offer us ideas on how to enhance Firefox."
+ %]
+ </table>
+
+</td>
+
+<td width="50%" id="create-account-right" valign="top">
+
+ <h2 class="column-header">I want to help</h2>
+
+ <div id="right-blurb">
+ <p>
+ Great! There are three things to know and do:
+ </p>
+ <ol>
+ <li>
+ Please consider reading our
+ <a href="https://developer.mozilla.org/en/Bug_writing_guidelines" target="_blank">bug writing guidelines</a>.
+ </li>
+ <li>
+ 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
+ <a href="http://email.about.com/od/freeemailreviews/tp/free_email.htm" target="_blank">alternative email address</a>
+ for this reason.
+ </li>
+ <li>
+ 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 bugs and helping fix them.
+ </li>
+ </ol>
+ </div>
+
+ <h2 class="column-header">Create an account</h2>
+
+ <form method="post" action="createaccount.cgi" onsubmit="return onSubmit()">
+ <table id="create-account-form">
+ <tr>
+ <td class="label">Email Address:</td>
+ <td>
+ <input size="35" id="login" name="login" placeholder="you@example.com">[% Param('emailsuffix') FILTER html %]</td>
+ <td>
+ <input type="submit" value="Create Account">
+ </td>
+ </tr>
+ </table>
+ </form>
+
+</td>
+
+</tr>
+</table>
+
+<p id="bmo-admin">
+ If you think there's something wrong with Bugzilla, you can
+ <a href="mailto:bugzilla-admin@mozilla.org">send an email to the admins</a>, but
+ remember, they can't file bugs for you, or solve tech support problems.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK product %]
+ <tr>
+ <td valign="top">
+ <a href="[% url FILTER none %]"><img
+ src="extensions/BMO/web/producticons/[% icon FILTER uri %].png"
+ border="0" width="64" height="64"></a>
+ </td>
+ <td valign="top">
+ <h2><a href="[% url FILTER none %]">[% name FILTER html %]</a></h2>
+ <div>[% desc FILTER html %]</div>
+ </td>
+ </tr>
+[% END %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl
new file mode 100644
index 000000000..216f2c53a
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-mktgevent.txt.tmpl
@@ -0,0 +1,48 @@
+[%# 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 <gerv@gerv.net>
+ #%]
+[%# 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: [% cgi.param('firstname') %] [%+ cgi.param('lastname') %]
+Email: [% cgi.param('email') %]
+Event Name: [% cgi.param('eventname') %]
+Event Date: [% cgi.param("date") %]
+Event Location: [% cgi.param("locations") %]
+Event Website: [% cgi.param("website") %]
+Event Description and Objectives:
+[%+ cgi.param("goals") %]
+
+Attendees: [% IF cgi.param('attendees') != "--Please Select--" %][% cgi.param('attendees') %][% END %]
+Target Audience: [% IF cgi.param('audience') != "--Please Select--" %][% cgi.param('audience') %][% END %]
+
+We'll be doing: [% cgi.param("doing").join(", ") %][% IF cgi.param('doing-other-what') %]: [% cgi.param('doing-other-what') %][% END %]
+
+Success will be measured by:
+[%+ cgi.param('successmeasure') %]
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl
new file mode 100644
index 000000000..c62461d42
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-mozlist.txt.tmpl
@@ -0,0 +1,44 @@
+[%# 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 <gerv@gerv.net>
+ #%]
+[%# 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 %]
+List Name: [% cgi.param("listName") %]
+List Admin: [% cgi.param("listAdmin") %]
+
+Short Description:
+[%+ cgi.param("listShortDesc") %]
+
+[% IF cgi.param("listType") != "mozilla.com" %]
+Long Description:
+[%+ cgi.param("listLongDesc") %]
+[% END %]
+
+Justification / Special Instructions:
+
+[%+ cgi.param("comment") IF cgi.param("comment") %]
+
diff --git a/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl
new file mode 100644
index 000000000..0ec7687d4
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/comment-swag.txt.tmpl
@@ -0,0 +1,48 @@
+[%# 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 <gerv@gerv.net>
+ #%]
+[%# 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: [% cgi.param('firstname') %] [% cgi.param('lastname') %]
+Email: [% cgi.param('email') %]
+
+Additional Swag: [% cgi.param("additional") %]
+
+Ship to:
+[%+ 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 %]
+
+Additional comments:
+
+[%+ 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
new file mode 100644
index 000000000..e4c6cabfb
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-brownbag.html.tmpl
@@ -0,0 +1,221 @@
+[%# 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 <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation Brownbag Requests"
+ style_urls = [ 'skins/standard/attachment.css', 'skins/custom/calendar.css' ]
+ style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }"
+ javascript_urls = [ 'js/attachment.js', 'js/field.js', 'js/util.js' ]
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+[% USE Bugzilla %]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Brownbag Request</div>
+
+<p><strong>Brownbag Request:</strong> Please use this form if you plan on hosting a brownbag so that IT will be able to properly provide support. </p>
+
+<p>Process:</p>
+
+<ol><li>Complete and submit request below.</li>
+ <li>Your request will be reviewed and assigned to the appropriate person in IT.</li>
+</ol>
+
+<p>These requests will only be visible internally in all cases and only to the
+person who submitted the request and any persons designated in the CC line.</p>
+
+<script type="text/javascript">
+function trySubmit() {
+ var out = 'Topic: the_topic\r\nPresenter: the_presenter\r\nDate: the_date\r\nTime: the_time\r\nAudience: the_audience\r\nAir Mozilla: air_mozilla\r\nDial-in: dial_in\r\nArchive: to_archive\r\nMember of IT to help with A/V: it_help\r\nDescription: the_description';
+
+ var topic = document.getElementById('topic').value;
+ var presenter = document.getElementById('presenter').value;
+ var date = document.getElementById('date').value;
+ var time = document.getElementById('time_hour').value + ':' + document.getElementById('time_minute').value + document.getElementById('ampm').value;
+ var shortdesc = 'Brownbag Request - ' + topic + ' (' + date + ' ' + time + ')';
+ var airmozilla = document.getElementById('airmozilla').checked? 'yes' : 'no';
+ var dialin = document.getElementById('dialin').checked? 'yes' : 'no';
+ var archive = document.getElementById('archive').checked? 'yes' : 'no';
+ var ithelp = document.getElementById('ithelp').checked? 'yes' : 'no';
+
+ out = out.replace( /the_topic/, topic );
+ out = out.replace( /the_presenter/, presenter );
+ out = out.replace( /the_date/, date);
+ out = out.replace( /the_time/, time);
+ out = out.replace( /the_audience/, document.getElementById('audience').value );
+ out = out.replace( /air_mozilla/, airmozilla);
+ out = out.replace( /dial_in/, dialin);
+ out = out.replace( /the_description/, document.getElementById('description').value );
+ out = out.replace( /to_archive/, archive);
+ out = out.replace( /it_help/, ithelp);
+
+ document.getElementById('comment').value = out;
+ document.getElementById('short_desc').value = shortdesc;
+
+ return true;
+}
+
+</script>
+
+<form method="post" action="post_bug.cgi" id="brownbagRequestForm" enctype="multipart/form-data"
+ onSubmit="return trySubmit();">
+
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="component" value="Server Operations: Desktop Issues">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="comment" id="comment" value="">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+<table>
+
+<tr>
+ <td align="right"><strong>Presenter:</strong></td>
+ <td>
+ <input type="text" name="presenter" id="presenter" value="" size="60" />
+ </td>
+
+</tr>
+
+<tr>
+ <td align="right"><strong>Topic:</strong></td>
+ <td>
+ <input type="text" name="topic" id="topic" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Date:</strong></td>
+ <td>
+ <input type="text" name="date" size="10" id="date"
+ align="right" value="" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date"
+ onclick="showCalendar('date')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_date"></div>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Start Time:</strong></td>
+ <td>
+ <select name="time_hour" id="time_hour">
+ <option value="12" selected>12</option>
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ </select>:<select name="time_minute" id="time_minute">
+ <option value="00" selected>00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+ </select>
+ <select name="ampm" id="ampm">
+ <option value="AM" selected>AM</option>
+ <option value="PM">PM</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Intended Audience:</strong></td>
+ <td>
+ <select name="audience" id="audience">
+ <option value="Public" selected>Open to Public</option>
+ <option value="Employees Only">Employees Only</option>
+ <option value="Interns">Interns</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Air Mozilla Broadcasting?</strong></td>
+ <td align="left"><input type="checkbox" name="airmozilla" id="airmozilla"></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Dial In?</strong></td>
+ <td align="left"><input type="checkbox" name="dialin" id="dialin"></td>
+</tr>
+
+<tr>
+<td align="right"><strong>Archive this?</strong></td>
+<td align="left"><input type="checkbox" name="archive" id="archive" value="yes"></td>
+</tr>
+
+
+<tr>
+<td align="right"><strong>Need IT to help run A/V?</strong></td>
+<td align="left"><input type="checkbox" name="ithelp" id="ithelp" value="yes" checked></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <th><label for="description">Description</label>:</th>
+ <td>
+ <em>Please briefly describe the brownbag and any specific needs you might have.</em><br>
+
+ <textarea id="description" name="description" rows="10" cols="80"></textarea>
+ </td>
+</tr>
+
+ </table>
+
+ <br>
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+
+</p>
+
+<script type="text/javascript">
+ createCalendar('date');
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
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
new file mode 100644
index 000000000..08207fd8c
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-itrequest.html.tmpl
@@ -0,0 +1,187 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation/Foundation IT Requests"
+ javascript_urls = [ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+[% USE Bugzilla %]
+
+<p><strong>Please use this form for IT requests only!</strong></p>
+<p>If you have a bug to file, go <a href="enter_bug.cgi">here</a>.</p>
+
+<form method="post" action="post_bug.cgi" id="itRequestForm" enctype="multipart/form-data">
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <script type="text/javascript">
+ <!--
+ function setsevdesc(theSelect) {
+ var theValue = theSelect.options[theSelect.selectedIndex].value;
+ if (theValue == 'blocker') {
+ document.getElementById('blockerdesc').style.display = 'block';
+ document.getElementById('critdesc').style.display = 'none';
+ } else if (theValue == 'critical') {
+ document.getElementById('blockerdesc').style.display = 'none';
+ document.getElementById('critdesc').style.display = 'block';
+ } else {
+ document.getElementById('blockerdesc').style.display = 'none';
+ document.getElementById('critdesc').style.display = 'none';
+ }
+ }
+ var compdesc = new Array();
+ [% FOREACH comp IN product.components %]
+ compdesc['[% comp.name FILTER js %]'] = '[% comp.description FILTER js %]';
+ [% END %]
+ compdesc['invalid'] = '';
+ function setcompdesc(theRadio) {
+ var theValue = theRadio.value;
+ document.getElementById('compdescription').innerHTML = compdesc[theValue];
+ }
+ // -->
+ </script>
+ <table>
+ <tr>
+
+ <td align="right">
+ <strong>Urgency:</strong>
+ </td>
+
+ <td>
+ <select id="bug_severity" name="bug_severity" onchange="setsevdesc(this)">
+ <option value="blocker">All work for IT stops until this is done</option>
+ <option value="critical">IT should work on it soon as possible (urgent)</option>
+ <option value="major">IT should get to it within 24 hours</option>
+ <option value="normal">IT should get to it within the next week</option>
+ <option value="minor" selected="selected">No rush, but hopefully IT can get to it soon</option>
+ <option value="trivial">Whenever IT can get around to it</option>
+ <option value="enhancement">This is just an idea, filing it so we don't forget</option>
+ </select>
+ </td>
+ <td>
+ <div id="blockerdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 30 minutes.</div>
+ <div id="critdesc" style="color:red;display:none">This will page the on-call sysadmin if not handled within 8 hours.</div>
+ </td>
+
+ </tr>
+ <tr>
+ <td align="right"><strong>Request Type:</strong></td>
+ <td style="white-space: nowrap;">
+ <input type="radio" name="component" id="componentac" onclick="setcompdesc(this)" value="Server Operations: Account Requests">
+ <label for="componentac">Request an LDAP/E-mail/etc. account</label><br>
+ <input type="radio" name="component" id="componentmvd" onclick="setcompdesc(this)" value="Server Operations: Desktop Issues">
+ <label for="componentmvd">Desktop/Laptop/Printer/Phone/Tablet/License problem/order/request</label><br>
+ <input type="radio" name="component" id="componenttbm" onclick="setcompdesc(this)" value="Server Operations: RelEng">
+ <label for="componenttbm">Report a problem with a tinderbox machine</label><br>
+ <input type="radio" name="component" id="componentwcp" onclick="setcompdesc(this)" value="Server Operations: Web Operations">
+ <label for="componentwcp">Report a problem with a Mozilla website, or to request a change or push</label><br>
+ <input type="radio" name="component" id="componentacl" onclick="setcompdesc(this)" value="Server Operations: ACL Request">
+ <label for="componentacl">Request a firewall change</label><br>
+ <input type="radio" name="component" id="componentso" onclick="setcompdesc(this)" value="Server Operations">
+ <label for="componentso">Any other issue</label><br>
+ Mailing list requests should be filed <a href="[% ulrbase FILTER none %]enter_bug.cgi?product=mozilla.org&format=mozlist">here</a> instead.
+ </td>
+ <td id="compdescription" align="left" style="color: green; padding-left: 1em">
+ </td>
+ <tr>
+ <td align="right"><strong>Summary:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Description:</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td colspan="4">&nbsp;</td></tr>
+
+ <tr>
+ <td colspan="4">
+ <strong>Attachment&nbsp;(optional):</strong>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">File:</td>
+ <td colspan="3">
+ <em>Enter the path to the file on your computer.</em><br>
+ <input type="file" id="data" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect" />
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right">Description:</td>
+ <td colspan="3">
+ <em>Describe the attachment briefly.</em><br>
+ <input type="text" id="description" name="description" size="60" maxlength="200">
+ </td>
+ </tr>
+ </table>
+
+ <br>
+ <!-- infra bugs -->
+ <input type="checkbox" name="groups" id="groups" value="infra" checked="checked"><label for="groups"><strong>This is an internal issue which should not be publicly visible.</strong></label><br>(please uncheck this box if it isn't)
+ <br><br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your
+ request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl
new file mode 100644
index 000000000..c690370fe
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-legal.html.tmpl
@@ -0,0 +1,216 @@
+[%# 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): Mark Smith <mark@mozilla.com>
+ # Reed Loden <reed@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation Legal Requests"
+ style_urls = [ 'skins/standard/attachment.css' ]
+ javascript_urls = [ 'js/attachment.js', 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+[% IF user.in_group("mozilla-corporation-confidential")
+ OR user.in_group("mozilla-messaging-confidential") %]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>MoLegal</div>
+
+<p><strong>Welcome to MoLegal.</strong> If you need legal assistance please complete the form below. To best service
+your request, it is essential that you give us complete information so we can respond
+properly and in a timely fashion. Please use this form only for requests for legal
+assistance related to the Mozilla Corporation. If you’ve been arrested, do not use
+this form or contact us.</p>
+
+<p>Process:</p>
+
+<ol><li>Complete and submit request below.</li>
+ <li>Your request will be reviewed and assigned to the appropriate legal service provider as necessary.</li>
+ <li>We will contact you to confirm receipt, gather any additional information, and agree on a completion timeline.</li>
+</ol>
+
+<p>These requests will only be visible internally and in all cases and only to the
+person who submitted the request and any persons designated in the CC line.</p>
+
+<p><strong>All Submissions, And Information Provided In Response To This Request,
+Are Confidential And Subject To The Attorney-Client Privilege And Work Product Doctrine.</strong></p>
+
+<script type="text/javascript">
+function trySubmit() {
+ var out = 'description\r\n\r\n--- First Response:\r\nfirst_response\r\n\r\n--- First Response Timeframe:\r\nfirst_resp_time\r\n\r\n' +
+ '--- Business Objective:\r\nbusiness_objective\r\n\r\n--- Other Party:\r\nother_party';
+
+ out = out.replace( /description/, document.getElementById('ncomment').value );
+ out = out.replace( /first_response/, document.getElementById('firstresp').value );
+ out = out.replace( /first_resp_time/, document.getElementById('firstrespwhen').value );
+ out = out.replace( /business_objective/, document.getElementById('busobj').value );
+ out = out.replace( /other_party/, document.getElementById('otherparty').value );
+
+ document.getElementById('comment').value = out;
+
+ return true;
+}
+</script>
+
+<form method="post" action="post_bug.cgi" id="legalRequestForm" enctype="multipart/form-data"
+ onSubmit="return trySubmit();">
+
+ <input type="hidden" name="product" value="Legal">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+<input type="hidden" name="comment" id="comment" value="">
+
+<table>
+
+<tr>
+ <td align="right"><strong>Request Type:</strong></td>
+ <td>
+ <select name="component">
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ [% " selected=\"selected\"" IF c.name == "General" %]>
+ [% c.name FILTER html -%]
+ </option>
+ [%- END %]
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right">
+ <strong>Urgency: </strong>
+ </td>
+ <td>
+ <select id="bug_severity" name="bug_severity">
+ <option value="blocker">Immediately - Don't leave the office, don't sleep until this is done (use with caution!)</option>
+ <option value="critical">A few days timeframe - critical priority</option>
+ <option value="major">One week timeframe - high priority</option>
+ <option value="normal">Two weeks timeframe - medium priority</option>
+ <option value="minor" selected="selected">One month timeframe - low priority</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>First Response:</strong></td>
+ <td>
+<em>If your request is a project with numerous milestones or stages, please describe the first task you would like to see completed.</em><br>
+ <textarea id="firstresp" name="firstresp" cols="80" rows="3"></textarea><br />
+ <select id="firstrespwhen" name="firstrespwhen">
+ <option value="24 hours">Urgent! Please do this within 24 hours!</option>
+ <option value="Few days">Important, but I can wait a few days for this.</option>
+ <option value="One week">Sometime within the next week is fine.</option>
+ <option value="Few weeks" selected="selected">Anytime in the next few weeks would be acceptable.</option>
+ </select>
+ </td>
+</tr>
+
+ <tr>
+ <td align="right"><strong>Summary:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+
+<tr>
+ <td align="right"><strong>Name of Other Party:</strong></td>
+ <td>
+<em>If applicable, include full legal entity name, address, and any other relevant contact information.</em><br>
+ <textarea id="otherparty" name="otherparty" rows="3" cols="80"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Business Objective:</strong></td>
+ <td>
+ <input type="text" name="busobj" id="busobj" value="" size="60" />
+ </td>
+</tr>
+
+ <tr><td align="right" valign="top"><strong>Description:</strong></td>
+ <td colspan="3">
+<em>Describe your question, what you want and/or provide any relevant deal terms, restrictions, or provisions that are applicable.</em>
+ <textarea id="ncomment" name="ncomment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+
+<tr><td colspan=3><br><br></td></tr>
+<tr><td></td><td colspan=2 style='background-color: #ddd;'><strong>Attachment (this is optional)</strong></td></tr>
+
+<tr>
+ <th><label for="data">File</label>:</th>
+ <td>
+ <em>Enter the path to the file on your computer.</em><br>
+ <input type="file" id="data" name="data" size="50">
+ <input type="hidden" name="contenttypemethod" value="autodetect" />
+ </td>
+</tr>
+<tr>
+ <th><label for="description">Description</label>:</th>
+ <td>
+ <em>Describe the attachment briefly.</em><br>
+ <input type="text" id="description" name="description" size="60" maxlength="200">
+ </td>
+</tr>
+
+ </table>
+
+ <br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+</p>
+
+[% ELSE %]
+
+<p>Sorry, you do not have access to this page.</p>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
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
new file mode 100644
index 000000000..d6b6c188f
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mktgevent.html.tmpl
@@ -0,0 +1,250 @@
+[%# 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 <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Event Request Form"
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js',
+ 'js/util.js' ]
+ style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }"
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Event Request Form</div>
+
+<p><strong>Event Request:</strong> Please use this form to file a request for an event. <b>This form is not a request for swag.</b></p>
+
+<p>Process:</p>
+
+<ol>
+ <li>Complete and submit request below.</li>
+ <li>Your request will be reviewed by the appropriate person in the Engagement team.</li>
+</ol>
+
+<p>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
+Engagement team.</p>
+
+<script language="javascript" type="text/javascript">
+function trySubmit() {
+
+ var date = document.getElementById('date').value;
+ var eventname = document.getElementById('eventname').value;
+ var shortdesc = 'Event Request (' + date + ') - ' + eventname;
+ document.getElementById('short_desc').value = shortdesc;
+ if(!isChecked('doing-other')) document.getElementById('doing-other-what').value = '';
+ return true;
+}
+
+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(!isValidEmail(document.getElementById('email').value)) alert_text += "Please enter a valid email address\n";
+ if(!isFilledOut('eventname')) alert_text += "Please enter an event name.\n";
+ if(!isFilledOut('website')) alert_text += "Please enter an event website.\n";
+ if(!isFilledOut('goals')) alert_text += "Please enter the Description and Objectives.\n";
+ if(!isFilledOut('date')) alert_text += "Please enter an event date.\n";
+ if(!isFilledOut('goals')) alert_text += "Please enter the event goals.\n";
+ if(!isFilledOut('successmeasure')) alert_text += "Please enter how you will measure the success of the event.\n";
+
+ if(!isChecked('doing-booth') &&
+ !isChecked('doing-speaking') &&
+ !isChecked('doing-outreach') &&
+ !isChecked('doing-other')
+ ) alert_text += "Please indicate what you'll be doing at the event.\n";
+ if(isChecked('doing-other') && !isFilledOut('doing-other-what')) alert_text += "Please describe what 'other' thing you'll be doing at the event.\n";
+
+ //Everything required is filled out..try to submit the form!
+ if(alert_text == '') {
+ return trySubmit();
+ }
+
+ //alert text, stay here on the pagee
+ alert(alert_text);
+ return false;
+}
+
+</script>
+
+<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+
+ <input type="hidden" name="format" value="mktgevent">
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Event Requests">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+<table>
+
+<tr>
+ <td align="right"><strong>First Name: <span style="color: red;">*</span></strong></td>
+ <td align="left">
+ <input type="text" name="firstname" id="firstname" value="" size="20" maxlength="20" />
+ </td>
+</tr>
+<tr>
+ <td align="right"><strong>Last Name: <span style="color: red;">*</span></strong></td>
+ <td align="left">
+ <input type="text" name="lastname" id="lastname" value="" size="20" maxlength="20"/>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Email Address: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="email" id="email" value="" size="50" maxlength="50"/>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 50
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <td><!-- spacer -->&nbsp;</td>
+</tr>
+
+<tr>
+ <td><!-- spacer -->&nbsp;</td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Event Name: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="eventname" id="eventname" value="" size="50" maxlength="50"/>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Event Date: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" id="date" name="date" size="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date"
+ onclick="showCalendar('date')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_date"></div>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Event Location: <span style="color: red;">*</span></strong><br /><small>(City, Country; or City, State)</small></td>
+ <td>
+ <input type="text" name="location" id="location" value="" size="50" maxlength="80" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Event Website: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="website" id="website" value="" size="50" maxlength="120" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Event Description and Key Objectives: <span style="color: red;">*</span></strong></td>
+ <td>
+ <textarea id="goals" name="goals" rows="5" cols="50"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>What will you be doing at the event? <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="checkbox" id="doing-booth" name="doing" value="Booth or Table"><label for="doing-booth">Booth/Table</label><br />
+ <input type="checkbox" id="doing-speaking" name="doing" value="Speaking Opportunity"><label for="doing-speaking">Speaking Opportunity</label><br />
+ <input type="checkbox" id="doing-outreach" name="doing" value="PR or Media Outreach"><label for="doing-outreach">PR or Media Outreach</label><br />
+ <input type="checkbox" id="doing-other" name="doing" value="Other"><label for="doing-other">Other, please explain:</label>
+ <input type="text" name="doing-other-what" id="doing-other-what" value="" size="50" maxlength="120"><br />
+ </td>
+</tr>
+
+<tr>
+ <td><!-- spacer -->&nbsp;</td>
+</tr>
+
+<tr>
+ <td align="right"><strong>How many attendees will be at the event?</strong></td>
+ <td>
+ <select name="attendees" id="attendees">
+ <option value="--Please Select--" selected>--Please Select--</option>
+ <option value="1-99">1-99</option>
+ <option value="100-499">100-499</option>
+ <option value="500-999">500-999</option>
+ <option value="1000+">1000+</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Targeted Audience:</strong></td>
+ <td>
+ <select name="audience" id="audience">
+ <option value="--Please Select--" selected>--Please Select--</option>
+ <option value="Contributors">Contributors (Developers, Education, Security, Designers, Localization, Support & Marketing)</option>
+ <option value="Potential New Users">Potential New Users</option>
+ <option value="User Community">User Community (Recent adopters, fans, Mozilla product evangelizers)</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>How will you measure the<br />success of your event? <span style="color: red;">*</span></strong></td>
+ <td>
+ <textarea id="successmeasure" name="successmeasure" rows="5" cols="50"></textarea>
+ </td>
+</tr>
+
+
+ </table>
+ <br>
+ <input type="submit" id="commit" value="Submit Request">
+
+<p>
+ <strong><span style="color: red;">*</span></strong> - Required field<br />
+ Thanks for contacting us.
+
+</p>
+
+<script type="text/javascript">
+ createCalendar('date');
+</script>
+
+[% PROCESS global/footer.html.tmpl %]
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
new file mode 100644
index 000000000..138f1754b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mozlist.html.tmpl
@@ -0,0 +1,306 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Discussion Forum / Mailing List Requests"
+ javascript_urls = [ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+<script type="text/javascript">
+<!--
+ function toggleGroup (theRadio) {
+ var radioValue = theRadio.value;
+ var groupDiv = YAHOO.util.Dom.get('groups');
+ var group = YAHOO.util.Dom.get('group_35');
+ if (radioValue == 'lists.mozilla.org') {
+ YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listNameOther', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('groups', 'display', 'none');
+ group.disabled = true;
+ YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block');
+ } else if (radioValue == 'mozilla.org') {
+ YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listNameOther', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('groups', 'display', 'table-row');
+ group.disabled = false;
+ YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block');
+ } else {
+ YAHOO.util.Dom.setStyle('listNameTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listNameDiscussion', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listNameOther', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listAdminTR', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listShortDescTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('listShortDescMailman', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listShortDescZimbra', 'display', 'inline');
+ YAHOO.util.Dom.setStyle('listLongDescTR', 'display', 'none');
+ YAHOO.util.Dom.setStyle('listCommentTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('CCTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('URLTR', 'display', 'table-row');
+ YAHOO.util.Dom.setStyle('groups', 'display', 'table-row');
+ group.disabled = false;
+ YAHOO.util.Dom.setStyle('submitDiv', 'display', 'block');
+ }
+ }
+
+ function trySubmit() {
+ var listName = document.getElementById('listName').value;
+ var listAdmin = document.getElementById('listAdmin').value;
+ var listTypeRadio = document.getElementsByName('listType');
+ var listType = "";
+
+ 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 == "lists.mozilla.org") {
+ document.getElementById('component').value = "Discussion Forums";
+ 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;
+ } else {
+ document.getElementById('component').value = "Server Operations";
+ short_desc = "[Mailman List Request] " + listName + "@" + listType;
+ }
+ } else {
+ alert_text += "Please select a list type\n";
+ }
+
+ if (!isFilledOut('listName')) {
+ alert_text += "Please enter the list name\n";
+ }
+
+ if ((!isValidEmail(listAdmin)) && (listType != 'mozilla.com')) {
+ alert_text += "Please enter a valid email address for the list administrator\n";
+ }
+
+ if (alert_text) {
+ alert(alert_text);
+ return false;
+ }
+
+ document.getElementById('short_desc').value = short_desc;
+
+ return true;
+ }
+// -->
+</script>
+
+<form method="post" action="post_bug.cgi" id="mozListRequestForm"
+ enctype="multipart/form-data" onSubmit="return trySubmit();">
+ <input type="hidden" id="format" name="format" value="mozlist">
+ <input type="hidden" id="product" name="product" value="mozilla.org">
+ <input type="hidden" name="token" value="[% token FILTER html %]">
+ <input type="hidden" id="rep_platform" name="rep_platform" value="All">
+ <input type="hidden" id="op_sys" name="op_sys" value="Other">
+ <input type="hidden" id="priority" name="priority" value="--">
+ <input type="hidden" id="version" name="version" value="other">
+ <input type="hidden" id="short_desc" name="short_desc" value="">
+ <input type="hidden" id="component" name="component" value="">
+ <input type="hidden" id="bug_severity" name="bug_severity" value="normal">
+
+ <table>
+ <tr id="listTypeTR" style="display: table-row;">
+ <td align="right" width="15%"><strong>List Type:</strong></td>
+ <td>
+ <dl>
+ <dt>
+ <input type="radio" name="listType" id="lists_mozilla_org"
+ onclick="toggleGroup(this);" value="lists.mozilla.org">
+ <label for="lists_mozilla_org">Standard Discussion Forum</label>
+ </dt>
+ <dd>
+ <label for="lists_mozilla_org">
+ This option gives you a Mozilla <a href="https://www.mozilla.org/about/forums/">Discussion Forum</a>.
+ These are the normal mechanism for public discussion in the Mozilla project. They are made up of a
+ mailing list, a newsgroup and a Google Group (which maintains the list archives), all linked together.
+ Users can add and remove themselves. If you aren't sure, pick this one.
+ </label>
+ </dd>
+ <dt>
+ <input type="radio" name="listType" id="mozilla_org"
+ onclick="toggleGroup(this);" value="mozilla.org">
+ <label for="mozilla_org">Mailing List Only</label>
+ </dt>
+ <dd>
+ <label for="mozilla_org">
+ This option gives you a mailing list without the other access mechanisms. The
+ list can be private, although Mozilla is an "open by default" organization so
+ you need a good reason to have a private list. The archives are maintained by
+ Mailman, our mailing list software. Subscription can be open or
+ moderator-controlled. This type of list is normally hosted on the <b>mozilla.org</b> domain.
+ </label>
+ </dd>
+ <dt>
+ <input type="radio" name="listType" id="mozilla_com"
+ onclick="toggleGroup(this)" value="mozilla.com">
+ <label for="mozilla_com">Distribution List</label>
+ </dt>
+ <dd>
+ <label for="mozilla_com">
+ This option gives you a distribution list - basically, a mail exploder - on
+ mozilla.com. (This option is only appropriate for things which relate
+ specifically to Mozilla Corporation, such as confidential partner projects
+ or internal department lists.) Send email to the address, and it gets remailed
+ out to everyone on the list. There are no archives, and the "subscriber" list
+ is controlled by the IT team.
+ </label>
+ </dd>
+ </dl>
+ <hr>
+ </td>
+ </tr>
+ <tr id="listNameTR" style="display: none;">
+ <td align="right" valign="top"><strong>List Name:</strong></td>
+ <td>
+ <input name="listName" id="listName" size="60" value="[% listName FILTER html %]"><br>
+ <span id="listNameDiscussion" style="display: none;">The desired name for the newsgroup. Should start with 'mozilla.' and fit somewhere in the hierarchy described <a href="https://www.mozilla.org/about/forums/">here</a>.</span>
+ <span id="listNameOther" style="display: none;">Only enter the part before the @, the domain name is chosen based on the list type.</span>
+ <hr>
+ </td>
+ </tr>
+ <tr id="listAdminTR" style="display: none;">
+ <td align="right" valign="top" width="15%"><strong>List Administrator:</strong></td>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "listAdmin"
+ name => "listAdmin"
+ value => ""
+ size => 60
+ multiple => 5
+ %]
+ <br>
+ <b>Note:</b>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, 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.<hr />
+ </td>
+ </tr>
+ <tr id="listShortDescTR" style="display: none;">
+ <td align="right" valign="top"><strong>Short one-line description:</strong></td>
+ <td>
+ <input name="listShortDesc" id="listShortDesc" size="60" value="[% listShortDesc FILTER html %]"><br />
+ <span id="listShortDescMailman" style="display: none;">This will be shown to users on the index of lists on the server.</span>
+ <span id="listShortDescZimbra" style="display: none;">This will be shown as the "real name" in the Zimbra address book.</span>
+ <hr />
+ </td>
+ </tr>
+ <tr id="listLongDescTR" style="display: none;">
+ <td align="right" valign="top"><strong>Long description:</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'listLongDesc'
+ id = 'listLongDesc'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = listLongDesc
+ %]
+ <br>This will be shown at the top of the list's listinfo page.
+ <hr>
+ </td>
+ </tr>
+ <tr id="listCommentTR" style="display: none;">
+ <td align="right" valign="top"><strong>Additional comments:</strong></td>
+ <td colspan="3">
+ Justification for the list, special instructions, etc.<br>
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = comment
+ %]
+ <hr>
+ </td>
+ </tr>
+ <tr id="CCTR" style="display: none;">
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+ </tr>
+ <tr id="URLTR" style="display: none;">
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+ </table>
+ <br>
+
+ <div id="groups" style="display:none;">
+ <!-- infra bugs -->
+ <input type="checkbox" name="groups" id="group_35" value="infra" disabled="true">
+ <label for="group_35"><strong>This is an internal issue which should not be publicly visible.</strong></label>
+ <br><br>
+ </div>
+
+ <div id="submitDiv" style="display: none;">
+ <input type="submit" id="commit" value="Submit Request">
+
+<p>
+ Thanks for contacting us. You will be notified by email of any progress made
+ in resolving your request.
+</p>
+ </div>
+</form>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
new file mode 100644
index 000000000..28a37a31e
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-mozpr.html.tmpl
@@ -0,0 +1,651 @@
+[%# 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 <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # Shane H. W. Travis <travis@sedsystems.ca>
+ # Marc Schumann <wurblzap@gmail.com>
+ # Akamai Technologies <bugzilla-dev@akamai.com>
+ # Max Kanat-Alexander <mkanat@bugzilla.org>
+ # Frédéric Buclin <LpSolit@gmail.com>
+ #%]
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+[% title = BLOCK %]Create a PR Request[% END %]
+
+[% PROCESS global/header.html.tmpl
+ title = title
+ style_urls = [ 'skins/standard/attachment.css' ]
+ javascript_urls = [ "js/attachment.js", "js/util.js",
+ "js/field.js", "js/TUI.js" ]
+ onload = 'set_assign_to();'
+ yui = [ 'autocomplete' ]
+%]
+
+<script type="text/javascript">
+<!--
+
+var initialowners = new Array([% product.components.size %]);
+var last_initialowner;
+var initialccs = new Array([% product.components.size %]);
+var components = new Array([% product.components.size %]);
+var comp_desc = new Array([% product.components.size %]);
+var flags = new Array([% product.components.size %]);
+[% IF Param("useqacontact") %]
+ var initialqacontacts = new Array([% product.components.size %]);
+ var last_initialqacontact;
+[% END %]
+[% count = 0 %]
+[%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ components[[% count %]] = "[% c.name FILTER js %]";
+ comp_desc[[% count %]] = "[% c.description FILTER html_light FILTER js %]";
+ initialowners[[% count %]] = "[% c.default_assignee.login FILTER js %]";
+ [% flag_list = [] %]
+ [% FOREACH f = c.flag_types(is_active=>1).bug %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ [% FOREACH f = c.flag_types(is_active=>1).attachment %]
+ [% flag_list.push(f.id) %]
+ [% END %]
+ flags[[% count %]] = [[% flag_list.join(",") FILTER js %]];
+ [% IF Param("useqacontact") %]
+ initialqacontacts[[% count %]] = "[% c.default_qa_contact.login FILTER js %]";
+ [% END %]
+
+ [% SET initial_cc_list = [] %]
+ [% FOREACH cc_user = c.initial_cc %]
+ [% initial_cc_list.push(cc_user.login) %]
+ [% END %]
+ initialccs[[% count %]] = "[% initial_cc_list.join(', ') FILTER js %]";
+
+ [% count = count + 1 %]
+[%- END %]
+
+function set_assign_to() {
+ // Based on the selected component, fill the "Assign To:" field
+ // with the default component owner, and the "QA Contact:" field
+ // with the default QA Contact. It also selectively enables flags.
+ var form = document.Create;
+ var assigned_to = form.assigned_to.value;
+
+[% IF Param("useqacontact") %]
+ var qa_contact = form.qa_contact.value;
+[% END %]
+
+ var index = -1;
+ if (form.component.type == 'select-one') {
+ index = form.component.selectedIndex;
+ } else if (form.component.type == 'hidden') {
+ // Assume there is only one component in the list
+ index = 0;
+ }
+ if (index != -1) {
+ var owner = initialowners[index];
+ var component = components[index];
+ if (assigned_to == last_initialowner
+ || assigned_to == owner
+ || assigned_to == '') {
+ form.assigned_to.value = owner;
+ last_initialowner = owner;
+ }
+
+ document.getElementById('initial_cc').innerHTML = initialccs[index];
+ document.getElementById('comp_desc').innerHTML = comp_desc[index];
+
+ [% IF Param("useqacontact") %]
+ var contact = initialqacontacts[index];
+ if (qa_contact == last_initialqacontact
+ || qa_contact == contact
+ || qa_contact == '') {
+ form.qa_contact.value = contact;
+ last_initialqacontact = contact;
+ }
+ [% END %]
+
+ // First, we disable all flags. Then we re-enable those
+ // which are available for the selected component.
+ var inputElements = document.getElementsByTagName("select");
+ var inputElement, flagField;
+ for ( var i=0 ; i<inputElements.length ; i++ ) {
+ inputElement = inputElements.item(i);
+ if (inputElement.name.search(/^flag_type-(\d+)$/) != -1) {
+ var id = inputElement.name.replace(/^flag_type-(\d+)$/, "$1");
+ inputElement.disabled = true;
+ // Also disable the requestee field, if it exists.
+ inputElement = document.getElementById("requestee_type-" + id);
+ if (inputElement) inputElement.disabled = true;
+ }
+ }
+ // Now enable flags available for the selected component.
+ for (var i = 0; i < flags[index].length; i++) {
+ flagField = document.getElementById("flag_type-" + flags[index][i]);
+ // Do not enable flags the user cannot set nor request.
+ if (flagField && flagField.options.length > 1) {
+ flagField.disabled = false;
+ // Re-enabling the requestee field depends on the status
+ // of the flag.
+ toggleRequesteeField(flagField, 1);
+ }
+ }
+ }
+}
+
+function fix_component() {
+ var form = document.Create;
+ var location = form.location.options[form.location.selectedIndex].value;
+ var fakecomp = form.fakecomp.options[form.fakecomp.selectedIndex].value;
+ var newcomp = location + " - " + fakecomp;
+ form.component.value = newcomp;
+ set_assign_to();
+}
+
+function handleWantsAttachment(wants_attachment) {
+ if (wants_attachment) {
+ document.getElementById('attachment_false').style.display = 'none';
+ document.getElementById('attachment_true').style.display = 'block';
+ }
+ else {
+ document.getElementById('attachment_false').style.display = 'block';
+ document.getElementById('attachment_true').style.display = 'none';
+ clearAttachmentFields();
+ }
+}
+
+
+TUI_alternates['expert_fields'] = 'Show Advanced Fields';
+// Hide the Advanced Fields by default, unless the user has a cookie
+// that specifies otherwise.
+TUI_hide_default('expert_fields');
+
+-->
+</script>
+
+[% IF user.in_group("mozilla-confidential") %]
+
+[% USE Bugzilla %]
+[% SET select_fields = {} %]
+[% FOREACH field = Bugzilla.get_fields(
+ { type => constants.FIELD_TYPE_SINGLE_SELECT, custom => 0 })
+%]
+ [% select_fields.${field.name} = field %]
+[% END %]
+
+<form name="Create" id="Create" method="post" action="post_bug.cgi"
+ enctype="multipart/form-data">
+<input type="hidden" name="product" value="[% product.name FILTER html %]">
+<input type="hidden" name="token" value="[% token FILTER html %]">
+
+<table cellspacing="4" cellpadding="2" border="0" style="background: url(extensions/BMO/web/images/presshat.png) top right no-repeat">
+<tbody>
+ <tr>
+ <td colspan="2">
+ <a id="expert_fields_controller" class="controller bz_default_hidden"
+ href="javascript:TUI_toggle_class('expert_fields')">Hide
+ Advanced Fields</a>
+ [%# Show the link if the browser supports JS %]
+ <script type="text/javascript">
+ YAHOO.util.Dom.removeClass('expert_fields_controller',
+ 'bz_default_hidden');
+ </script>
+ </td>
+ <td colspan="2">
+ (<span class="required_star">*</span> =
+ <span class="required_explanation">Required Field</span>)
+ </td>
+ </tr>
+
+ <tr>
+ <th>Product:</th>
+ <td width="10%">[% product.name FILTER html %]</td>
+
+ <th>Reporter:</th>
+ <td width="100%">[% user.login FILTER html %]</td>
+ </tr>
+
+ [%# We can't use the select block in these two cases for various reasons. %]
+[% matches = default.component_.matches('^(.*) - (.*)$') %]
+[% default.location = matches.0 %]
+[% default.fakecomp = matches.1 %]
+[% IF default.location == '' %]
+ [% default.location = 'US' %]
+[% END %]
+[% locations = [] %]
+[% fakecomps = [] %]
+[% FOREACH c = product.components %]
+ [% matches = c.name.match('^(.*) - (.*)$') %]
+ [% locations.push(matches.0) %]
+ [% fakecomps.push(matches.1) %]
+[% END %]
+[% locations = locations.unique %]
+[% fakecomps = fakecomps.unique %]
+ <tr>
+ <th class="required">
+ Location:
+ </th>
+ <td>
+
+ <select name="location" onchange="fix_component();" size="7">
+ [% FOREACH l = locations %]
+ <option value="[% l FILTER html %]" [% " selected=\"selected\"" IF l == default.location %]>
+ [% l FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ <select name="component" onchange="set_assign_to();" size="7"
+ aria-required="true" class="required" style="display: none;">
+ [%# Build the lists of assignees and QA contacts if "usemenuforusers" is enabled. %]
+ [% IF Param("usemenuforusers") %]
+ [% assignees_list = user.get_userlist.clone %]
+ [% qa_contacts_list = user.get_userlist.clone %]
+ [% END %]
+
+ [%- FOREACH c = product.components %]
+ [% NEXT IF NOT c.is_active %]
+ <option value="[% c.name FILTER html %]"
+ [% " selected=\"selected\"" IF c.name == default.component_ %]>
+ [% c.name FILTER html -%]
+ </option>
+ [% IF Param("usemenuforusers") %]
+ [% INCLUDE build_userlist default_user = c.default_assignee,
+ userlist = assignees_list %]
+ [% INCLUDE build_userlist default_user = c.default_qa_contact,
+ userlist = qa_contacts_list %]
+ [% END %]
+ [%- END %]
+ </select>
+ </td>
+
+ </tr>
+ <tr>
+ <th>
+ Request type:
+ </th>
+ <td>
+
+ <select name="fakecomp" onchange="fix_component();" size="7">
+ [% FOREACH f = fakecomps %]
+ <option value="[% f FILTER html %]" [% " selected=\"selected\"" IF f == default.fakecomp %]>
+ [% f FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+ <td colspan="2">
+ [%# Enclose the fieldset in a nested table so that its width changes based
+ # on the length on the component description. %]
+ <table>
+ <tr>
+ <td>
+ <fieldset>
+ <legend>Request Description</legend>
+ <div id="comp_desc" class="comment">Select a request type to read its description.</div>
+ </fieldset>
+ </td>
+ </tr>
+ </table>
+ <input type="hidden" name="bug_severity" value="[% default.bug_severity %]">
+ <input type="hidden" name="rep_platform" value="[% default.rep_platform %]">
+ <input type="hidden" name="op_sys" value="[% default.op_sys %]">
+ <input type="hidden" name="version" value="unspecified">
+ </td>
+ </tr>
+</tbody>
+
+<tbody class="expert_fields">
+ <tr>
+ <td colspan="4">&nbsp;</td>
+ </tr>
+
+ <tr>
+[% IF bug_status.size <= 1 %]
+ <input type="hidden" name="bug_status"
+ value="[% default.bug_status FILTER html %]">
+ <th>Initial State:</th>
+ <td>[% display_value("bug_status", default.bug_status) FILTER html %]</td>
+[% ELSE %]
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.bug_status,
+ editable = (bug_status.size > 1), value = default.bug_status
+ override_legal_values = bug_status %]
+[% END %]
+
+ <td>&nbsp;</td>
+ [%# Calculate the number of rows we can use for flags %]
+ [% num_rows = 6 + (Param("useqacontact") ? 1 : 0) +
+ (user.is_timetracker ? 3 : 0) +
+ (Param("usebugaliases") ? 1 : 0)
+ %]
+
+ <td rowspan="[% num_rows FILTER html %]">
+ [% IF product.flag_types(is_active=>1).bug.size > 0 %]
+ [% display_flag_headers = 0 %]
+ [% any_flags_requesteeble = 0 %]
+
+ [% 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(is_active=>1).bug
+ any_flags_requesteeble = any_flags_requesteeble
+ flag_table_id = "bug_flags"
+ %]
+ [% END %]
+ [% END %]
+ </td>
+ </tr>
+
+ <tr>
+ <th><a href="page.cgi?id=fields.html#assigned_to">Assign To</a>:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "assigned_to"
+ name => "assigned_to"
+ value => assigned_to
+ disabled => assigned_to_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => assignees_list
+ %]
+ <noscript>(Leave blank to assign to component's default assignee)</noscript>
+ </td>
+ </tr>
+
+[% IF Param("useqacontact") %]
+ <tr>
+ <th>QA Contact:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "qa_contact"
+ name => "qa_contact"
+ value => qa_contact
+ disabled => qa_contact_disabled
+ size => 30
+ emptyok => 1
+ custom_userlist => qa_contacts_list
+ %]
+ <noscript>(Leave blank to assign to default qa contact)</noscript>
+ </td>
+ </tr>
+[% END %]
+
+ <tr>
+ <th>CC:</th>
+ <td colspan="2">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ disabled => cc_disabled
+ size => 30
+ multiple => 5
+ %]
+ </td>
+ </tr>
+
+ <tr>
+ <th>Default CC:</th>
+ <td colspan="2">
+ <div id="initial_cc">
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="3">&nbsp;</td>
+ </tr>
+
+[% IF user.is_timetracker %]
+ <tr>
+ <th>Estimated Hours:</th>
+ <td colspan="2">
+ <input name="estimated_time" size="6" maxlength="6" value="[% estimated_time FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Deadline:</th>
+ <td colspan="2">
+ <input name="deadline" size="10" maxlength="10" value="[% deadline FILTER html %]">
+ <small>(YYYY-MM-DD)</small>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="3">&nbsp;</td>
+ </tr>
+[% END %]
+
+[% IF Param("usebugaliases") %]
+ <tr>
+ <th>Alias:</th>
+ <td colspan="2">
+ <input name="alias" size="20" value="[% alias FILTER html %]">
+ </td>
+ </tr>
+[% END %]
+
+ <tr>
+ <th>URL:</th>
+ <td colspan="2">
+ <input name="bug_file_loc" size="40"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+</tbody>
+
+<tbody>
+
+ <tr>
+ <th class="required">Summary:</th>
+ <td colspan="3">
+ <input name="short_desc" size="70" value="[% short_desc FILTER html %]"
+ maxlength="255" spellcheck="true" aria-required="true"
+ class="required">
+ </td>
+ </tr>
+
+ <tr>
+ <th>Description:</th>
+ <td colspan="3">
+ [% defaultcontent = BLOCK %]
+ [% IF cloned_bug_id %]
++++ This [% terms.bug %] was initially created as a clone of [% terms.Bug %] #[% cloned_bug_id %] +++
+
+
+ [% END %]
+ [%-# We are within a BLOCK. The comment will be correctly HTML-escaped
+ # by global/textarea.html.tmpl. So we must not escape the comment here. %]
+ [% comment FILTER none %]
+ [%- END %]
+ [% INCLUDE global/textarea.html.tmpl
+ name = 'comment'
+ id = 'comment'
+ minrows = 10
+ maxrows = 25
+ cols = constants.COMMENT_COLS
+ defaultcontent = defaultcontent
+ %]
+ <br>
+ </td>
+ </tr>
+
+ [% IF user.is_insider %]
+ <tr class="expert_fields">
+ <th>&nbsp;</th>
+ <td colspan="3">
+ &nbsp;&nbsp;
+ <input type="checkbox" id="commentprivacy" name="commentprivacy"
+ [% " checked=\"checked\"" IF commentprivacy %]>
+ <label for="commentprivacy">
+ Make description private (visible only to members of the
+ <strong>[% Param('insidergroup') FILTER html %]</strong> group)
+ </label>
+ </td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Attachment:</th>
+ <td colspan="3">
+ <script type="text/javascript">
+ <!--
+ document.write( '<div id="attachment_false">'
+ + '<input type="button" value="Add an attachment" '
+ + 'onClick="handleWantsAttachment(true)"> '
+ + '<em style="display: none">This button has no '
+ + 'functionality for you because your browser does '
+ + 'not support CSS or does not use it.<\/em>'
+ + '<\/div>'
+ + '<div id="attachment_true" style="display: none">'
+ + '<input type="button" '
+ + 'value="Don\'t add an attachment " '
+ + 'onClick="handleWantsAttachment(false)">');
+ //-->
+ </script>
+ <fieldset>
+ <legend>Add an attachment</legend>
+ <table class="attachment_entry">
+ [% PROCESS attachment/createformcontents.html.tmpl
+ flag_types = product.flag_types(is_active=>1).attachment
+ any_flags_requesteeble = 1
+ flag_table_id ="attachment_flags" %]
+ </table>
+ </fieldset>
+ <script type="text/javascript">
+ <!--
+ document.write('<\/div>');
+ //-->
+ </script>
+ </td>
+ </tr>
+</tbody>
+
+<tbody class="expert_fields">
+ [% IF user.in_group('editbugs', product.id) %]
+ [% IF use_keywords %]
+ <tr>
+ [% INCLUDE bug/field.html.tmpl
+ bug = default, field = bug_fields.keywords, editable = 1,
+ value = keywords, desc_url = "describekeywords.cgi",
+ value_span = 3 %]
+ </tr>
+ [% END %]
+
+ <tr>
+ <th>Status Whiteboard:</th>
+ <td colspan="3">
+ <input id="status_whiteboard" name="status_whiteboard" size="70"
+ value="[% status_whiteboard %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Depends on:</th>
+ <td colspan="3">
+ <input name="dependson" accesskey="d" value="[% dependson FILTER html %]">
+ </td>
+ </tr>
+ <tr>
+ <th>Blocks:</th>
+ <td colspan="3">
+ <input name="blocked" accesskey="b" value="[% blocked FILTER html %]">
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody class="expert_fields">
+ [% IF group.size %]
+ <tr>
+ <th>&nbsp;</th>
+ <td colspan="3">
+ <br>
+ <strong>
+ Only users in all of the selected groups can view this [% terms.bug %]:
+ </strong>
+ <br>
+ <font size="-1">
+ (Leave all boxes unchecked to make this a public [% terms.bug %].)
+ </font>
+ <br>
+ <br>
+
+ <!-- Checkboxes -->
+ [% FOREACH g = group %]
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <input type="checkbox" id="bit-[% g.bit %]"
+ name="bit-[% g.bit %]" value="1"
+ [% " checked=\"checked\"" IF g.checked %]>
+ <label for="bit-[% g.bit %]">[% g.description FILTER html_light %]</label><br>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+</tbody>
+
+<tbody>
+ [%# Form controls for entering additional data about the bug being created. %]
+ [% Hook.process("form") %]
+
+ <tr>
+ <th>&nbsp;</th>
+ <td colspan="3">
+ <input type="submit" id="commit" value="Submit [% terms.Bug %]"
+ onclick="if (this.form.short_desc.value == '')
+ { alert('Please enter a summary sentence for this [% terms.bug %].');
+ return false; } return true;">
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ <input type="submit" name="maketemplate" id="maketemplate"
+ value="Remember values as bookmarkable template"
+ class="expert_fields">
+ </td>
+ </tr>
+</tbody>
+ </table>
+ <input type="hidden" name="form_name" value="enter_bug">
+</form>
+
+[%# Links or content with more information about the bug being created. %]
+[% Hook.process("end") %]
+
+[% ELSE %]
+
+<p>Sorry, you do not have access to this page.</p>
+
+[% END %]
+
+[% PROCESS global/footer.html.tmpl %]
+
+[% BLOCK build_userlist %]
+ [% user_found = 0 %]
+ [% default_login = default_user.login %]
+ [% RETURN UNLESS default_login %]
+
+ [% FOREACH user = userlist %]
+ [% IF user.login == default_login %]
+ [% user_found = 1 %]
+ [% LAST %]
+ [% END %]
+ [% END %]
+
+ [% userlist.push({login => default_login,
+ identity => default_user.identity,
+ visible => 1})
+ UNLESS user_found %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
new file mode 100644
index 000000000..c0b3ea237
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-poweredby.html.tmpl
@@ -0,0 +1,85 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville SkyttŠ <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Powered by Mozilla Logo Requests"
+%]
+
+[% USE Bugzilla %]
+
+<p>If you are interested in using the <a href="http://www.mozilla.org/poweredby">Powered by Mozilla logo</a>,
+please provide some information about your application or product.</p>
+
+<p><strong>Please use this form for Powered by Mozilla logo requests only.</strong></p>
+
+<form method="post" action="post_bug.cgi" id="tmRequestForm">
+
+ <input type="hidden" name="product" value="Websites">
+ <input type="hidden" name="component" value="www.mozilla.org">
+ <input type="hidden" name="bug_severity" value="enhancement">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="other">
+ <!-- Marketing-Private -->
+ <input type="hidden" name="groups" value="marketing-private">
+
+ <table>
+ <tr>
+ <td align="right"><strong>Application or Product Name:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="Powered by Mozilla request for: [% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Comments&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+
+ </table>
+
+ <br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your
+ request.
+</p>
+
+[% 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
new file mode 100644
index 000000000..cdbce5c8c
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-presentation.html.tmpl
@@ -0,0 +1,217 @@
+[%# 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 <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Corporation Mountain View Presentation Request"
+ javascript_urls = [ 'js/field.js', 'js/util.js' ]
+ style = ".yui-skin-sam .yui-calcontainer { z-index: 1; }"
+ yui = [ 'autocomplete', 'calendar' ]
+%]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Mountain View Presentation Request</div>
+
+<p><strong>Mountain View Presentation Request:</strong> Please use this form if you plan on hosting a presentation so that IT will be able to properly provide support. </p>
+
+<p>Process:</p>
+
+<ol><li>Complete and submit request below.</li>
+ <li>Your request will be reviewed and assigned to the appropriate person in IT.</li>
+</ol>
+
+<p>These requests will only be visible internally in all cases and only to the
+person who submitted the request and any persons designated in the CC line.</p>
+
+<script type="text/javascript">
+function trySubmit() {
+ var out = 'Topic: the_topic\r\nPresenter: the_presenter\r\nDate: the_date\r\nTime: the_time\r\nAudience: the_audience\r\nAir Mozilla: air_mozilla\r\nDial-in: dial_in\r\nArchive: to_archive\r\nMember of IT to help with A/V: it_help\r\nDescription: the_description';
+
+ var topic = document.getElementById('topic').value;
+ var presenter = document.getElementById('presenter').value;
+ var date = document.getElementById('date').value;
+ var time = document.getElementById('time_hour').value + ':' + document.getElementById('time_minute').value + document.getElementById('ampm').value;
+ var shortdesc = 'Mountain View Presentation Request - ' + topic + ' (' + date + ' ' + time + ')';
+ var airmozilla = document.getElementById('airmozilla').checked? 'yes' : 'no';
+ var dialin = document.getElementById('dialin').checked? 'yes' : 'no';
+ var archive = document.getElementById('archive').checked? 'yes' : 'no';
+ var ithelp = document.getElementById('ithelp').checked? 'yes' : 'no';
+
+ out = out.replace( /the_topic/, topic );
+ out = out.replace( /the_presenter/, presenter );
+ out = out.replace( /the_date/, date);
+ out = out.replace( /the_time/, time);
+ out = out.replace( /the_audience/, document.getElementById('audience').value );
+ out = out.replace( /air_mozilla/, airmozilla);
+ out = out.replace( /dial_in/, dialin);
+ out = out.replace( /the_description/, document.getElementById('description').value );
+ out = out.replace( /to_archive/, archive);
+ out = out.replace( /it_help/, ithelp);
+
+ document.getElementById('comment').value = out;
+ document.getElementById('short_desc').value = shortdesc;
+
+ return true;
+}
+
+</script>
+
+<form method="post" action="post_bug.cgi" id="presentationRequestForm" enctype="multipart/form-data"
+ onSubmit="return trySubmit();">
+
+ <input type="hidden" name="product" value="mozilla.org">
+ <input type="hidden" name="component" value="Server Operations: Desktop Issues">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="other">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+ <input type="hidden" name="comment" id="comment" value="">
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+<table>
+
+<tr>
+ <td align="right"><strong>Presenter:</strong></td>
+ <td>
+ <input type="text" name="presenter" id="presenter" value="" size="60" />
+ </td>
+
+</tr>
+
+<tr>
+ <td align="right"><strong>Topic:</strong></td>
+ <td>
+ <input type="text" name="topic" id="topic" value="" size="60" />
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Date:</strong></td>
+ <td>
+ <input type="text" id="date" name="date" size="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_date"
+ onclick="showCalendar('date')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_date"></div>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Start Time:</strong></td>
+ <td>
+ <select name="time_hour" id="time_hour">
+ <option value="12" selected>12</option>
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="7">7</option>
+ <option value="8">8</option>
+ <option value="9">9</option>
+ <option value="10">10</option>
+ <option value="11">11</option>
+ </select>:<select name="time_minute" id="time_minute">
+ <option value="00" selected>00</option>
+ <option value="15">15</option>
+ <option value="30">30</option>
+ <option value="45">45</option>
+ </select>
+ <select name="ampm" id="ampm">
+ <option value="AM" selected>AM</option>
+ <option value="PM">PM</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Intended Audience:</strong></td>
+ <td>
+ <select name="audience" id="audience">
+ <option value="Public" selected>Open to Public</option>
+ <option value="Employees Only">Employees Only</option>
+ <option value="Interns">Interns</option>
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Air Mozilla Broadcasting?</strong></td>
+ <td align="left"><input type="checkbox" name="airmozilla" id="airmozilla"></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Dial In?</strong></td>
+ <td align="left"><input type="checkbox" name="dialin" id="dialin"></td>
+</tr>
+
+<tr>
+<td align="right"><strong>Archive this?</strong></td>
+<td align="left"><input type="checkbox" name="archive" id="archive" value="yes"></td>
+</tr>
+
+
+<tr>
+<td align="right"><strong>Need IT to help run A/V?</strong></td>
+<td align="left"><input type="checkbox" name="ithelp" id="ithelp" value="yes" checked></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>CC&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 60
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <th><label for="description">Description</label>:</th>
+ <td>
+ <em>Please briefly describe the presentation and any specific needs you might have.</em><br>
+
+ <textarea id="description" name="description" rows="10" cols="80"></textarea>
+ </td>
+</tr>
+
+ </table>
+
+ <br>
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+
+</p>
+
+<script type="text/javascript">
+ createCalendar('date');
+</script>
+
+[% 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
new file mode 100644
index 000000000..f7edccbe1
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-swag.html.tmpl
@@ -0,0 +1,221 @@
+[%# 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 <reed@mozilla.com>
+ # David Tran <dtran@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Swag Request Form"
+ javascript_urls = [ 'extensions/BMO/web/js/swag.js',
+ 'extensions/BMO/web/js/form_validate.js',
+ 'js/field.js' ]
+ yui = [ 'autocomplete' ]
+%]
+
+<div style='text-align: center; width: 98%; font-size: 2em; font-weight: bold; margin: 10px;'>Swag Request Form</div>
+
+<p><strong>Swag Request:</strong> Please use this form to file a request for swag. </p>
+
+<ol>
+ <li>You first need submit a <a href="/enter_bug.cgi?product=Marketing&amp;format=mktgevent">Event Request Form</a>. You'll be asked for the bug number below.</li>
+ <li>Complete and submit request below.</li>
+ <li>Your request will be reviewed by the appropriate person in the Engagement team.</li>
+ <li>Your swag request will be reviewed and if approved shipped to you from
+ one of our two fulfillment houses. <i>Please note that swag is expensive and
+ products change over time - we are happy to send you a small quantity of swag
+ to use at your event!</i></li>
+</ol>
+
+<p>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
+Engagement team.</p>
+
+<script language="javascript" type="text/javascript">
+function trySubmit() {
+
+ var firstname = document.getElementById('firstname').value;
+ var lastname = document.getElementById('lastname').value;
+ var requester = firstname + ' ' + lastname;
+ var shortdesc = 'Swag Request - ' + requester;
+ document.getElementById('short_desc').value = shortdesc;
+
+ // the following fields we don't let the user mess with because they're
+ // calculated, but they need to be submitted, and disabled fields don't submit
+ document.getElementById('Totalswag').disabled = false;
+ document.getElementById('mens_total').disabled = false;
+ document.getElementById('womens_total').disabled = false;
+
+ return true;
+}
+
+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 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!
+ if(alert_text == '') {
+ return trySubmit();
+ }
+
+ //alert text, stay here on the pagee
+ alert(alert_text);
+ return false;
+}
+
+</script>
+
+<form method="post" action="post_bug.cgi" id="swagRequestForm" enctype="multipart/form-data"
+ onSubmit="return validateAndSubmit();">
+
+ <input type="hidden" name="format" value="swag">
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Swag Requests">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="priority" value="--">
+ <input type="hidden" name="version" value="unspecified">
+ <input type="hidden" name="bug_severity" id="bug_severity" value="normal">
+
+ <input type="hidden" name="short_desc" id="short_desc" value="">
+ <input type="hidden" name="groups" value="mozilla-corporation-confidential">
+<table>
+
+<tr>
+ <td align="right"><strong>First Name: <span style="color: red;">*</span></strong></td>
+ <td align="left">
+ <input type="text" name="firstname" id="firstname" value="" size="20" maxlength="20" />
+ </td>
+</tr>
+<tr>
+ <td align="right"><strong>Last Name: <span style="color: red;">*</span></strong></td>
+ <td align="left">
+ <input type="text" name="lastname" id="lastname" value="" size="20" maxlength="20"/>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Email Address: <span style="color: red;">*</span></strong></td>
+ <td>
+ <input type="text" name="email" id="email" value="" size="50" maxlength="50"/>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><strong>CC:</strong></td>
+ <td colspan="3">
+ [% INCLUDE global/userselect.html.tmpl
+ id => "cc"
+ name => "cc"
+ value => cc
+ size => 50
+ multiple => 5
+ %]
+ </td>
+</tr>
+
+<tr>
+ <td><!-- spacer -->&nbsp;</td>
+</tr>
+
+<tr>
+ <td><!-- spacer -->&nbsp;</td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Bug number assigned to previously- &nbsp;&nbsp;<br>submitted <a href="/enter_bug.cgi?product=Marketing&amp;format=mktgevent">Event Request Form</a>: <span style="color: red;">*</span></strong></td>
+ <td colspan="3"><input name="dependson" id="dependson"></td>
+</tr>
+
+<tr>
+ <td align="right"><strong>Specific swag needed?</strong></td>
+ <td>
+ <textarea id="additional" name="additional" rows="5" cols="50"></textarea>
+ </td>
+</tr>
+
+<tr>
+ <td align="right"><br><br><strong>Ship to:</strong></td>
+ <td colspan="3"></td>
+</tr>
+<tr>
+ <td align="right"><strong>First name:</strong></td>
+ <td colspan="3"><input name="shiptofirstname" id="shiptofirstname"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Last name:</strong></td>
+ <td colspan="3"><input name="shiptolastname" id="shiptolastname"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Address</strong></td>
+ <td colspan="3"><input name="shiptoaddress" id="shiptoaddress" size="60"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Address 2</strong></td>
+ <td colspan="3"><input name="shiptoaddress2" id="shiptoaddress2" size="60"></td>
+</tr>
+<tr>
+ <td align="right"><strong>City</strong></td>
+ <td colspan="3"><input name="shiptocity" id="shiptocity"></td>
+</tr>
+<tr>
+ <td align="right"><strong>State</strong></td>
+ <td colspan="3"><input name="shiptostate" id="shiptostate"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Country</strong></td>
+ <td colspan="3"><input name="shiptocountry" id="shiptocountry"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Postal Code</strong></td>
+ <td colspan="3"><input name="shiptopcode" id="shiptopcode"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Telephone</strong></td>
+ <td colspan="3"><input name="shiptophone" id="shiptophone"></td>
+</tr>
+<tr>
+ <td align="right"><strong>Personal ID/RUT</strong><br><small>(if your country requires this)</small></td>
+ <td colspan="3"><input name="shiptoidrut" id="shiptoidrut"></td>
+</tr>
+
+<tr><td colspan="4"><br><br></td></tr>
+
+<tr>
+ <td align="right"><label for="comment"><strong>Any additional comments?</strong></label></td>
+ <td>
+ <textarea id="comment" name="comment" rows="5" cols="50"></textarea>
+ </td>
+</tr>
+
+ </table>
+ <br>
+ <input type="submit" id="commit" value="Submit Request">
+
+<p>
+ <strong><span style="color: red;">*</span></strong> - Required field<br />
+ Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl
new file mode 100644
index 000000000..116564255
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/create-trademark.html.tmpl
@@ -0,0 +1,87 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Ville Skyttä <ville.skytta@iki.fi>
+ # John Hoogstrate <hoogstrate@zeelandnet.nl>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Trademark Usage Requests"
+%]
+
+[% USE Bugzilla %]
+
+<p>
+ If, after reading
+ <a href="http://www.mozilla.org/foundation/trademarks/">the trademark policy
+ documents</a>, you know you need permission to use a certain trademark, this
+ is the place to be.
+</p>
+
+<p><strong>Please use this form for trademark requests only!</strong></p>
+
+<form method="post" action="post_bug.cgi" id="tmRequestForm">
+
+ <input type="hidden" name="product" value="Marketing">
+ <input type="hidden" name="component" value="Trademark Permissions">
+ <input type="hidden" name="bug_severity" value="enhancement">
+ <input type="hidden" name="rep_platform" value="All">
+ <input type="hidden" name="priority" value="P3">
+ <input type="hidden" name="op_sys" value="Other">
+ <input type="hidden" name="version" value="unspecified">
+ <!-- Marketing-Private -->
+ <input type="hidden" name="groups" value="marketing-private">
+
+ <table>
+ <tr>
+ <td align="right"><strong>Summary:</strong></td>
+ <td colspan="3">
+ <input name="short_desc" size="60" value="[% short_desc FILTER html %]">
+ </td>
+ </tr>
+
+ <tr><td align="right" valign="top"><strong>Description:</strong></td>
+ <td colspan="3">
+ <textarea name="comment" rows="10" cols="80">
+ [% comment FILTER html %]</textarea>
+ <br>
+ </td>
+ </tr>
+ <tr>
+ <td align="right"><strong>URL&nbsp;(optional):</strong></td>
+ <td colspan="3">
+ <input name="bug_file_loc" size="60"
+ value="[% bug_file_loc FILTER html %]">
+ </td>
+ </tr>
+ </table>
+
+ <br>
+
+ <input type="submit" id="commit" value="Submit Request">
+</form>
+
+<p>Thanks for contacting us.
+ You will be notified by email of any progress made in resolving your
+ request.
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl
new file mode 100644
index 000000000..e9a480090
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/created-mozreps.html.tmpl
@@ -0,0 +1,38 @@
+[%# 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 <glob@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Mozilla Reps - Application Form"
+
+%]
+
+<h1>Thank you!</h1>
+
+<p>
+Thank you for submitting your Mozilla Reps Application Form. A Mozilla Rep
+mentor will contact you shortly at your bugzilla email address.
+</p>
+
+<p style="font-size: x-small">
+Reference: <a href="show_bug.cgi?id=[% id FILTER uri %]">#[% id FILTER html %]</a>
+</p>
+
+[% PROCESS global/footer.html.tmpl %]
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
new file mode 100644
index 000000000..e7cea5d2b
--- /dev/null
+++ b/extensions/BMO/template/en/default/bug/create/user-message.html.tmpl
@@ -0,0 +1,140 @@
+<!-- 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Matthew Tuck <matty@chariot.net.au>
+ #%]
+
+[%# Migration note: this file corresponds to the old Param
+ # 'entryheaderhtml'
+ #%]
+
+[%# You can make the output of this template product-specific by using
+ # Template Toolkit IF statements. The current product name is stored in
+ # the 'product' variable.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% IF product == "Bugzilla" %]
+ [% IF format == "guided" %]
+<p align="center">
+<table WIDTH="90%" BGCOLOR="#FFFFFF" style="border: 8px double red;"><tr>
+<td valign="middle" align="center"><img width="200" height="200" src="extensions/BMO/web/images/stop-sign.gif"></td>
+<td align="center" valign="middle">
+<font size="+2"><b>
+Are you here because you have a problem with
+<a href="http://www.mozilla.com/firefox/">Firefox</a> or
+<a href="http://www.mozilla.com/thunderbird/">Thunderbird</a>?</b><br>
+<b>If so, you're in the wrong place.</b></font><br>
+
+If you are having a problem with Firefox,
+<a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Firefox">file
+your [% terms.bug %] in the Firefox product</a>.<br>
+
+If you are having a problem with Thunderbird,
+<a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Thunderbird">file
+your [% terms.bug %] in the Thunderbird product</a>.<br>
+
+If none of those is a good fit for your [% terms.bug %], you can pick from
+the <a href="https://bugzilla.mozilla.org/enter_bug.cgi">full product list</a>.
+</td></tr></table>
+
+</p>
+
+<h3>Step 0 - Make sure you are in the right place</h3>
+
+ [% END %]
+
+<p>
+<b>The product you have chosen is for [% terms.bug %] reports and enhancement requests for the
+<a href="http://www.bugzilla.org/">Bugzilla [% terms.bug %] tracking software</a> only.</b>
+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 %]
+ Please <a href="https://bugzilla.mozilla.org/enter_bug.cgi">choose a different product</a>.
+[% END %]
+</p>
+
+<p><b>We WILL NOT accept [% terms.bug %] reports for Bugzilla
+installed via the Debian packaging system. If you obtained Bugzilla from Debian,
+please visit the <a href="http://www.debian.org/support">Debian Support page</a>,
+or file a bug on the <a href="http://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=bugzilla">Debian
+Bug Tracker</a>.</b> 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.</p>
+
+<p>
+Bugs specific to bugzilla.mozilla.org, rather than the Bugzilla software in
+general (which is used by many sites), should be filed in the
+<a href="enter_bug.cgi?product=mozilla.org">mozilla.org product</a>.
+</p>
+
+<p>
+Please do not file test [% terms.bugs %] or support requests here! You
+can test Bugzilla at
+<a href="http://landfill.bugzilla.org/">landfill.bugzilla.org</a> and ask
+for support in the
+<a href="news://news.mozilla.org/mozilla.support.bugzilla">
+mozilla.support.bugzilla newsgroup</a>,
+<a href="mailto:support-bugzilla&#64;lists.mozilla.org">
+support-bugzilla&#64;lists.mozilla.org mailing list</a>, or
+<a href="irc://irc.mozilla.org/mozwebtools">#mozwebtools IRC channel</a>.
+</p>
+
+<hr>
+
+[% ELSE %]
+
+ [% IF format != "guided" %]
+<p>
+[% UNLESS cloned_bug_id %]
+Consider using the
+<a href="enter_bug.cgi?product=[% product.name FILTER html %]&amp;format=guided">
+Bugzilla Helper</a> instead of this form.
+[% END +%]
+Before reporting a [% terms.bug %], make sure you've read our
+<a href="http://www.mozilla.org/quality/bug-writing-guidelines.html">
+[% terms.bug %] writing guidelines</a> and double checked that your [% terms.bug %] hasn't already
+been reported. Consult our list of
+<a href="https://bugzilla.mozilla.org/duplicates.cgi">
+most frequently reported [% terms.bugs %]</a> and
+<a href="https://bugzilla.mozilla.org/query.cgi">search through descriptions</a>
+of previously reported [% terms.bugs %].
+</p>
+ [% ELSE %]
+<p>
+ This form prompts you for the information required to
+ file a good [% terms.bug %] report (or enhancement request.)
+ It may seem lengthy, but developers need all this information
+ to understand and reproduce the [% terms.bug %], which is the first step towards
+ fixing it. Please note that <strong>we do not accept [% terms.bug %] reports by
+ email</strong> - please do not email developers or mozilla.org staff
+ with [% terms.bug %] reports. <font color="red">Also, please do not
+ file [% terms.bugs %] on browser/email software older than two weeks - first,
+ download a newer build of
+ <a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/">Firefox</a>,
+ <a href="http://ftp.mozilla.org/pub/mozilla.org/thunderbird/nightly/latest-comm-central/">Thunderbird</a>,
+ <a href="http://ftp.mozilla.org/pub/mozilla.org/seamonkey/nightly/latest-comm-central-trunk/">SeaMonkey</a>,
+ or
+ <a href="http://ftp.mozilla.org/pub/mozilla.org/camino/nightly/">Camino</a>
+ and check that the problem is still present.
+ </font>
+</p>
+ [% END %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/global/choose-product.html.tmpl b/extensions/BMO/template/en/default/global/choose-product.html.tmpl
new file mode 100644
index 000000000..a65605a93
--- /dev/null
+++ b/extensions/BMO/template/en/default/global/choose-product.html.tmpl
@@ -0,0 +1,182 @@
+[%# 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 <gerv@gerv.net>
+ #%]
+
+[%# INTERFACE:
+ # classifications: array of hashes, with an 'object' key representing a
+ # classification object and 'products' the list of
+ # product objects the user can enter bugs into.
+ # target: the script that displays this template.
+ # cloned_bug_id: ID of the bug being cloned.
+ # format: the desired format to display the target.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% IF target == "enter_bug.cgi" %]
+ [% title = "Enter $terms.Bug" %]
+ [% h2 = BLOCK %]First, you must pick a product on which to enter [% terms.abug %]. [% END %]
+[% ELSIF target == "describecomponents.cgi" %]
+ [% title = "Browse" %]
+ [% h2 = "Please specify the product whose components you want described." %]
+[% END %]
+
+[% DEFAULT title = "Choose a Product" %]
+[% PROCESS global/header.html.tmpl %]
+
+<center>
+<hr>
+<p><span style="font-family: verdana,helvetica;">Looking for technical support or help getting your site to work with Mozilla? <a href="http://www.mozilla.org/support/">Visit the mozilla.org support page</a> before filing bugs.</span></p>
+<hr>
+</center>
+
+<br>
+[% USE Bugzilla %]
+[% cgi = Bugzilla.cgi %]
+[% SET classification = cgi.param('classification') %]
+[% IF NOT ((cgi.param("full")) OR (user.settings.product_chooser.value == 'full_product_chooser')) %]
+[% IF target == "enter_bug.cgi" %]
+<h2 align="center">Which product is affected by the problem you would like to report?</h2>
+[% END %]
+<table align="center" border="0" width="600" cellpadding="5" cellspacing="0">
+[% INCLUDE easyproduct
+ name="Core"
+ icon="dino.png"
+%]
+[% INCLUDE easyproduct
+ name="Firefox"
+ icon="firefox.png"
+%]
+[% INCLUDE easyproduct
+ name="Thunderbird"
+ icon="thunderbird.png"
+%]
+[% INCLUDE easyproduct
+ name="Calendar"
+ icon="sunbird.png"
+%]
+[% INCLUDE easyproduct
+ name="Camino"
+ icon="camino.png"
+%]
+[% INCLUDE easyproduct
+ name="SeaMonkey"
+ icon="seamonkey.png"
+%]
+[% INCLUDE easyproduct
+ name="Fennec"
+ icon="fennec.png"
+%]
+[% INCLUDE easyproduct
+ name="Mozilla Localizations"
+ icon="dino.png"
+%]
+[% INCLUDE easyproduct
+ name="Mozilla Labs"
+ icon="labs.png"
+%]
+[% INCLUDE easyproduct
+ name="Mozilla Services"
+ icon="dino.png"
+%]
+<tr>
+ <td><a href="[% target FILTER uri i%]?full=1
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF classification %]&amp;classification=[% classification FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ <img src="extensions/BMO/web/producticons/other.png" height="64" width="64" border="0"></a></td>
+ <td><h2 align="left" style="margin-bottom: 0px;"><a href="[% target FILTER uri i%]?full=1
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF classification %]&amp;classification=[% classification FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ Other Products</a></h2>
+ <p style="margin-top: 0px;">Other Mozilla products which aren't listed here</p>
+ </td>
+</tr>
+</table>
+[% ELSE %]
+<h2>[% h2 FILTER html %]</h2>
+
+<table>
+
+[% FOREACH c = classifications %]
+ [% IF c.object %]
+ <tr>
+ <td align="right"><h2>[% c.object.name FILTER html %]</h2></td>
+ <td><strong>[%+ c.object.description FILTER html_light %]</strong></td>
+ </tr>
+ [% END %]
+
+ [% FOREACH p = c.products %]
+ <tr>
+ <th align="right" valign="top">
+ [% IF p.name == "Mozilla PR" AND target == "enter_bug.cgi" AND NOT format AND NOT cgi.param("debug") %]
+ <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END %]&amp;format=mozpr">
+ [% p.name FILTER html FILTER no_break %]</a>:&nbsp;
+ [% ELSE %]
+ <a href="[% target FILTER uri %]?product=[% p.name FILTER uri -%]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ [% p.name FILTER html FILTER no_break %]</a>:&nbsp;
+ [% END %]
+ </th>
+ <td valign="top">[% p.description FILTER html_light %]</td>
+ </tr>
+ [% END %]
+[% END %]
+
+</table>
+
+<br>
+[% IF target == "enter_bug.cgi" AND user.settings.product_chooser.value != 'full_product_chooser' %]
+<p align="center">You can choose to get this screen by default when you click "New Bug" by changing your <a href="userprefs.cgi?tab=settings">preferences</a>.</p>
+[% END %]
+[% END %]
+<br>
+
+[% PROCESS global/footer.html.tmpl %]
+
+[%###########################################################################%]
+[%# Block for "easy" product sections #%]
+[%###########################################################################%]
+
+[% BLOCK easyproduct %]
+ [% FOREACH c = classifications %]
+ [% FOREACH p = c.products %]
+ [% IF p.name == name %]
+ <tr>
+ <td><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ <img src="extensions/BMO/web/producticons/[% icon FILTER uri %]" height="64" width="64" border="0"></a></td>
+ <td><h2 align="left" style="margin-bottom: 0px"><a href="[% target FILTER uri %]?product=[% p.name FILTER uri %]
+ [%- IF cloned_bug_id %]&amp;cloned_bug_id=[% cloned_bug_id FILTER uri %][% END -%]
+ [%- IF format %]&amp;format=[% format FILTER uri %][% END %]">
+ [% p.name FILTER html FILTER no_break %]</a>:</h2>
+ [% IF p.description %]
+ <p style="margin-top: 0px;">[% p.description FILTER html_light %]</p>
+ [% END %]
+ </td>
+ </tr>
+ [% LAST %]
+ [% END %]
+ [% END %]
+ [% END %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl
new file mode 100644
index 000000000..3dc727b87
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-mimetypes.html.tmpl
@@ -0,0 +1,2 @@
+[% mimetypes.push({type => "image/svg+xml", desc => "SVG image"}) %]
+[% mimetypes.push({type => "application/vnd.mozilla.xul+xml", desc => "XUL"}) %] \ No newline at end of file
diff --git a/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl
new file mode 100644
index 000000000..ea80fdc5e
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/attachment/createformcontents-patch_notes.html.tmpl
@@ -0,0 +1 @@
+<em>You can <a href="http://developer.mozilla.org/en/docs/Getting_your_patch_in_the_tree">read about the patch submission and approval process</a>.</em><br>
diff --git a/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl
new file mode 100644
index 000000000..fd5477c9f
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/comments-comment_banner.html.tmpl
@@ -0,0 +1,7 @@
+[%# *** Disclaimer for Legal bugs *** %]
+[% IF bug.product == "Legal" %]
+ <div id="legal_disclaimer">
+ The material and information contained herein is Confidential and
+ subject to Attorney-Client Privilege and Work Product Doctrine.
+ </div>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl
new file mode 100644
index 000000000..1b1f1d67d
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/create/create-form.html.tmpl
@@ -0,0 +1,18 @@
+ <tr>
+ <th>Security:</th>
+ <td colspan="3">
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+
+ <input type="checkbox" name="groups"
+ value="[% sec_group FILTER none %]" id="groups"
+ [% FOREACH g = group %]
+ [% IF g.name == sec_group %]
+ [% " checked=\"checked\"" IF g.checked %]
+ [% END %]
+ [% END %]
+ >
+ <label for="groups">Many users could be harmed by this security problem:
+ it should be kept hidden from the public until it is resolved.</label>
+ <br><br>
+ </td>
+ </tr>
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
new file mode 100644
index 000000000..ee88aac7c
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/create/create-guided-form.html.tmpl
@@ -0,0 +1,22 @@
+ <tr bgcolor="[% tablecolour %]">
+ <td valign="middle" align="right">
+ <b>Security</b>
+ </td>
+ <td valign="top">
+ <p>
+ [% sec_group = sec_groups.${product.name} || sec_groups._default %]
+
+ <input type="checkbox" name="groups"
+ id="groups" value="[% sec_group FILTER none %]"
+ [% FOREACH g = group %]
+ [% IF g.name == sec_group %]
+ [% " checked=\"checked\"" IF g.checked %]
+ [% END %]
+ [% END %]
+ >
+ <label for="groups">
+ Many users could be harmed by this security problem: it should be kept
+ hidden from the public until it is resolved.</label>
+ </p>
+ </td>
+ </tr>
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
new file mode 100644
index 000000000..0c68d8e72
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/edit-after_custom_fields.html.tmpl
@@ -0,0 +1,83 @@
+[%# ***** BEGIN LICENSE BLOCK *****
+ # Version: MPL 1.1
+ #
+ # 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 Developer are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <glob@mozilla.com>
+ #
+ # ***** END LICENSE BLOCK *****
+ #%]
+
+[% show_custom_flags = 0 %]
+[% FOREACH field = Bugzilla.active_custom_fields %]
+ [% NEXT IF NOT user.id AND bug.${field.name} == "---" %]
+ [% NEXT IF cf_hidden_in_product(field.name, bug.product, bug.component, 2) %]
+ [% show_custom_flags = 1 %]
+ [% LAST %]
+[% END %]
+
+[% IF show_custom_flags %]
+ [% custom_flags = [] %]
+ <tr>
+ <td class="" colspan="2">
+ <label><b>Tracking Flags:</b></label>
+ [% IF user.id %]
+ <span id="edit_tracking_fields_action">
+ (<a onclick="bmo_show_tracking_flags()" href="javascript:void(0)">edit</a>)
+ </span>
+ [% END %]
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table id="custom-flags">
+ [% 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) %]
+ <tr id="row_[% field.name FILTER js %]">
+ <td>&nbsp;</td>
+ <td>
+ <label for="[% field.name FILTER html %]">
+ [% field_descs.${field.name} FILTER html %]:
+ </label>
+ </td>
+ <td>
+ [% PROCESS bug/field.html.tmpl value = bug.${field.name}
+ editable = user.id
+ no_tds = 1 %]
+ [% IF user.id %]
+ <span id="ro_[% field.name FILTER html %]" class="bz_hidden">
+ [% bug.${field.name} FILTER html %]
+ </span>
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+ </td>
+ </tr>
+ <script type="text/javascript">
+ var bmo_custom_flags = new Array([% custom_flags.size FILTER none %]);
+ [% FOREACH field_name = custom_flags %]
+ bmo_custom_flags['[% field_name FILTER js %]'] = '[% bug.${field_name} FILTER js %]';
+ [% END %]
+ bmo_hide_tracking_flags();
+ </script>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl
new file mode 100644
index 000000000..70132d7e0
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/field-help-end.none.tmpl
@@ -0,0 +1,114 @@
+[%# 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 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):
+ # Dave Lawrence <dkl@mozilla.com>
+ #%]
+
+[% USE Bugzilla %]
+[% IF Bugzilla.request_cache.bmo_fields_page %]
+ [% filtered_severity_blocker = display_value("bug_severity", "blocker") FILTER html %]
+ [% filtered_severity_critical = display_value("bug_severity", "critical") FILTER html %]
+ [% filtered_severity_major = display_value("bug_severity", "major") FILTER html %]
+ [% filtered_severity_normal = display_value("bug_severity", "normal") FILTER html %]
+ [% filtered_severity_minor = display_value("bug_severity", "minor") FILTER html %]
+ [% filtered_severity_trivial = display_value("bug_severity", "trivial") FILTER html %]
+ [% filtered_severity_enhancement = display_value("bug_severity", "enhancement") FILTER html %]
+
+ [% filtered_platform_all = display_value("rep_platform", "All") FILTER html %]
+ [% filtered_platform_x86_64 = display_value("rep_platform", "x86_64") FILTER html %]
+ [% filtered_platform_arm = display_value("rep_platform", "ARM") FILTER html %]
+
+ [% filtered_opsys_all = display_value("op_sys", "All") FILTER html %]
+ [% filtered_opsys_windows = display_value("op_sys", "Windows 7") FILTER html %]
+ [% filtered_opsys_mac = display_value("op_sys", "Mac OS X") FILTER html %]
+ [% filtered_opsys_linux = display_value("op_sys", "Linux") FILTER html %]
+
+ [% filtered_status_new = display_value("bug_status", "NEW") FILTER html %]
+
+ [%
+ vars.help_html.priority =
+ "This field describes the importance and order in which $terms.abug
+ should be fixed compared to other ${terms.bugs}. This field is utilized
+ by the programmers/engineers to prioritize their work to be done."
+
+ vars.help_html.bug_severity =
+ "This field describes the impact of ${terms.abug}.
+ <table>
+ <tr>
+ <th>$filtered_severity_blocker</th>
+ <td>Blocks development and/or testing work</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_critical</th>
+ <td>crashes, loss of data, severe memory leak</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_major</th>
+ <td>major loss of function</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_normal</th>
+ <td>regular issue, some loss of functionality under specific circumstances</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_minor</th>
+ <td>minor loss of function, or other problem where easy
+ workaround is present</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_trivial</th>
+ <td>cosmetic problem like misspelled words or misaligned
+ text</td>
+ </tr>
+ <tr>
+ <th>$filtered_severity_enhancement</th>
+ <td>Request for enhancement</td>
+ </table>"
+
+ vars.help_html.rep_platform =
+ "This is the hardware platform against which the $terms.bug was reported.
+ Legal platforms include:
+ <ul>
+ <li>$filtered_platform_all (happens on all platforms; cross-platform ${terms.bug})</li>
+ <li>$filtered_platform_x86_64</li>
+ <li>$filtered_platform_arm</li>
+ </ul>
+ <b>Note:</b> When searching, selecting the option
+ <em>$filtered_platform_all</em> does not
+ select $terms.bugs assigned against any platform. It merely selects
+ $terms.bugs that are marked as occurring on all platforms, i.e. are
+ designated <em>$filtered_platform_all</em>.",
+
+ vars.help_html.op_sys =
+ "This is the operating system against which the $terms.bug was
+ reported. Legal operating systems include:
+ <ul>
+ <li>$filtered_opsys_all (happens on all operating systems; cross-platform ${terms.bug})</li>
+ <li>$filtered_opsys_windows</li>
+ <li>$filtered_opsys_mac</li>
+ <li>$filtered_opsys_linux</li>
+ </ul>
+ Sometimes the operating system implies the platform, but not
+ always. For example, Linux can run on x86_64, ARM, and others.",
+
+ vars.help_html.assigned_to =
+ "This is the person in charge of resolving the ${terms.bug}. Every time
+ this field changes, the status changes to
+ <b>$filtered_status_new</b> to make it
+ easy to see which new $terms.bugs have appeared on a person's list.</p>",
+ %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl
new file mode 100644
index 000000000..55e428e01
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/bug/show-header-end.html.tmpl
@@ -0,0 +1,27 @@
+[%# ***** BEGIN LICENSE BLOCK *****
+ # Version: MPL 1.1
+ #
+ # 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 Developer are Copyright (C) 2011 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Byron Jones <glob@mozilla.com>
+ #
+ # ***** END LICENSE BLOCK *****
+ #%]
+
+[% style_urls.push('extensions/BMO/web/styles/edit_bug.css') %]
+[% javascript_urls.push('extensions/BMO/web/js/edit_bug.js') %]
diff --git a/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl
new file mode 100644
index 000000000..b5bb4719c
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/footer-outro.html.tmpl
@@ -0,0 +1 @@
+<a href="https://www.mozilla.org/about/policies/privacy-policy.html">Privacy Policy</a>
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
new file mode 100644
index 000000000..0277f3e7e
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/header-additional_header.html.tmpl
@@ -0,0 +1,60 @@
+[%#
+ # 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 BMOHeader Bugzilla Extension.
+ #
+ # The Initial Developer of the Original Code is Reed Loden.
+ # Portions created by the Initial Developer are Copyright (C) 2010 the
+ # Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+<link rel="shortcut icon" href="extensions/BMO/web/images/bugzilla.png">
+[% IF bug %]
+<link id="shorturl" rev="canonical" href="https://bugzil.la/[% bug.bug_id %]">
+[% END %]
+
+<style type="text/css">
+body {
+ background: url("extensions/BMO/web/images/background.png") repeat-x;
+}
+</style>
+
+[%# *** Bug List Navigation *** %]
+[% IF bug %]
+ [% SET my_search = user.recent_search_for(bug) %]
+ [% IF my_search %]
+ [% SET last_bug_list = my_search.bug_list %]
+ [% SET this_bug_idx = lsearch(last_bug_list, bug.id) %]
+ <link rel="Up" href="buglist.cgi?regetlastlist=
+ [%- my_search.id FILTER uri %]">
+ <link rel="First" href="show_bug.cgi?id=
+ [%- last_bug_list.first FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ <link rel="Last" href="show_bug.cgi?id=
+ [%- last_bug_list.last FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% IF this_bug_idx > 0 %]
+ [% prev_bug = this_bug_idx - 1 %]
+ <link rel="Prev" href="show_bug.cgi?id=
+ [%- last_bug_list.$prev_bug FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% END %]
+ [% IF this_bug_idx + 1 < last_bug_list.size %]
+ [% next_bug = this_bug_idx + 1 %]
+ <link rel="Next" href="show_bug.cgi?id=
+ [%- last_bug_list.$next_bug FILTER uri %]&amp;list_id=
+ [%- my_search.id FILTER uri %]">
+ [% END %]
+ [% END %]
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl
new file mode 100644
index 000000000..3c2f90e19
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/header-start.html.tmpl
@@ -0,0 +1,3 @@
+[% IF template.name == 'list/list.html.tmpl' %]
+ [% javascript_urls.push('extensions/BMO/web/js/sorttable.js') %]
+[% END %] \ No newline at end of file
diff --git a/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl
new file mode 100644
index 000000000..666621d8b
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/setting-descs-settings.none.tmpl
@@ -0,0 +1,5 @@
+[%
+ setting_descs.product_chooser = "Product chooser to use when entering bugs",
+ setting_descs.pretty_product_chooser = "Pretty chooser with common products and icons",
+ setting_descs.full_product_chooser = "Full chooser with all products",
+%]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
new file mode 100644
index 000000000..067347f3b
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error-auth_failure_object.html.tmpl
@@ -0,0 +1,3 @@
+[% IF object == 'group_admins' %]
+ the group administrators report
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl
new file mode 100644
index 000000000..85881aca7
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error-errors.html.tmpl
@@ -0,0 +1,40 @@
+[%# 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 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 <bjones@mozilla.com>
+ #%]
+
+[% IF error == "user_activity_missing_username" %]
+ [% title = "Missing Username" %]
+ You must provide at least one email address to report on.
+
+[% ELSIF error == "user_activity_missing_from_date" %]
+ [% title = "Missing Date" %]
+ You must provided the period start date.
+
+[% ELSIF error == "user_activity_missing_to_date" %]
+ [% title = "Missing Date" %]
+ You must provided the period end date.
+
+[% ELSIF error == "user_activity_invalid_date" %]
+ [% title = "Invalid Date" %]
+ The date '[% date FILTER html %]' is invalid.
+
+[% ELSIF error == "invalid_object" %]
+ Invalid [% object FILTER html %]: "[% value FILTER html %]"
+
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl
new file mode 100644
index 000000000..5f6ca946a
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/user-error.html.tmpl/auth_failure/permissions.html.tmpl
@@ -0,0 +1,29 @@
+<!-- 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Gervase Markham <gerv@gerv.net>
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+[% IF (group == "canconfirm" OR group == "editbugs") AND !reason %]
+ <p>
+ If you are attempting to confirm an unconfirmed bug or edit the fields of a bug,
+ <a href="http://www.gerv.net/hacking/before-you-mail-gerv.html#bugzilla-permissions">find
+ out how to get the necessary permissions</a>.
+ </p>
+[% END %]
diff --git a/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl
new file mode 100644
index 000000000..89eef6fc4
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/global/variables-end.none.tmpl
@@ -0,0 +1,3 @@
+[%
+ terms.BugzillaTitle = "Bugzilla@Mozilla"
+%]
diff --git a/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl
new file mode 100644
index 000000000..56a133c6c
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/index-additional_links.html.tmpl
@@ -0,0 +1,10 @@
+<li>
+|
+<a href="page.cgi?id=etiquette.html">
+ [%- terms.Bugzilla %] Etiquette</a>
+</li>
+<li>
+|
+<a href="https://developer.mozilla.org/en/Bug_writing_guidelines">
+ [%- terms.Bug %] Writing Guidelines</a>
+</li>
diff --git a/extensions/BMO/template/en/default/hook/index-intro.html.tmpl b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl
new file mode 100644
index 000000000..d81d91491
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/index-intro.html.tmpl
@@ -0,0 +1,2 @@
+<a id="get_help" class="bz_common_actions"
+ href="page.cgi?id=get_help.html"><span>Get Help</span></a> \ No newline at end of file
diff --git a/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl
new file mode 100644
index 000000000..4d12ab345
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/pages/fields-resolution.html.tmpl
@@ -0,0 +1,13 @@
+<dt>
+ [% display_value("resolution", "INCOMPLETE") FILTER html %]
+</dt>
+<dd>
+ The problem is vaguely described with no steps to reproduce,
+ or is a support request. The reporter should be directed to the
+ product's support page for help diagnosing the issue. If there
+ are only a few comments in the [% terms.bug %], it may be reopened only if
+ the original reporter provides more info, or confirms someone
+ else's steps to reproduce. If the [% terms.bug %] is long, when enough info
+ is provided a new [% terms.bug %] should be filed and the original [% terms.bug %]
+ marked as a duplicate of it.
+</dd>
diff --git a/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl b/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl
new file mode 100644
index 000000000..4d12ab345
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/pages/fields-resolutions.html.tmpl
@@ -0,0 +1,13 @@
+<dt>
+ [% display_value("resolution", "INCOMPLETE") FILTER html %]
+</dt>
+<dd>
+ The problem is vaguely described with no steps to reproduce,
+ or is a support request. The reporter should be directed to the
+ product's support page for help diagnosing the issue. If there
+ are only a few comments in the [% terms.bug %], it may be reopened only if
+ the original reporter provides more info, or confirms someone
+ else's steps to reproduce. If the [% terms.bug %] is long, when enough info
+ is provided a new [% terms.bug %] should be filed and the original [% terms.bug %]
+ marked as a duplicate of it.
+</dd>
diff --git a/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl
new file mode 100644
index 000000000..6e8463020
--- /dev/null
+++ b/extensions/BMO/template/en/default/hook/reports/menu-end.html.tmpl
@@ -0,0 +1,41 @@
+[%# 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 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 <bjones@mozilla.com>
+ #%]
+
+<h2>Other Reports</h2>
+
+<ul>
+ <li>
+ <strong><a href="[% urlbase FILTER none
+ %]page.cgi?id=user_activity.html">User Changes</a></strong> - Show changes
+ made by an individual user.
+ </li>
+ <li>
+ <strong><a href="[% urlbase FILTER none
+ %]page.cgi?id=triage_reports.html">Triage Report</a></strong> - Report
+ on UNCONFIRMED [% terms.bugs %] to assist triage.
+ </li>
+ [% IF user.in_group('editusers') %]
+ <li>
+ <strong><a href="[% urlbase FILTER none
+ %]page.cgi?id=group_admins.html">Group Admins</a></strong> - Group Admins Report
+ </li>
+ [% END %]
+</ul>
+
diff --git a/extensions/BMO/template/en/default/list/list.microsummary.tmpl b/extensions/BMO/template/en/default/list/list.microsummary.tmpl
new file mode 100644
index 000000000..8f6b13cbd
--- /dev/null
+++ b/extensions/BMO/template/en/default/list/list.microsummary.tmpl
@@ -0,0 +1,29 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Ronaldo Maia <rmaia@everythingsolved.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+
+[% IF searchname %]
+ [% searchname %] ([% bugs.size %])
+[% ELSE %]
+ [% terms.Bug %] List ([% bugs.size %])
+[% END %]
diff --git a/extensions/BMO/template/en/default/list/server-push.html.tmpl b/extensions/BMO/template/en/default/list/server-push.html.tmpl
new file mode 100644
index 000000000..40432a35b
--- /dev/null
+++ b/extensions/BMO/template/en/default/list/server-push.html.tmpl
@@ -0,0 +1,52 @@
+[%# 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Myk Melez <myk@mozilla.org>
+ #%]
+
+[%# INTERFACE:
+ # debug: boolean. True if we want the search displayed while we wait.
+ # query: string. The SQL query which makes the buglist.
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+<html>
+ <head>
+ <title>[% terms.Bugzilla %] is pondering your search</title>
+ </head>
+ <body>
+ <div style="margin-top: 15%; text-align: center;">
+ <center><img src="extensions/BMO/web/images/mozchomp.gif" alt=""
+ width="160" height="87"></center>
+ <h1>Please wait while your bugs are retrieved.</h1>
+ </div>
+
+ [% IF debug %]
+ <p>
+ [% FOREACH debugline = debugdata %]
+ <code>[% debugline FILTER html %]</code><br>
+ [% END %]
+ </p>
+ <p>
+ <code>[% query FILTER html %]</code>
+ </p>
+ [% END %]
+
+ </body>
+</html>
diff --git a/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
new file mode 100644
index 000000000..f326d1821
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/bug-writing.html.tmpl
@@ -0,0 +1,25 @@
+[%# 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): David Lawrence <dkl@mozilla.com>
+ #%]
+
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0;url=https://developer.mozilla.org/en/Bug_writing_guidelines">
+ </head>
+</html>
diff --git a/extensions/BMO/template/en/default/pages/etiquette.html.tmpl b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
new file mode 100644
index 000000000..281057eeb
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/etiquette.html.tmpl
@@ -0,0 +1,147 @@
+<!-- 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 Netscape Communications
+ # Corporation. Portions created by Netscape are
+ # Copyright (C) 1998 Netscape Communications Corporation. All
+ # Rights Reserved.
+ #
+ # Contributor(s): Stefan Seifert <nine@detonation.org>
+ # Gervase Markham <gerv@gerv.net>
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Bugzilla Etiquette"
+ style = "li { margin: 5px } .heading { font-weight: bold }" %]
+
+<p>
+ There's a number of <i lang="fr">faux pas</i> you can commit when using
+ Bugzilla. At the very
+ least, these will make Mozilla contributors upset at you; if committed enough
+ times they will cause those contributors to demand the disabling of your
+ Bugzilla account. So, ignore this advice at your peril.
+</p>
+
+<p>
+ That said, Mozilla developers are generally a friendly bunch, and will be
+ friendly towards you as long as you follow these guidelines.
+</p>
+
+<h3>1. Commenting</h3>
+
+<p>
+ This is the most important section.
+</p>
+
+<ol>
+ <li>
+ <span class="heading">No pointless comments</span>.
+ Unless you have something constructive and helpful to say, do not add a
+ comment to a bug. In bugs where there is a heated debate going on, you
+ should be even more
+ inclined not to add a comment. Unless you have something new to contribute,
+ then the bug owner is aware of all the issues, and will make a judgement
+ as to what to do. If you agree the bug should be fixed, vote for it.
+ Additional "I see this too" or "It works for me" comments are unnecessary
+ unless they are on a different platform or a significantly different build.
+ Constructive and helpful thoughts unrelated to the topic of the bug
+ should go in the appropriate
+ <a href="http://www.mozilla.org/about/forums/">newsgroup</a>.
+ </li>
+
+ <li>
+ <span class="heading">No obligation</span>.
+ "Open Source" is not the same as "the developers must do my bidding."
+ Everyone here wants to help, but the only person who has any
+ <i>obligation</i> to fix the bugs you want fixed is you. Therefore, you
+ should not act as if you expect someone to fix a bug by a particular date
+ or release. Aggressive or repeated demands will not be received
+ well and will almost certainly diminish the impact and interest in your
+ suggestions.
+ </li>
+
+ <li>
+ <span class="heading">No abusing people</span>.
+ Constant and intense critique is one of the reasons we build great products.
+ It's harder to fall into group-think if there is always a healthy amount of
+ dissent. We want to encourage vibrant debate inside of the Mozilla
+ community, we want you to disagree with us, and we want you to effectively
+ argue your case. However, we require that in the process, you attack
+ <i>things</i>, not <i>people</i>. Examples of things include: interfaces,
+ algorithms, and schedules. Examples of people include: developers,
+ designers and users. <b>Attacking a person may result in you being banned
+ from Bugzilla.</b>
+ </li>
+
+ <li>
+ <span class="heading">No private email</span>.
+ Unless the bug owner or another respected project contributor has asked you
+ to email them with specific information, please place all information
+ relating to bugs
+ in the bug itself. Do not send them by private email; no-one else can read
+ them if you do that, and they'll probably just get ignored. If a file
+ is too big for Bugzilla, add a comment giving the file size and contents
+ and ask what to do.
+ </li>
+</ol>
+
+<h3>2. Changing Fields</h3>
+
+<ol>
+ <li>
+ <span class="heading">No messing with other people's bugs</span>.
+ Unless you are the bug assignee, or have some say over the use of their
+ time, never change the Priority or Target Milestone fields. If in doubt,
+ do not change the fields of bugs you do not own - add a comment
+ instead, suggesting the change.
+ </li>
+
+ <li>
+ <span class="heading">No whining about decisions</span>.
+ If a respected project contributor has marked a bug as INVALID, then it is
+ invalid. Someone filing another duplicate of it does not change this. Unless
+ you have further important evidence, do not post a comment arguing that an
+ INVALID or WONTFIX bug should be reopened.
+ </li>
+
+</ol>
+
+<h3>3. Applicability</h3>
+
+<ol>
+ <li>
+ Some of these rules may not apply to you. If they do not, you will know
+ exactly which ones do not, and why they do not apply. If you are not
+ sure, then they definitely all apply to you.
+ </li>
+</ol>
+
+<p>
+ If you see someone not following these rules, the first step is, as an exception
+ to guideline 1.4, to make them aware of this document by <em>private</em> mail.
+ Flaming people publically in bugs violates guidelines 1.1 and 1.3. In the case of
+ persistent offending you should report the matter to
+ <a href="mailto:gerv@mozilla.org">Gerv</a>.
+</p>
+
+<p>
+ This entire document can be summed up in one sentence:
+ do unto others as you would have them do unto you.
+</p>
+
+<p>
+ Other useful documents:
+ <a href="page.cgi?id=bug-writing.html">The Bug Writing Guidelines</a>.
+</p>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/get_help.html.tmpl b/extensions/BMO/template/en/default/pages/get_help.html.tmpl
new file mode 100644
index 000000000..70ff0a12b
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/get_help.html.tmpl
@@ -0,0 +1,42 @@
+[%# 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): David Miller <justdave@bugzilla.org>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% INCLUDE global/header.html.tmpl title = "Get Help with Mozilla Products" %]
+
+<div id="steps">
+<h2>Got a problem?</h2>
+
+<ul>
+<li><a href="http://www.mozilla.org/support/">Get help with your mozilla.org product</a></li>
+<li><a href="http://hendrix.mozilla.org/">Leave quick feedback</a></li>
+<li><a href="http://input.mozilla.com/feedback">Report a broken website</a></li>
+<li><a href="enter_bug.cgi">Report a [% terms.bug %]</a> - latest release only
+ [% IF NOT user.id %]
+ (you'll need an
+ <a href="createaccount.cgi">account</a>)
+ [% END %]
+</li>
+</ul>
+</div>
+
+<br>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/group_admins.html.tmpl b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
new file mode 100644
index 000000000..a55b6e2ad
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/group_admins.html.tmpl
@@ -0,0 +1,53 @@
+[%# 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 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):
+ # David Lawrence <dkl@mozilla.com>
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Group Admins Report"
+ style_urls = [ "extensions/BMO/web/styles/reports.css" ]
+%]
+
+[% IF groups.size > 0 %]
+ <table border="0" cellspacing="0" id="report" width="100%">
+ <tr id="report-header">
+ <th align="left">Name</th>
+ <th align="left">Admins</th>
+ </tr>
+
+ [% FOREACH group = groups %]
+ [% count = loop.count() %]
+ <tr class="report_item [% count % 2 == 1 ? "report_row_odd" : "report_row_even" %]">
+ <td>
+ [% group.name FILTER html %]
+ </td>
+ <td>
+ [% FOREACH admin = group.admins %]
+ [% INCLUDE global/user.html.tmpl who = admin %][% ", " UNLESS loop.last %]
+ [% END %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+[% ELSE %]
+ <p>
+ No groups found.
+ </p>
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl
new file mode 100644
index 000000000..023dc4791
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/triage_reports.html.tmpl
@@ -0,0 +1,199 @@
+[%# 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 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 <bjones@mozilla.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% js_data = BLOCK %]
+var useclassification = false;
+var first_load = true;
+var last_sel = [];
+var cpts = new Array();
+[% n = 1 %]
+[% FOREACH p = user.get_selectable_products %]
+ cpts['[% n FILTER js %]'] = [
+ [%- FOREACH c = p.components %]'[% c.name FILTER js %]'[% ", " UNLESS loop.last %] [%- END -%] ];
+ [% n = n+1 %]
+[% END %]
+
+var selected_components = [
+ [%- FOREACH c = input.component %]'[% c FILTER js %]'
+ [%- ',' UNLESS loop.last %] [%- END ~%] ];
+
+[% END %]
+
+[% INCLUDE global/header.html.tmpl
+ title = "Triage Reports"
+ yui = [ 'autocomplete', 'calendar' ]
+ javascript = js_data
+ javascript_urls = [ "js/util.js", "js/field.js", "js/productform.js",
+ "extensions/BMO/web/js/triage_reports.js" ]
+ style_urls = [ "skins/standard/buglist.css",
+ "extensions/BMO/web/styles/triage_reports.css" ]
+%]
+
+<noscript>
+<h2>Javascript is required to use this report.</h2>
+</noscript>
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+<form id="activity_form" name="activity_form" action="page.cgi" method="get"
+ onSubmit="return onGenerateReport()">
+<input type="hidden" name="id" value="triage_reports.html">
+<input type="hidden" name="action" value="run">
+
+Show UNCONFIRMED bugs with:
+<table id="triage_form">
+
+<tr>
+ <th>Product:</th>
+ <td>
+ <select name="product" id="product" onChange="onSelectProduct()">
+ <option value=""></option>
+ [% FOREACH p = user.get_selectable_products %]
+ <option value="[% p.name FILTER html %]"
+ [% " selected" IF input.product == p.name %]>
+ [% p.name FILTER html %]
+ </option>
+ [% END %]
+ </select>
+ </td>
+ <td rowspan="2" valign="top">
+ <b>Comment:</b><br>
+
+ <input type="checkbox" name="filter_commenter" id="filter_commenter" value="1"
+ [% 'checked' IF input.filter_commenter %]>
+ <label for="filter_commenter">where the last commenter</label>
+ <select name="commenter" id="commenter" onChange="onCommenterChange()">
+ <option value="reporter" [% 'selected' IF input.commenter == 'reporter' %]>is the reporter</option>
+ <option value="noconfirm" [% 'selected' IF input.commenter == 'noconfirm' %]>does not have canconfirm</option>
+ <option value="is" [% 'selected' IF input.commenter == 'is' %]>is</option>
+ </select>
+ [%+ INCLUDE global/userselect.html.tmpl
+ id => "commenter_is"
+ name => "commenter_is"
+ value => input.commenter_is
+ size => 20
+ emptyok => 0
+ classes = input.commenter == "is" ? "" : "hidden"
+ %]
+ <br>
+
+ <input type="checkbox" name="filter_last" id="filter_last" value="1"
+ [% 'checked' IF input.filter_last %]>
+ <label for="filter_last">where the last comment is older than</label>
+ <select name="last" id="last" onChange="onLastChange()">
+ <option value="30" [% 'selected' IF input.last == '30' %]>30 days</option>
+ <option value="60" [% 'selected' IF input.last == '60' %]>60 days</option>
+ <option value="90" [% 'selected' IF input.last == '90' %]>90 days</option>
+ <option value="365" [% 'selected' IF input.last == '365' %]>one year</option>
+ <option value="is" [% 'selected' IF input.last == 'is' %]>the date</option>
+ </select>
+ <span id="last_is_span" class="[% 'hidden' IF input.last != 'is' %]">
+ <input type="text" id="last_is" name="last_is" size="11" maxlength="10"
+ value="[% input.last_is FILTER html %]"
+ onChange="updateCalendarLastIs(this)">
+ <button type="button" class="calendar_button" id="button_calendar_last_is"
+ onClick="showCalendar('last_is')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_last_is"></div>
+ </span>
+ <br>
+ </td>
+</tr>
+
+<tr>
+ <th>Component:</th>
+ <td>
+ <select name="component" id="component" multiple size="5">
+ </select>
+ </td>
+</tr>
+
+<tr>
+ <td>&nbsp;</td>
+ <td>
+ <input type="submit" value="Generate Report">
+ </td>
+</tr>
+
+</table>
+
+</form>
+<script>
+ createCalendar('last_is');
+</script>
+
+[% IF input.action == 'run' %]
+<hr>
+[% IF bugs.size > 0 %]
+ <p>
+ Found [% bugs.size %] [%+ terms.bug %][% 's' IF bugs.size != 1 %]:
+ </p>
+ <table border="0" cellspacing="0" id="report" width="100%">
+ <tr id="report-header">
+ <th>Bug / Date</th>
+ <th>Summary</th>
+ <th>Reporter / Commenter</th>
+ <th>Comment Date</th>
+ <th>Last Comment</th>
+ </tr>
+
+ [% FOREACH bug = bugs %]
+ [% count = loop.count() %]
+ <tr class="bz_bugitem [% count % 2 == 1 ? "bz_row_odd" : "bz_row_even" %]">
+ <td>
+ [% bug.id FILTER bug_link(bug.id) FILTER none %]<br>
+ [% bug.creation_ts.replace(' .*' '') FILTER html FILTER no_break %]
+ </td>
+ <td>
+ [% bug.summary FILTER html %]
+ </td>
+ <td>
+ [% INCLUDE global/user.html.tmpl who = bug.reporter %]
+ [% IF bug.commenter.id != bug.reporter.id %]
+ <br>[% INCLUDE global/user.html.tmpl who = bug.commenter %]
+ [% END %]
+ </td>
+ <td>
+ [% bug.comment_ts FILTER html FILTER no_break %]
+ </td>
+ <td>
+ [% bug.comment FILTER html %]
+ </td>
+ </tr>
+ [% END %]
+ </table>
+
+ <p>
+ <a href="buglist.cgi?bug_id=
+ [%- FOREACH bug = bugs %][% bug.id FILTER uri %],[% END -%]
+ ">Show as a [% terms.Bug %] List</a>
+ </p>
+
+[% ELSE %]
+ <p>
+ No bugs found.
+ </p>
+[% END %]
+
+[% END %]
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl
new file mode 100644
index 000000000..8fa944ae6
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/upgrade-3.6.html.tmpl
@@ -0,0 +1,304 @@
+[%# 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): David Miller <justdave@bugzilla.org>
+ # Reed Loden <reed@reedloden.com>
+ #%]
+
+[% PROCESS global/variables.none.tmpl %]
+[% INCLUDE global/header.html.tmpl
+ title = "Bugzilla 3.6 Upgrade"
+%]
+[% USE date %]
+
+<p><b>Last Updated:</b> [% date.format(template.modtime, "%d-%b-%Y %H:%M %Z") %]</p>
+
+<p>On Friday, July 9, 2010, at 11:40pm PDT (0640 UTC), bugzilla.mozilla.org was
+ <a href="show_bug.cgi?id=558044">upgraded</a> to Bugzilla 3.6.1+. Please
+ <a href="enter_bug.cgi?product=mozilla.org&amp;component=Bugzilla:+Other+b.m.o+Issues&amp;blocked=bmo-regressions">file
+ any regressions</a> for tracking purposes.</p>
+
+<h3>Known Issues</h3>
+
+<p>The following is a list of issues which are known to be broken or incomplete with this upgrade so far.</p>
+
+<ul>
+
+<li>The <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=577801&hide_resolved=1">stuff filed in Bugzilla</a>.</li>
+
+</ul>
+
+<h3>What's New</h3>
+
+<h4>Custom bugzilla.mozilla.org Changes</h4>
+
+<ul>
+ <li>Addition of autocomplete support for all user-related fields (assignee,
+ QA contact, and CC list) and the keywords field.</li>
+ <li>New attachment details UI.</li>
+ <li>New icons for the front page.</li>
+ <li>Removal of unused "Patches" column from buglist.</li>
+ <li>Initial support for <a href="http://en.wikipedia.org/wiki/Strict_Transport_Security">Strict-Transport-Security</a> (STS) header.</li>
+</ul>
+
+<h4>General Usability Improvements</h4>
+
+<p>A <a href="https://wiki.mozilla.org/Bugzilla:CMU_HCI_Research_2008">scientific
+ usability study</a> was done on [% terms.Bugzilla %] by researchers
+ from Carnegie-Mellon University. As a result of this study,
+ <a href="https://bugzilla.mozilla.org/showdependencytree.cgi?id=490786&amp;hide_resolved=0">several
+ usability issues</a> were prioritized to be fixed, based on specific data
+ from the study.</p>
+
+<p>As a result, you will see many small improvements in [% terms.Bugzilla %]'s
+ usability, such as using Javascript to validate certain forms before
+ they are submitted, standardizing the words that we use in the user interface,
+ being clearer about what [% terms.Bugzilla %] needs from the user,
+ and other changes, all of which are also listed individually in this New
+ Features section.</p>
+
+<p>Work continues on improving usability for the next release of
+ [%+ terms.Bugzilla %], but the results of the research have already
+ had an impact on this 3.6 release.</p>
+
+<h4>Improved Quicksearch</h4>
+
+<p>The "quicksearch" box that appears on the front page of
+ [%+ terms.Bugzilla %] and in the header/footer of every page
+ is now simplified and made more powerful. There is a
+ <kbd>[?]</kbd> link next to the box that will take you to
+ the simplified <a href="page.cgi?id=quicksearch.html">Quicksearch Help</a>,
+ which describes every single feature of the system in a simple layout,
+ including new features such as the ability to use partial field names
+ when searching.</p>
+
+<p>Quicksearch should also be much faster than it was before, particularly
+ on large installations.</p>
+
+<p>Note that in order to implement the new quicksearch, certain old
+ and rarely-used features had to be removed:
+
+<ul>
+ <li><b>+</b> as a prefix to mean "search additional resolutions", and
+ <b>+</b> as a prefix to mean "search just the summary". You can
+ instead use <kbd>summary:</kbd> to explicitly search summaries.</li>
+ <li>Searching the Severity field if you type something that matches
+ the first few characters of a severity. You can explicitly search
+ the Severity field if you want to find [% terms.bugs %] by severity.</li>
+ <li>Searching the Priority field if you typed something that exactly
+ matched the name of a priority. You can explicitly search the
+ Priority field if you want to find [% terms.bugs %] by priority.</li>
+ <li>Searching the Platform and OS fields if you typed in one of a
+ certain hard-coded list of strings (like "pc", "windows", etc.).
+ You can explicitly search these fields, instead, if you want to
+ find [% terms.bugs %] with a specific Platform or OS set.</li>
+</ul>
+
+<h4>Simple "Browse" Interface</h4>
+
+<p>There is now a "Browse" link in the header of each [% terms.Bugzilla %]
+ page that presents a very basic interface that allows users to simply
+ browse through all open [% terms.bugs %] in particular components.</p>
+
+<h4>JSON-RPC Interface</h4>
+
+<p>[% terms.Bugzilla %] now has support for the
+ <a href="http://json-rpc.org/">JSON-RPC</a> WebServices protocol via
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Server/JSONRPC.html">jsonrpc.cgi</a>.
+ The JSON-RPC interface is experimental in this release--if you want any
+ fundamental changes in how it works,
+ <a href="http://www.bugzilla.org/developers/reporting_bugs.html">let us
+ know</a>, for the next release of [% terms.Bugzilla %].</p>
+
+<h3>New Features</h3>
+
+<h4>Enhancements for Users</h4>
+
+<ul>
+ <li><b>[% terms.Bug %] Filing:</b> When filing [% terms.abug %],
+ [%+ terms.Bugzilla %] now visually indicates which fields are
+ mandatory.</li>
+ <li><b>[% terms.Bug %] Filing:</b> "Bookmarkable templates" now
+ support the "alias" and "estimated hours" fields.</li>
+
+ <li><b>[% terms.Bug %] Editing:</b> In previous versions of
+ [%+ terms.Bugzilla %], if you added a private comment to [% terms.abug %],
+ then <em>none</em> of the changes that you made at that time were
+ sent to users who couldn't see the private comment. Now, for users
+ who can't see private comments, public changes are sent, but the private
+ comment is excluded from their email notification.</li>
+ <li><b>[% terms.Bug %] Editing:</b> The controls for groups now
+ appear to the right of the attachment and time-tracking tables,
+ when editing [% terms.abug %].</li>
+ <li><b>[% terms.Bug %] Editing:</b> The "Collapse All Comments"
+ and "Expand All Comments" links now appear to the right of the
+ comment list instead of above it.</li>
+ <li><b>[% terms.Bug %] Editing:</b> The See Also field now supports
+ URLs for Google Code Issues and the Debian B[% %]ug-Tracking System.</li>
+ <li><b>[% terms.Bug %] Editing:</b> There have been significant performance
+ improvements in <kbd>show_bug.cgi</kbd> (the script that displays the
+ [% terms.bug %]-editing form), particularly for [% terms.bugs %] that
+ have lots of comments or attachments.</li>
+
+ <li><b>Attachments:</b> The "Details" page of an attachment
+ now displays itself as uneditable if you can't edit the fields
+ there.</li>
+ <li><b>Attachments:</b> We now make sure that there is
+ a Description specified for an attachment, using JavaScript, before
+ the form is submitted.</li>
+ <li><b>Attachments:</b> There is now a link back to the [% terms.bug %]
+ at the bottom of the "Details" page for an attachment.</li>
+ <li><b>Attachments:</b> When you click on an "attachment 12345" link
+ in a comment, if the attachment is a patch, you will now see the
+ formatted "Diff" view instead of the raw patch.</li>
+ <li><b>Attachments</b>: For text attachments, we now let the browser
+ auto-detect the character encoding, instead of forcing the browser to
+ always assume the attachment is in UTF-8.</li>
+
+ <li><b>Search:</b> You can now display [% terms.bug %] flags as a column
+ in search results.</li>
+ <li><b>Search:</b> When viewing search results, you can see which columns are
+ being sorted on, and which direction the sort is on, as indicated
+ by arrows next to the column headers.</li>
+ <li><b>Search:</b> You can now search the Deadline field using relative
+ dates (like "1d", "2w", etc.).</li>
+ <li><b>Search:</b> The iCalendar format of search results now includes
+ a PRIORITY field.</li>
+ <li><b>Search:</b> It is no longer an error to enter an invalid search
+ order in a search URL--[% terms.Bugzilla %] will simply warn you that
+ some of your order options are invalid.</li>
+ <li><b>Search:</b> When there are no search results, some helpful
+ links are displayed, offering actions you might want to take.</li>
+ <li><b>Search:</b> For those who like to make their own
+ <kbd>buglist.cgi</kbd> URLs (and for people working on customizations),
+ <kbd>buglist.cgi</kbd> now accepts nearly every valid field in
+ [%+ terms.Bugzilla %] as a direct URL parameter, like
+ <kbd>&amp;field=value</kbd>.</li>
+
+ <li><b>Requests:</b> When viewing the "My Requests" page, you can now
+ see the lists as a normal search result by clicking a link at the
+ bottom of each table.</li>
+ <li><b>Requests:</b> When viewing the "My Requests" page, if you are
+ using Classifications, the Product drop-down will be grouped by
+ Classification.</li>
+
+ <li>If there are multiple languages available for your
+ [%+ terms.Bugzilla %], you can now select what language you want
+ [%+ terms.Bugzilla %] displayed in using links at the top of every
+ page.</li>
+ <li>When creating a new account, you will be automatically logged in
+ after setting your password.</li>
+ <li>There is no longer a maximum password length for accounts.</li>
+ <li>In the Dusk skin, it's now easier to see links.</li>
+ <li>In the Whining system, you can now choose to receive emails even
+ if there are no [% terms.bugs %] that match your searches.</li>
+ <li>The arrows in dependency graphs now point the other way, so that
+ [%+ terms.bugs %] point at their dependencies.</li>
+
+ <li><b>New Charts:</b> You can now convert an existing Saved Search
+ into a data series for New Charts.</li>
+ <li><b>New Charts:</b> There is now an interface that allows you to
+ delete data series.</li>
+ <li><b>New Charts:</b> When deleting a product, you now have the option
+ to delete the data series that are associated with that product.</li>
+</ul>
+
+<h4>Enhancements for Administrators and Developers</h4>
+
+<ul>
+ <li>Depending on how your workflow is set up, it is now possible to
+ have both UNCONFIRMED and REOPENED show up as status choices for
+ a closed [% terms.bug %]. If you only want one or the other to
+ show up, you should edit your status workflow appropriately
+ (possibly by removing or disabling the REOPENED status).</li>
+ <li>You can now "disable" field values so that they don't show
+ up as choices on [% terms.abug %] unless they are already set as
+ the value for that [% terms.bug %]. This doesn't work for the
+ per-product field values (component, target_milestone, and version)
+ yet, though.</li>
+ <li>Users are now locked out of their accounts for 30 minutes after
+ trying five bad passwords in a row during login. Every time a
+ user is locked out like this, the user in the "maintainer" parameter
+ will get an email.</li>
+ <li>The minimum length allowed for a password is now 6 characters.</li>
+ <li>The <kbd>UNCONFIRMED</kbd> status being enabled in a product
+ is now unrelated to the voting parameters. Instead, there is a checkbox
+ to enable the <kbd>UNCONFIRMED</kbd> status in a product.</li>
+ <li>Information about duplicates is now stored in the database instead
+ of being stored in the <kbd>data/</kbd> directory. On large installations
+ this could save several hundred megabytes of disk space.</li>
+
+ <li>When editing a group, you can now specify that members of a group
+ are allowed to grant others membership in that group itself.</li>
+ <li>The ability to compress BMP attachments to PNGs is now an Extension.
+ To enable the feature, remove the file
+ <kbd>extensions/BmpConvert/disabled</kbd> and then run checksetup.pl.</li>
+ <li>The default list of values for the Priority field are now clear English
+ words instead of P1, P2, etc.</li>
+ <li><kbd>config.cgi</kbd> now returns an ETag header and understands
+ the If-None-Match header in HTTP requests.</li>
+ <li>The XML format of <kbd>show_bug.cgi</kbd> now returns more information:
+ the numeric id of each comment, whether an attachment is a URL,
+ the modification time of an attachment, the numeric id of a flag,
+ and the numeric id of a flag's type.</li>
+</ul>
+
+<h4>WebService Changes</h4>
+
+<ul>
+ <li>The WebService now returns all dates and times in the UTC timezone.
+ <kbd>B[% %]ugzilla.time</kbd> now acts as though the [% terms.Bugzilla %]
+ server were in the UTC timezone, always. If you want to write clients
+ that are compatible across all [% terms.Bugzilla %] versions,
+ check the timezone from <kbd>B[% %]ugzilla.timezone</kbd> or
+ <kbd>B[% %]ugzilla.time</kbd>, and always input times in that timezone
+ and expect times to be returned in that format.</li>
+ <li>You can now log in by passing <kbd>Bugzilla_login</kbd> and
+ <kbd>Bugzilla_password</kbd> as arguments to any WebService function.
+ See the
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService.html#LOGGING_IN">Bugzilla::WebService</a>
+ documentation for details.</li>
+ <li>New Method:
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#attachments">B[% %]ug.attachments</a>
+ which allows getting information about attachments.</li>
+ <li>New Method:
+ <a href="[% docs_urlbase FILTER html %]api/Bugzilla/WebService/Bug.html#fields">B[% %]ug.fields</a>,
+ which gets information about all the fields that [% terms.abug %] can have
+ in [% terms.Bugzilla %], include custom fields and legal values for
+ all fields. The <kbd>B[% %]ug.legal_values</kbd> method is now deprecated.</li>
+ <li>In the <kbd>B[% %]ug.add_comment</kbd> method, the "private" parameter
+ has been renamed to "is_private" (for consistency with other methods).
+ You can still use "private", though, for backwards-compatibility.</li>
+ <li>The WebService now has Perl's "taint mode" turned on. This means that
+ it validates all data passed in before sending it to the database.
+ Also, all parameter names are validated, and if you pass in a parameter
+ whose name contains anything other than letters, numbers, or underscores,
+ that parameter will be ignored. Mostly this just affects
+ customizers--[% terms.Bugzilla %]'s WebService is not functionally
+ affected by these changes.</li>
+ <li>In previous versions of [% terms.Bugzilla %], error messages were
+ sent word-wrapped to the client, from the WebService. Error messages
+ are now sent as one unbroken line.</li>
+</ul>
+
+<h3>Last Ten Commits</h3>
+
+<pre>[% bzr_history.join('') FILTER html %]</pre>
+
+<br>
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/pages/user_activity.html.tmpl b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl
new file mode 100644
index 000000000..dd16595ab
--- /dev/null
+++ b/extensions/BMO/template/en/default/pages/user_activity.html.tmpl
@@ -0,0 +1,180 @@
+[%# 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 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 <bjones@mozilla.com>
+ #%]
+
+[% INCLUDE global/header.html.tmpl
+ title = "User Activity Report"
+ yui = [ 'autocomplete', 'calendar' ]
+ javascript_urls = [ "js/util.js", "js/field.js" ]
+%]
+
+<style>
+#report tr:hover {
+ background: #dddddd;
+}
+
+#report-header {
+ background: #dddddd;
+}
+</style>
+
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS bug/time.html.tmpl %]
+
+<form id="activity_form" name="activity_form" action="page.cgi" method="get">
+<input type="hidden" name="id" value="user_activity.html">
+<input type="hidden" name="action" value="run">
+<table>
+<tr>
+ <td>
+ <b>Who</b>:
+ </td>
+ <td>
+ [% INCLUDE global/userselect.html.tmpl
+ id => "who"
+ name => "who"
+ value => who
+ size => 40
+ emptyok => 0
+ title => "One or more email address (comma delimited)"
+ %]
+ &nbsp;
+ </td>
+ <td>
+ <b>Period</b>:
+ </td>
+ <td>
+ <input type="text" id="from" name="from" size="11"
+ align="right" value="[% from FILTER html %]" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_from"
+ onclick="showCalendar('from')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_from"></div>
+ </td>
+ <td>
+ -
+ </td>
+ <td>
+ <input type="text" name="to" size="11" id="to"
+ align="right" value ="[% to FILTER html %]" maxlength="10"
+ onchange="updateCalendarFromField(this)">
+ <button type="button" class="calendar_button" id="button_calendar_to"
+ onclick="showCalendar('to')"><span>Calendar</span>
+ </button>
+ <div id="con_calendar_to"></div>
+ </td>
+ <td>
+ <input type="submit" id="run" value="Generate Report">
+ </td>
+</tr>
+</table>
+</form>
+
+<script type="text/javascript">
+ createCalendar('from');
+ createCalendar('to');
+</script>
+
+[% IF action == 'run' %]
+
+[% IF incomplete_data %]
+ <p>
+ There used to be an issue in <a href="http://www.bugzilla.org/">Bugzilla</a>
+ which caused activity data to be lost if there were a large number of cc's
+ or dependencies. That has been fixed, but some data was already lost in
+ your activity table that could not be regenerated. The changes that
+ could not reliably determine are prefixed by '?'.
+ </p>
+[% END %]
+
+[% IF operations.size > 0 %]
+ <br>
+ <table border="1" cellpadding="4" cellspacing="0" id="report">
+ <tr id="report-header">
+ <th>Who</th>
+ <th>When</th>
+ <th>Bug</th>
+ <th>What</th>
+ <th>Removed</th>
+ <th>Added</th>
+ </tr>
+
+ [% FOREACH operation = operations %]
+ <tr>
+ <td rowspan="[% operation.changes.size %]" valign="top">
+ [% operation.who FILTER email FILTER html %]
+ </td>
+ <td rowspan="[% operation.changes.size %]" valign="top">
+ [% operation.when FILTER time %]
+ </td>
+ <td rowspan="[% operation.changes.size %]" valign="top">
+ [% operation.bug FILTER bug_link(operation.bug) FILTER none %]
+ </td>
+ [% FOREACH change = operation.changes %]
+ [% "</tr><tr>" IF loop.index > 0 %]
+ <td>
+ [% IF change.attachid %]
+ <a href="attachment.cgi?id=[% change.attachid %]">Attachment #[% change.attachid %]</a>
+ [% ELSIF change.comment.defined && change.fieldname == 'longdesc' %]
+ [% "Comment $change.comment.count" FILTER bug_link(operation.bug, comment_num => change.comment.count) %]
+ [% ELSE %]
+ [%+ field_descs.${change.fieldname} FILTER html %]
+ [% END %]
+ </td>
+ [% PROCESS change_column change_type = change.removed %]
+ [% PROCESS change_column change_type = change.added %]
+ [% END %]
+ </tr>
+ [% END %]
+ </table>
+[% ELSE %]
+ <p>
+ No changes.
+ </p>
+[% END %]
+
+[% BLOCK change_column %]
+ <td>
+ [% IF change_type.defined %]
+ [% IF change.fieldname == 'estimated_time' ||
+ change.fieldname == 'remaining_time' ||
+ change.fieldname == 'work_time' %]
+ [% PROCESS formattimeunit time_unit=change_type %]
+ [% ELSIF change.fieldname == 'blocked' ||
+ change.fieldname == 'dependson' %]
+ [% change_type FILTER bug_list_link FILTER none %]
+ [% ELSIF change.fieldname == 'assigned_to' ||
+ change.fieldname == 'reporter' ||
+ change.fieldname == 'qa_contact' ||
+ change.fieldname == 'cc' ||
+ change.fieldname == 'flagtypes.name' %]
+ [% display_value(change.fieldname, change_type) FILTER email FILTER html %]
+ [% ELSE %]
+ [% display_value(change.fieldname, change_type) FILTER html %]
+ [% END %]
+ [% ELSE %]
+ &nbsp;
+ [% END %]
+ </td>
+[% END %]
+[% END %]
+
+
+[% INCLUDE global/footer.html.tmpl %]
diff --git a/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl
new file mode 100644
index 000000000..5d187bf40
--- /dev/null
+++ b/extensions/BMO/template/en/default/search/search-plugin.xml.tmpl
@@ -0,0 +1,24 @@
+[%# 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 <LpSolit@gmail.com>
+ #
+ #%]
+[% PROCESS global/variables.none.tmpl %]
+<?xml version="1.0" encoding="UTF-8"?>
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+<ShortName>[% terms.BugzillaTitle %]</ShortName>
+<Description>[% terms.BugzillaTitle %] Quick Search</Description>
+<InputEncoding>UTF-8</InputEncoding>
+<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABGdBTUEAAK%2FINwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz%2F%2Fz8DJQAggJiQOe%2Ffv2fv7Oz8rays%2FN%2BVkfG%2FiYnJfyD%2F1%2BrVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw%2F8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi%2FG%2BQKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo%2BMXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia%2BCuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq%2FvLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg%2FkdypqCg4H8lUIACnQ%2FSOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD%2BaDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg%3D%3D</Image>
+<Url type="text/html" method="GET" template="[% urlbase FILTER xml %]buglist.cgi?quicksearch={searchTerms}"/>
+</OpenSearchDescription>
diff --git a/extensions/BMO/web/images/background.png b/extensions/BMO/web/images/background.png
new file mode 100644
index 000000000..eb254aab9
--- /dev/null
+++ b/extensions/BMO/web/images/background.png
Binary files differ
diff --git a/extensions/BMO/web/images/bugzilla.png b/extensions/BMO/web/images/bugzilla.png
new file mode 100644
index 000000000..4b7c10284
--- /dev/null
+++ b/extensions/BMO/web/images/bugzilla.png
Binary files differ
diff --git a/extensions/BMO/web/images/groups/bugzilla-approvers.png b/extensions/BMO/web/images/groups/bugzilla-approvers.png
new file mode 100644
index 000000000..d2414e041
--- /dev/null
+++ b/extensions/BMO/web/images/groups/bugzilla-approvers.png
Binary files differ
diff --git a/extensions/BMO/web/images/groups/calendar-drivers.png b/extensions/BMO/web/images/groups/calendar-drivers.png
new file mode 100644
index 000000000..fc2c1d1e5
--- /dev/null
+++ b/extensions/BMO/web/images/groups/calendar-drivers.png
Binary files differ
diff --git a/extensions/BMO/web/images/mozchomp.gif b/extensions/BMO/web/images/mozchomp.gif
new file mode 100644
index 000000000..ac6549527
--- /dev/null
+++ b/extensions/BMO/web/images/mozchomp.gif
Binary files differ
diff --git a/extensions/BMO/web/images/presshat.png b/extensions/BMO/web/images/presshat.png
new file mode 100644
index 000000000..a61de59e5
--- /dev/null
+++ b/extensions/BMO/web/images/presshat.png
Binary files differ
diff --git a/extensions/BMO/web/images/stop-sign.gif b/extensions/BMO/web/images/stop-sign.gif
new file mode 100644
index 000000000..9b420ec6c
--- /dev/null
+++ b/extensions/BMO/web/images/stop-sign.gif
Binary files differ
diff --git a/extensions/BMO/web/js/edit_bug.js b/extensions/BMO/web/js/edit_bug.js
new file mode 100644
index 000000000..5fc2ab6f7
--- /dev/null
+++ b/extensions/BMO/web/js/edit_bug.js
@@ -0,0 +1,71 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * 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 Developer are Copyright (C) 2011 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+// --- custom flags
+var Dom = YAHOO.util.Dom;
+
+function bmo_hide_tracking_flags() {
+ for (var field in bmo_custom_flags) {
+ var el = Dom.get(field);
+ var value = el ? el.value : bmo_custom_flags[field];
+ if (el && (value != bmo_custom_flags[field])) {
+ bmo_show_tracking_flags();
+ return;
+ }
+ if (value == '---') {
+ Dom.addClass('row_' + field, 'bz_hidden');
+ } else {
+ Dom.addClass(field, 'bz_hidden');
+ Dom.removeClass('ro_' + field, 'bz_hidden');
+ }
+ }
+}
+
+function bmo_show_tracking_flags() {
+ Dom.addClass('edit_tracking_fields_action', 'bz_hidden');
+ for (var field in bmo_custom_flags) {
+ if (Dom.get(field).value == '---') {
+ Dom.removeClass('row_' + field, 'bz_hidden');
+ } else {
+ Dom.removeClass(field, 'bz_hidden');
+ Dom.addClass('ro_' + field, 'bz_hidden');
+ }
+ }
+}
+
+// -- make attachment table, comments, new comment textarea equal widths
+
+YAHOO.util.Event.onDOMReady(function() {
+ var comment_tables = Dom.getElementsByClassName('bz_comment_table', 'table', 'comments');
+ if (comment_tables.length) {
+ var comment_width = comment_tables[0].getElementsByTagName('td')[0].clientWidth + 'px';
+ var attachment_table = Dom.get('attachment_table');
+ if (attachment_table)
+ attachment_table.style.width = comment_width;
+ var new_comment = Dom.get('comment');
+ if (new_comment)
+ new_comment.style.width = comment_width;
+ }
+});
diff --git a/extensions/BMO/web/js/edituser_menu.js b/extensions/BMO/web/js/edituser_menu.js
new file mode 100644
index 000000000..9ce78d9ce
--- /dev/null
+++ b/extensions/BMO/web/js/edituser_menu.js
@@ -0,0 +1,26 @@
+var admin_usermenu;
+
+YAHOO.util.Event.onDOMReady(function() {
+ admin_usermenu = new YAHOO.widget.Menu('admin_usermenu', { position : 'dynamic' });
+ admin_usermenu.addItems([
+ { text: 'Edit', url: '#', target: '_new' },
+ { text: 'Activity', url: '#', target: '_new' },
+ { text: 'Mail', url: '#', target: '_new' }
+ ]);
+ admin_usermenu.render(document.body);
+});
+
+function show_admin_username(event, id, email) {
+ if (!admin_usermenu)
+ return;
+ admin_usermenu.getItem(0).cfg.setProperty('url', 'editusers.cgi?action=edit&userid=' + id);
+ admin_usermenu.getItem(1).cfg.setProperty('url',
+ 'page.cgi?id=user_activity.html&action=run' +
+ '&from=' + YAHOO.util.Date.format(new Date(new Date() - (1000 * 60 * 60 * 24 * 14)), {format: '%Y-%m-%d'}) +
+ '&to=' + YAHOO.util.Date.format(new Date(), {format: '%Y-%m-%d'}) +
+ '&who=' + escape(email));
+ admin_usermenu.getItem(2).cfg.setProperty('url', 'mailto:' + escape(email));
+ admin_usermenu.cfg.setProperty('xy', YAHOO.util.Event.getXY(event));
+ admin_usermenu.show();
+}
+
diff --git a/extensions/BMO/web/js/form_validate.js b/extensions/BMO/web/js/form_validate.js
new file mode 100644
index 000000000..6c8fa6f07
--- /dev/null
+++ b/extensions/BMO/web/js/form_validate.js
@@ -0,0 +1,21 @@
+/**
+ * Some Form Validation and Interaction
+ **/
+//Makes sure that there is an '@' in the address with a '.'
+//somewhere after it (and at least one character in between them
+
+function isValidEmail(email) {
+ var at_index = email.indexOf("@");
+ var last_dot = email.lastIndexOf(".");
+ return at_index > 0 && last_dot > (at_index + 1);
+}
+
+//Takes a DOM element id and makes sure that it is filled out
+function isFilledOut(elem_id) {
+ var str = document.getElementById(elem_id).value;
+ return str.length>0 && str!="noneselected";
+}
+
+function isChecked(elem_id) {
+ return document.getElementById(elem_id).checked;
+}
diff --git a/extensions/BMO/web/js/sorttable.js b/extensions/BMO/web/js/sorttable.js
new file mode 100644
index 000000000..1703a06ae
--- /dev/null
+++ b/extensions/BMO/web/js/sorttable.js
@@ -0,0 +1,709 @@
+/*
+ SortTable
+ version 2
+ 7th April 2007
+ Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
+
+ Instructions:
+ Download this file
+ Add <script src="sorttable.js"></script> to your HTML
+ Add class="sortable" to any table you'd like to make sortable
+ Click on the headers to sort
+
+ Thanks to many, many people for contributions and suggestions.
+ Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
+ This basically means: do what you want with it.
+*/
+
+var stIsIE = /*@cc_on!@*/false;
+
+sorttable = {
+ init: function() {
+ // quit if this function has already been called
+ if (arguments.callee.done) return;
+ // flag this function so we don't do the same thing twice
+ arguments.callee.done = true;
+ // kill the timer
+ if (_timer) clearInterval(_timer);
+
+ if (!document.createElement || !document.getElementsByTagName) return;
+
+ sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
+
+ forEach(document.getElementsByTagName('table'), function(table) {
+ if (table.className.search(/\bsortable\b/) != -1) {
+ sorttable.makeSortable(table);
+ }
+ });
+
+ },
+
+ /*
+ * Prepares the table so that it can be sorted
+ *
+ */
+ makeSortable: function(table) {
+
+ if (table.getElementsByTagName('thead').length == 0) {
+ // table doesn't have a tHead. Since it should have, create one and
+ // put the first table row in it.
+ the = document.createElement('thead');
+ the.appendChild(table.rows[0]);
+ table.insertBefore(the,table.firstChild);
+ }
+ // Safari doesn't support table.tHead, sigh
+ if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
+
+ //if (table.tHead.rows.length != 1) return; // can't cope with two header rows
+
+ // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
+ // "total" rows, for example). This is B&R, since what you're supposed
+ // to do is put them in a tfoot. So, if there are sortbottom rows,
+ // for backwards compatibility, move them to tfoot (creating it if needed).
+ sortbottomrows = [];
+ for (var i=0; i<table.rows.length; i++) {
+ if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
+ sortbottomrows[sortbottomrows.length] = table.rows[i];
+ }
+ }
+
+ if (sortbottomrows) {
+ if (table.tFoot == null) {
+ // table doesn't have a tfoot. Create one.
+ tfo = document.createElement('tfoot');
+ table.appendChild(tfo);
+ }
+ for (var i=0; i<sortbottomrows.length; i++) {
+ tfo.appendChild(sortbottomrows[i]);
+ }
+ delete sortbottomrows;
+ }
+
+ sorttable._walk_through_headers(table);
+ },
+
+ /*
+ * Helper function for preparing the table
+ *
+ */
+ _walk_through_headers: function(table) {
+ // First, gather some information we need to sort the table.
+ var bodies = [];
+ var table_rows = [];
+ var body_size = table.tBodies[0].rows.length;
+
+ // We need to get all the rows
+ for (var i=0; i<table.tBodies.length; i++) {
+ if (!table.tBodies[i].className.match(/\bsorttable_body\b/))
+ continue;
+
+ bodies[bodies.length] = table.tBodies[i];
+ for (j=0; j<table.tBodies[i].rows.length; j++) {
+ table_rows[table_rows.length] = table.tBodies[i].rows[j];
+ }
+ }
+
+ table.sorttable_rows = table_rows;
+ table.sorttable_body_size = body_size;
+ table.sorttable_bodies = bodies;
+
+
+ // work through each column and calculate its type
+
+ // For each row in the header..
+ for (var row_index=0; row_index < table.tHead.rows.length; row_index++) {
+
+ headrow = table.tHead.rows[row_index].cells;
+ // ... Walk through each column and calculate the type.
+ for (var i=0; i<headrow.length; i++) {
+ // Don't sort this column, please
+ if (headrow[i].className.match(/\bsorttable_nosort\b/)) continue;
+
+ // Override sort column index.
+ column_index = i;
+ mtch = headrow[i].className.match(/\bsortable_column_([a-z0-9]+)\b/);
+ if (mtch) column_index = mtch[1];
+
+
+ // Manually override the type with a sorttable_type attribute
+ // Override sort function
+ mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
+ if (mtch) override = mtch[1];
+
+ if (mtch && typeof sorttable["sort_"+override] == 'function') {
+ headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
+ } else {
+ headrow[i].sorttable_sortfunction = sorttable.guessType(table, column_index);
+ }
+
+ // make it clickable to sort
+ headrow[i].sorttable_columnindex = column_index;
+ headrow[i].table = table;
+
+ // If the header contains a link, clear the href.
+ for (var k=0; k<headrow[i].childNodes.length; k++) {
+ if (headrow[i].childNodes[k].tagName == 'A') {
+ headrow[i].childNodes[k].href = "javascript:void(0);";
+ }
+ }
+
+ dean_addEvent(headrow[i], "click", sorttable._on_column_header_clicked);
+
+ } // inner for (var i=0; i<headrow.length; i++)
+ } // outer for
+ },
+
+
+
+
+ /*
+ * Helper function for the _on_column_header_clicked handler
+ *
+ */
+
+ _remove_sorted_classes: function(header) {
+ // For each row in the header..
+ for (var j=0; j< header.rows.length; j++) {
+ // ... Walk through each column and calculate the type.
+ row = header.rows[j].cells;
+
+ for (var i=0; i<row.length; i++) {
+ cell = row[i];
+ if (cell.nodeType != 1) return; // an element
+
+ mtch = cell.className.match(/\bsorted_([0-9]+)\b/);
+ if (mtch) {
+ cell.className = cell.className.replace('sorted_'+mtch[1],
+ 'sorted_'+(parseInt(mtch[1])+1));
+ }
+
+ cell.className = cell.className.replace('sorttable_sorted_reverse','');
+ cell.className = cell.className.replace('sorttable_sorted','');
+ }
+ }
+ },
+
+ _check_already_sorted: function(cell) {
+ if (cell.className.search(/\bsorttable_sorted\b/) != -1) {
+ // if we're already sorted by this column, just
+ // reverse the table, which is quicker
+ sorttable.reverse_table(cell);
+
+ sorttable._mark_column_as_sorted(cell, '&#x25B2;', 1);
+ return 1;
+ }
+
+ if (cell.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
+ // if we're already sorted by this column in reverse, just
+ // re-reverse the table, which is quicker
+ sorttable.reverse_table(cell);
+
+ sorttable._mark_column_as_sorted(cell, '&#x25BC;', 0);
+
+ return 1;
+ }
+
+ return 0;
+ },
+
+ /* Visualy mark the cell as sorted.
+ *
+ * @param cell: the cell being marked
+ * @param text: the text being used to mark. you can use html
+ * @param reversed: whether the column is reversed or not.
+ *
+ */
+ _mark_column_as_sorted: function(cell, text, reversed) {
+ // remove eventual class
+ cell.className = cell.className.replace('sorttable_sorted', '');
+ cell.className = cell.className.replace('sorttable_sorted_reverse', '');
+
+ // the column is reversed
+ if (reversed) {
+ cell.className += ' sorttable_sorted_reverse';
+ }
+ else {
+ // remove eventual class
+ cell.className += ' sorttable_sorted';
+ }
+
+ sorttable._remove_sorting_marker();
+
+ marker = document.createElement('span');
+ marker.id = "sorttable_sort_mark";
+ marker.className = "bz_sort_order_primary";
+ marker.innerHTML = text;
+ cell.appendChild(marker);
+ },
+
+ _remove_sorting_marker: function() {
+ mark = document.getElementById('sorttable_sort_mark');
+ if (mark) { mark.parentNode.removeChild(mark); }
+ els = sorttable._getElementsByClassName('bz_sort_order_primary');
+ for(var i=0,j=els.length; i<j; i++) {
+ els[i].parentNode.removeChild(els[i]);
+ }
+ els = sorttable._getElementsByClassName('bz_sort_order_secondary');
+ for(var i=0,j=els.length; i<j; i++) {
+ els[i].parentNode.removeChild(els[i]);
+ }
+ },
+
+ _getElementsByClassName: function(classname, node) {
+ if(!node) node = document.getElementsByTagName("body")[0];
+ var a = [];
+ var re = new RegExp('\\b' + classname + '\\b');
+ var els = node.getElementsByTagName("*");
+ for(var i=0,j=els.length; i<j; i++)
+ if(re.test(els[i].className))a.push(els[i]);
+ return a;
+ },
+
+ /*
+ * This is the callback for when the table header is clicked.
+ *
+ * @param evt: the event that triggered this callback
+ */
+ _on_column_header_clicked: function(evt) {
+
+ // The table is already sorted by this column. Just reverse it.
+ if (sorttable._check_already_sorted(this))
+ return;
+
+
+ // First, remove sorttable_sorted classes from the other header
+ // that is currently sorted and its marker (the simbol indicating
+ // that its sorted.
+ sorttable._remove_sorted_classes(this.table.tHead);
+ mtch = this.className.match(/\bsorted_([0-9]+)\b/);
+ if (mtch) {
+ this.className = this.className.replace('sorted_'+mtch[1], '');
+ }
+ this.className += ' sorted_0 ';
+
+ // This is the text that indicates that the column is sorted.
+ sorttable._mark_column_as_sorted(this, '&#x25BC;', 0);
+
+ sorttable.sort_table(this);
+
+ },
+
+ sort_table: function(cell) {
+ // build an array to sort. This is a Schwartzian transform thing,
+ // i.e., we "decorate" each row with the actual sort key,
+ // sort based on the sort keys, and then put the rows back in order
+ // which is a lot faster because you only do getInnerText once per row
+ col = cell.sorttable_columnindex;
+ rows = cell.table.sorttable_rows;
+
+ var BUGLIST = '';
+
+ for (var j = 0; j < cell.table.sorttable_rows.length; j++) {
+ rows[j].sort_data = sorttable.getInnerText(rows[j].cells[col]);
+ }
+
+ /* If you want a stable sort, uncomment the following line */
+ sorttable.shaker_sort(rows, cell.sorttable_sortfunction);
+ /* and comment out this one */
+ //rows.sort(cell.sorttable_sortfunction);
+
+ // Rebuild the table, using he sorted rows.
+ tb = cell.table.sorttable_bodies[0];
+ body_size = cell.table.sorttable_body_size;
+ body_index = 0;
+
+ for (var j=0; j<rows.length; j++) {
+ if (j % 2)
+ rows[j].className = rows[j].className.replace('bz_row_even',
+ 'bz_row_odd');
+ else
+ rows[j].className = rows[j].className.replace('bz_row_odd',
+ 'bz_row_even');
+
+ tb.appendChild(rows[j]);
+ var bug_id = sorttable.getInnerText(rows[j].cells[0].childNodes[1]);
+ BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id;
+
+ if (j % body_size == body_size-1) {
+ body_index++;
+ if (body_index < cell.table.sorttable_bodies.length) {
+ tb = cell.table.sorttable_bodies[body_index];
+ }
+ }
+ }
+
+ document.cookie = 'BUGLIST='+BUGLIST;
+
+ cell.table.sorttable_rows = rows;
+ },
+
+ reverse_table: function(cell) {
+ oldrows = cell.table.sorttable_rows;
+ newrows = [];
+
+ for (var i=0; i < oldrows.length; i++) {
+ newrows[newrows.length] = oldrows[i];
+ }
+
+ tb = cell.table.sorttable_bodies[0];
+ body_size = cell.table.sorttable_body_size;
+ body_index = 0;
+
+ var BUGLIST = '';
+
+ cell.table.sorttable_rows = [];
+ for (var i = newrows.length-1; i >= 0; i--) {
+ if (i % 2)
+ newrows[i].className = newrows[i].className.replace('bz_row_even',
+ 'bz_row_odd');
+ else
+ newrows[i].className = newrows[i].className.replace('bz_row_odd',
+ 'bz_row_even');
+
+ tb.appendChild(newrows[i]);
+ cell.table.sorttable_rows.push(newrows[i]);
+
+ var bug_id = sorttable.getInnerText(newrows[i].cells[0].childNodes[1]);
+ BUGLIST = BUGLIST ? BUGLIST+':'+bug_id : bug_id;
+
+ if ((newrows.length-1-i) % body_size == body_size-1) {
+ body_index++;
+ if (body_index < cell.table.sorttable_bodies.length) {
+ tb = cell.table.sorttable_bodies[body_index];
+ }
+ }
+
+ }
+
+ document.cookie = 'BUGLIST='+BUGLIST;
+
+ delete newrows;
+ },
+
+ guessType: function(table, column) {
+ // guess the type of a column based on its first non-blank row
+ sortfn = sorttable.sort_alpha;
+ for (var i=0; i<table.sorttable_bodies[0].rows.length; i++) {
+ text = sorttable.getInnerText(table.sorttable_bodies[0].rows[i].cells[column]);
+ if (text != '') {
+ if (text.match(/^-?[£$¤]?[\d,.]+%?$/)) {
+ return sorttable.sort_numeric;
+ }
+ // check for a date: dd/mm/yyyy or dd/mm/yy
+ // can have / or . or - as separator
+ // can be mm/dd as well
+ possdate = text.match(sorttable.DATE_RE)
+ if (possdate) {
+ // looks like a date
+ first = parseInt(possdate[1]);
+ second = parseInt(possdate[2]);
+ if (first > 12) {
+ // definitely dd/mm
+ return sorttable.sort_ddmm;
+ } else if (second > 12) {
+ return sorttable.sort_mmdd;
+ } else {
+ // looks like a date, but we can't tell which, so assume
+ // that it's dd/mm (English imperialism!) and keep looking
+ sortfn = sorttable.sort_ddmm;
+ }
+ }
+ }
+ }
+ return sortfn;
+ },
+
+ getInnerText: function(node) {
+ // gets the text we want to use for sorting for a cell.
+ // strips leading and trailing whitespace.
+ // this is *not* a generic getInnerText function; it's special to sorttable.
+ // for example, you can override the cell text with a customkey attribute.
+ // it also gets .value for <input> fields.
+
+ hasInputs = (typeof node.getElementsByTagName == 'function') &&
+ node.getElementsByTagName('input').length;
+
+ if (typeof node.getAttribute != 'undefined' && node.getAttribute("sorttable_customkey") != null) {
+ return node.getAttribute("sorttable_customkey");
+ }
+ else if (typeof node.textContent != 'undefined' && !hasInputs) {
+ return node.textContent.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.innerText != 'undefined' && !hasInputs) {
+ return node.innerText.replace(/^\s+|\s+$/g, '');
+ }
+ else if (typeof node.text != 'undefined' && !hasInputs) {
+ return node.text.replace(/^\s+|\s+$/g, '');
+ }
+ else {
+ switch (node.nodeType) {
+ case 3:
+ if (node.nodeName.toLowerCase() == 'input') {
+ return node.value.replace(/^\s+|\s+$/g, '');
+ }
+ case 4:
+ return node.nodeValue.replace(/^\s+|\s+$/g, '');
+ break;
+ case 1:
+ case 11:
+ var innerText = '';
+ for (var i = 0; i < node.childNodes.length; i++) {
+ innerText += sorttable.getInnerText(node.childNodes[i]);
+ }
+ return innerText.replace(/^\s+|\s+$/g, '');
+ break;
+ default:
+ return '';
+ }
+ }
+ },
+
+ /* sort functions
+ each sort function takes two parameters, a and b
+ you are comparing a.sort_data and b.sort_data */
+ sort_numeric: function(a,b) {
+ aa = parseFloat(a.sort_data.replace(/[^0-9.-]/g,''));
+ if (isNaN(aa)) aa = 0;
+ bb = parseFloat(b.sort_data.replace(/[^0-9.-]/g,''));
+ if (isNaN(bb)) bb = 0;
+ return aa-bb;
+ },
+
+ sort_alpha: function(a,b) {
+ if (a.sort_data.toLowerCase()==b.sort_data.toLowerCase()) return 0;
+ if (a.sort_data.toLowerCase()<b.sort_data.toLowerCase()) return -1;
+ return 1;
+ },
+
+ sort_ddmm: function(a,b) {
+ mtch = a.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; m = mtch[2]; d = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ sort_mmdd: function(a,b) {
+ mtch = a.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt1 = y+m+d;
+ mtch = b.sort_data.match(sorttable.DATE_RE);
+ y = mtch[3]; d = mtch[2]; m = mtch[1];
+ if (m.length == 1) m = '0'+m;
+ if (d.length == 1) d = '0'+d;
+ dt2 = y+m+d;
+ if (dt1==dt2) return 0;
+ if (dt1<dt2) return -1;
+ return 1;
+ },
+
+ shaker_sort: function(list, comp_func) {
+ // A stable sort function to allow multi-level sorting of data
+ // see: http://en.wikipedia.org/wiki/Cocktail_sort
+ // thanks to Joseph Nahmias
+ var b = 0;
+ var t = list.length - 1;
+ var swap = true;
+
+ while(swap) {
+ swap = false;
+ for(var i = b; i < t; ++i) {
+ if ( comp_func(list[i], list[i+1]) > 0 ) {
+ var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
+ swap = true;
+ }
+ } // for
+ t--;
+
+ if (!swap) break;
+
+ for(var i = t; i > b; --i) {
+ if ( comp_func(list[i], list[i-1]) < 0 ) {
+ var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
+ swap = true;
+ }
+ } // for
+ b++;
+
+ } // while(swap)
+ }
+}
+
+/* ******************************************************************
+ Supporting functions: bundled here to avoid depending on a library
+ ****************************************************************** */
+
+// Dean Edwards/Matthias Miller/John Resig
+
+/* for Mozilla/Opera9 */
+if (document.addEventListener) {
+ document.addEventListener("DOMContentLoaded", sorttable.init, false);
+}
+
+/* for Internet Explorer */
+/*@cc_on @*/
+/*@if (@_win32)
+ // IE doesn't have a way to test if the DOM is loaded
+ // doing a deferred script load with onReadyStateChange checks is
+ // problematic, so poll the document until it is scrollable
+ // http://blogs.atlassian.com/developer/2008/03/when_ie_says_dom_is_ready_but.html
+ var loadTestTimer = function() {
+ try {
+ if (document.readyState != "loaded" && document.readyState != "complete") {
+ document.documentElement.doScroll("left");
+ }
+ sorttable.init(); // call the onload handler
+ } catch(error) {
+ setTimeout(loadTestTimer, 100);
+ }
+ };
+ loadTestTimer();
+/*@end @*/
+
+/* for Safari */
+if (/WebKit/i.test(navigator.userAgent)) { // sniff
+ var _timer = setInterval(function() {
+ if (/loaded|complete/.test(document.readyState)) {
+ sorttable.init(); // call the onload handler
+ }
+ }, 10);
+}
+
+/* for other browsers */
+window.onload = sorttable.init;
+
+// written by Dean Edwards, 2005
+// with input from Tino Zijdel, Matthias Miller, Diego Perini
+
+// http://dean.edwards.name/weblog/2005/10/add-event/
+
+function dean_addEvent(element, type, handler) {
+ if (element.addEventListener) {
+ element.addEventListener(type, handler, false);
+ } else {
+ // assign each event handler a unique ID
+ if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
+ // create a hash table of event types for the element
+ if (!element.events) element.events = {};
+ // create a hash table of event handlers for each element/event pair
+ var handlers = element.events[type];
+ if (!handlers) {
+ handlers = element.events[type] = {};
+ // store the existing event handler (if there is one)
+ if (element["on" + type]) {
+ handlers[0] = element["on" + type];
+ }
+ }
+ // store the event handler in the hash table
+ handlers[handler.$$guid] = handler;
+ // assign a global event handler to do all the work
+ element["on" + type] = handleEvent;
+ }
+};
+// a counter used to create unique IDs
+dean_addEvent.guid = 1;
+
+function removeEvent(element, type, handler) {
+ if (element.removeEventListener) {
+ element.removeEventListener(type, handler, false);
+ } else {
+ // delete the event handler from the hash table
+ if (element.events && element.events[type]) {
+ delete element.events[type][handler.$$guid];
+ }
+ }
+};
+
+function handleEvent(event) {
+ var returnValue = true;
+ // grab the event object (IE uses a global event object)
+ event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
+ // get a reference to the hash table of event handlers
+ var handlers = this.events[event.type];
+ // execute each event handler
+ for (var i in handlers) {
+ this.$$handleEvent = handlers[i];
+ if (this.$$handleEvent(event) === false) {
+ returnValue = false;
+ }
+ }
+ return returnValue;
+};
+
+function fixEvent(event) {
+ // add W3C standard event methods
+ event.preventDefault = fixEvent.preventDefault;
+ event.stopPropagation = fixEvent.stopPropagation;
+ return event;
+};
+fixEvent.preventDefault = function() {
+ this.returnValue = false;
+};
+fixEvent.stopPropagation = function() {
+ this.cancelBubble = true;
+}
+
+// Dean's forEach: http://dean.edwards.name/base/forEach.js
+/*
+ forEach, version 1.0
+ Copyright 2006, Dean Edwards
+ License: http://www.opensource.org/licenses/mit-license.php
+*/
+
+// array-like enumeration
+if (!Array.forEach) { // mozilla already supports this
+ Array.forEach = function(array, block, context) {
+ for (var i = 0; i < array.length; i++) {
+ block.call(context, array[i], i, array);
+ }
+ };
+}
+
+// generic enumeration
+Function.prototype.forEach = function(object, block, context) {
+ for (var key in object) {
+ if (typeof this.prototype[key] == "undefined") {
+ block.call(context, object[key], key, object);
+ }
+ }
+};
+
+// character enumeration
+String.forEach = function(string, block, context) {
+ Array.forEach(string.split(""), function(chr, index) {
+ block.call(context, chr, index, string);
+ });
+};
+
+// globally resolve forEach enumeration
+var forEach = function(object, block, context) {
+ if (object) {
+ var resolve = Object; // default
+ if (object instanceof Function) {
+ // functions have a "length" property
+ resolve = Function;
+ } else if (object.forEach instanceof Function) {
+ // the object implements a custom forEach method so use that
+ object.forEach(block, context);
+ return;
+ } else if (typeof object == "string") {
+ // the object is a string
+ resolve = String;
+ } else if (typeof object.length == "number") {
+ // the object is array-like
+ resolve = Array;
+ }
+ resolve.forEach(object, block, context);
+ }
+};
+
diff --git a/extensions/BMO/web/js/swag.js b/extensions/BMO/web/js/swag.js
new file mode 100644
index 000000000..47886b2a9
--- /dev/null
+++ b/extensions/BMO/web/js/swag.js
@@ -0,0 +1,60 @@
+/**
+ * Swag Request Form Functions
+ * Form Interal Swag Request Form
+ * dtran
+ * 7/6/09
+ **/
+
+
+function evalToNumber(numberString) {
+ if(numberString=='') return 0;
+ return parseInt(numberString);
+}
+
+function evalToNumberString(numberString) {
+ if(numberString=='') return '0';
+ return numberString;
+}
+//item_array should be an array of DOM element ids
+function getTotal(item_array) {
+ var total = 0;
+ for(var i in item_array) {
+ total += evalToNumber(document.getElementById(item_array[i]).value);
+ }
+ return total;
+}
+
+function calculateTotalSwag() {
+ document.getElementById('Totalswag').value =
+ getTotal( new Array('Lanyards',
+ 'Stickers',
+ 'Bracelets',
+ 'Tattoos',
+ 'Buttons',
+ 'Posters'));
+
+}
+
+
+function calculateTotalMensShirts() {
+ document.getElementById('mens_total').value =
+ getTotal( new Array('mens_s',
+ 'mens_m',
+ 'mens_l',
+ 'mens_xl',
+ 'mens_xxl',
+ 'mens_xxxl'));
+
+}
+
+
+function calculateTotalWomensShirts() {
+ document.getElementById('womens_total').value =
+ getTotal( new Array('womens_s',
+ 'womens_m',
+ 'womens_l',
+ 'womens_xl',
+ 'womens_xxl',
+ 'womens_xxxl'));
+
+}
diff --git a/extensions/BMO/web/js/triage_reports.js b/extensions/BMO/web/js/triage_reports.js
new file mode 100644
index 000000000..855b577d7
--- /dev/null
+++ b/extensions/BMO/web/js/triage_reports.js
@@ -0,0 +1,83 @@
+var Dom = YAHOO.util.Dom;
+
+function onSelectProduct() {
+ var component = Dom.get('component');
+ if (Dom.get('product').value == '') {
+ bz_clearOptions(component);
+ return;
+ }
+ selectProduct(Dom.get('product'), component);
+ // selectProduct only supports __Any__ on both elements
+ // we only want it on component, so add it back in
+ try {
+ component.add(new Option('__Any__', ''), component.options[0]);
+ } catch(e) {
+ // support IE
+ component.add(new Option('__Any__', ''), 0);
+ }
+ component.value = '';
+}
+
+function onCommenterChange() {
+ var commenter_is = Dom.get('commenter_is');
+ if (Dom.get('commenter').value == 'is') {
+ Dom.removeClass(commenter_is, 'hidden');
+ } else {
+ Dom.addClass(commenter_is, 'hidden');
+ }
+}
+
+function onLastChange() {
+ var last_is_span = Dom.get('last_is_span');
+ if (Dom.get('last').value == 'is') {
+ Dom.removeClass(last_is_span, 'hidden');
+ } else {
+ Dom.addClass(last_is_span, 'hidden');
+ }
+}
+
+function onGenerateReport() {
+ if (Dom.get('product').value == '') {
+ alert('You must select a product.');
+ return false;
+ }
+ if (Dom.get('component').value == '' && !Dom.get('component').options[0].selected) {
+ alert('You must select at least one component.');
+ return false;
+ }
+ if (!(Dom.get('filter_commenter').checked || Dom.get('filter_last').checked)) {
+ alert('You must select at least one comment filter.');
+ return false;
+ }
+ if (Dom.get('filter_commenter').checked
+ && Dom.get('commenter').value == 'is'
+ && Dom.get('commenter_is').value == '')
+ {
+ alert('You must specify the last commenter\'s email address.');
+ return false;
+ }
+ if (Dom.get('filter_last').checked
+ && Dom.get('last').value == 'is'
+ && Dom.get('last_is').value == '')
+ {
+ alert('You must specify the "comment is older than" date.');
+ return false;
+ }
+ return true;
+}
+
+YAHOO.util.Event.onDOMReady(function() {
+ onSelectProduct();
+ onCommenterChange();
+ onLastChange();
+
+ var component = Dom.get('component');
+ if (selected_components.length == 0)
+ return;
+ component.options[0].selected = false;
+ for (var i = 0, n = selected_components.length; i < n; i++) {
+ var index = bz_optionIndex(component, selected_components[i]);
+ if (index != -1)
+ component.options[index].selected = true;
+ }
+});
diff --git a/extensions/BMO/web/producticons/camino.png b/extensions/BMO/web/producticons/camino.png
new file mode 100644
index 000000000..c833b4d04
--- /dev/null
+++ b/extensions/BMO/web/producticons/camino.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/dino.png b/extensions/BMO/web/producticons/dino.png
new file mode 100644
index 000000000..9e0470a07
--- /dev/null
+++ b/extensions/BMO/web/producticons/dino.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/fennec.png b/extensions/BMO/web/producticons/fennec.png
new file mode 100644
index 000000000..ebad7e358
--- /dev/null
+++ b/extensions/BMO/web/producticons/fennec.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/firefox.png b/extensions/BMO/web/producticons/firefox.png
new file mode 100644
index 000000000..582a6952a
--- /dev/null
+++ b/extensions/BMO/web/producticons/firefox.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/idea.png b/extensions/BMO/web/producticons/idea.png
new file mode 100644
index 000000000..9480dce62
--- /dev/null
+++ b/extensions/BMO/web/producticons/idea.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/input.png b/extensions/BMO/web/producticons/input.png
new file mode 100644
index 000000000..81f355d85
--- /dev/null
+++ b/extensions/BMO/web/producticons/input.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/labs.png b/extensions/BMO/web/producticons/labs.png
new file mode 100644
index 000000000..346e0ef06
--- /dev/null
+++ b/extensions/BMO/web/producticons/labs.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/mozilla.png b/extensions/BMO/web/producticons/mozilla.png
new file mode 100644
index 000000000..e506328bc
--- /dev/null
+++ b/extensions/BMO/web/producticons/mozilla.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/other.png b/extensions/BMO/web/producticons/other.png
new file mode 100644
index 000000000..e436c22ae
--- /dev/null
+++ b/extensions/BMO/web/producticons/other.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/seamonkey.png b/extensions/BMO/web/producticons/seamonkey.png
new file mode 100644
index 000000000..fcb261ae1
--- /dev/null
+++ b/extensions/BMO/web/producticons/seamonkey.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/sunbird.png b/extensions/BMO/web/producticons/sunbird.png
new file mode 100644
index 000000000..6b15c257d
--- /dev/null
+++ b/extensions/BMO/web/producticons/sunbird.png
Binary files differ
diff --git a/extensions/BMO/web/producticons/thunderbird.png b/extensions/BMO/web/producticons/thunderbird.png
new file mode 100644
index 000000000..f3523183a
--- /dev/null
+++ b/extensions/BMO/web/producticons/thunderbird.png
Binary files differ
diff --git a/extensions/BMO/web/styles/create_account.css b/extensions/BMO/web/styles/create_account.css
new file mode 100644
index 000000000..27ea9912a
--- /dev/null
+++ b/extensions/BMO/web/styles/create_account.css
@@ -0,0 +1,62 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * 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 the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#create-account h2 {
+ margin: 0px;
+}
+
+.column-header {
+ padding: 20px 20px 20px 0px;
+}
+
+#create-account-left {
+ border-right: 2px solid #888888;
+ padding-right: 10px;
+}
+
+#product-list td {
+ padding-top: 10px;
+}
+
+#product-list img {
+ padding-right: 10px;
+}
+
+#create-account-right {
+ padding-left: 10px;
+}
+
+#right-blurb {
+ font-size: large;
+}
+
+#right-blurb li {
+ padding-bottom: 1em;
+}
+
+#create-account-form {
+ margin-bottom: 5em;
+}
+
diff --git a/extensions/BMO/web/styles/edit_bug.css b/extensions/BMO/web/styles/edit_bug.css
new file mode 100644
index 000000000..ecfb2f80c
--- /dev/null
+++ b/extensions/BMO/web/styles/edit_bug.css
@@ -0,0 +1,32 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * 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 Developer are Copyright (C) 2011 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Byron Jones <glob@mozilla.com>
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+#custom-flags {
+ width: auto;
+}
+
+.bz_hidden {
+ display: none;
+}
diff --git a/extensions/BMO/web/styles/reports.css b/extensions/BMO/web/styles/reports.css
new file mode 100644
index 000000000..3106a6295
--- /dev/null
+++ b/extensions/BMO/web/styles/reports.css
@@ -0,0 +1,37 @@
+.hidden {
+ display: none;
+}
+
+#triage_form th {
+ text-align: left;
+}
+
+#product, #component {
+ width: 20em;
+}
+
+#report tr.bugitem:hover {
+ background: #ccccff;
+}
+
+#report td {
+ padding: 1px 10px 1px 10px;
+}
+
+#report-header {
+ background: #dddddd;
+}
+
+.report_row_odd {
+ background-color: #F7F7F7;
+ color: #000000;
+}
+
+.report_row_even {
+ background-color: #FFFFFF;
+ color: #000000;
+}
+
+tr.report_item:hover {
+ background-color: #ccccff;
+}
diff --git a/extensions/BMO/web/styles/triage_reports.css b/extensions/BMO/web/styles/triage_reports.css
new file mode 100644
index 000000000..6190fd32c
--- /dev/null
+++ b/extensions/BMO/web/styles/triage_reports.css
@@ -0,0 +1,23 @@
+.hidden {
+ display: none;
+}
+
+#triage_form th {
+ text-align: left;
+}
+
+#product, #component {
+ width: 20em;
+}
+
+#report tr.bugitem:hover {
+ background: #ccccff;
+}
+
+#report td {
+ padding: 1px 10px 1px 10px;
+}
+
+#report-header {
+ background: #dddddd;
+}