summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--template/default/prefs/account.tmpl56
-rw-r--r--template/default/prefs/email.tmpl156
-rw-r--r--template/default/prefs/footer.tmpl75
-rw-r--r--template/default/prefs/permissions.tmpl56
-rw-r--r--template/default/prefs/userprefs.tmpl105
-rwxr-xr-xuserprefs.cgi696
6 files changed, 644 insertions, 500 deletions
diff --git a/template/default/prefs/account.tmpl b/template/default/prefs/account.tmpl
new file mode 100644
index 000000000..486aba082
--- /dev/null
+++ b/template/default/prefs/account.tmpl
@@ -0,0 +1,56 @@
+[%# 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:
+ # realname: string. The user's real name, if any.
+ # login: string. The user's Bugzilla login email address.
+ #%]
+
+<table>
+ <tr>
+ <th align="right">Old password:</th>
+ <td>
+ <input type="hidden" name="Bugzilla_login"
+ value="[% login FILTER html %]" />
+ <input type="password" name="Bugzilla_password" />
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">New password:</th>
+ <td>
+ <input type="password" name="new_password1" />
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">Re-enter new password:</th>
+ <td>
+ <input type="password" name="new_password2" />
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">Your real name (optional, but encouraged):</th>
+ <td>
+ <input size="35" name="realname" value="[% realname FILTER html %]" />
+ </td>
+ </tr>
+</table>
diff --git a/template/default/prefs/email.tmpl b/template/default/prefs/email.tmpl
new file mode 100644
index 000000000..2210f2716
--- /dev/null
+++ b/template/default/prefs/email.tmpl
@@ -0,0 +1,156 @@
+[%# 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:
+ # watchedusers: string.
+ # Comma-separated list of email addresses this user watches.
+ # excludeself: boolean.
+ # True if user is not receiving self-generated mail.
+ # <rolename>: Multiple hashes, one for each rolename (e.g. owner; see
+ # below), keyed by reasonname (e.g. comments; again, see
+ # below). The value is a boolean - true if the user is
+ # receiving mail for that reason when in that role.
+ # Also references the 'supportwatchers' Param.
+ #%]
+
+<table>
+ [% IF Param('supportwatchers') %]
+ <tr>
+ <td colspan="4">
+ <hr />
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="4">
+ If you want to help cover for someone when they're on vacation, or if
+ you need to do the QA related to all of their bugs, you can tell
+ Bugzilla to send mail related to their bugs to you also. List the
+ email addresses of any users you wish to watch here, separated by
+ commas.
+ </td>
+ </tr>
+
+ <tr>
+ <th align="right">Users to watch:</th>
+ <td>
+ <input size="35" name="watchedusers" value="[% watchedusers %]" />
+ </td>
+ </tr>
+ [% END %]
+
+ <tr>
+ <td colspan="2">
+ <p>
+ If you don't like getting a notification for "trivial"
+ changes to bugs, you can use the settings below to
+ filter some (or even all) notifications.
+ </p>
+ </td>
+ </tr>
+</table>
+
+<hr />
+
+<table>
+ <tr>
+ <td colspan="2">
+ <b>Global options:</b>
+ </td>
+ </tr>
+
+ <tr>
+ <td width="150"></td>
+ <td>
+ Only email me reports of changes made by other people
+ <input type="checkbox" name="ExcludeSelf" value="on"
+ [% " checked" IF excludeself %]>
+ <br />
+ </td>
+ </tr>
+</table>
+
+<hr />
+<b>Field/recipient specific options:</b>
+<br />
+<br />
+
+
+<table width="100%" border="1">
+ <tr>
+ <td colspan="5" align="center" width="50%">
+ <b>When my relationship to this bug is:</b>
+ </td>
+ <td rowspan="2" width="50%">
+ <b>I want to receive mail when:</b>
+ </td>
+ </tr>
+
+ <tr>
+ <td align="center" width="10%">
+ <b>Reporter</b>
+ </td>
+ <td align="center" width="10%">
+ <b>Assignee</b>
+ </td>
+ <td align="center" width="10%">
+ <b>QA Contact</b>
+ </td>
+ <td align="center" width="10%">
+ <b>CC</b>
+ </td>
+ <td align="center" width="10%">
+ <b>Voter</b>
+ </td>
+ </tr>
+
+ [% FOREACH reason = [
+ { name = 'Removeme',
+ description = 'I\'m added to or removed from this capacity' },
+ { name = 'Comments',
+ description = 'New Comments are added' },
+ { name = 'Attachments',
+ description = 'New Attachments are added' },
+ { name = 'Status',
+ description = 'Priority, status, severity, and/or milestone changes' },
+ { name = 'Resolved',
+ description = 'The bug is resolved or verified' },
+ { name = 'Keywords',
+ description = 'Keywords field changes' },
+ { name = 'CC',
+ description = 'CC field changes' },
+ { name = 'Other',
+ description = 'Any field not mentioned above changes' } ] %]
+ <tr>
+ [% FOREACH role = [ "Owner", "Reporter", "QAcontact", "CClist", "Voter" ]
+ %]
+ <td align="center">
+ <input type="checkbox" name="email[% role %][% reason.name %]" value="on"
+ [% " checked" IF $role.${reason.name} %]>
+ </td>
+ [% END %]
+ <td>
+ [% reason.description %]
+ </td>
+ </tr>
+ [% END %]
+</table>
+
+<br />
diff --git a/template/default/prefs/footer.tmpl b/template/default/prefs/footer.tmpl
new file mode 100644
index 000000000..7b0756dbf
--- /dev/null
+++ b/template/default/prefs/footer.tmpl
@@ -0,0 +1,75 @@
+[%# 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:
+ # mybugslink: boolean. True if the user wishes the My Bugs link to appear.
+ # queries: array of hashes. May be empty. Each hash has two members:
+ # name: string. The name of the query.
+ # footer: boolean. True if the query appears in the footer.
+ #%]
+
+<table>
+ <tr>
+ <th align="right">The 'My bugs' link:</th>
+ <td>
+ <select name="mybugslink">
+ <option value="1">should appear on the footer of every page</option>
+ <option value="0"
+ [% " selected" IF NOT mybugslink %]>should not be displayed
+ </option>
+ </select>
+ </td>
+ </tr>
+
+ <input type="hidden" name="numqueries" value="[% queries.size %]" />
+ [% IF queries.size %]
+ [% FOREACH query = queries %]
+ <tr>
+ <th align="right">Your query named '[% query.name FILTER html %]':</th>
+ <td>
+ <select name="query-[% loop.index %]">
+ <option value="0">should only appear in the query page</option>
+ <option value="1"
+ [% " selected" IF query.footer %]>
+ should appear on the footer of every page
+ </option>
+ </select>
+ </td>
+ </tr>
+
+ <input type="hidden" name="name-[% loop.index %]"
+ value="[% query.name FILTER html %]" />
+ [% END %]
+
+ [% ELSE %]
+ <tr>
+ <td colspan="4">
+ <br />
+ If you create remembered queries using the
+ <a href="query.cgi">query page</a>,
+ you can then come to this page and choose to have some of them
+ appear in the footer of each Bugzilla page.
+ <br />
+ <br />
+ </td>
+ </tr>
+ [% END %]
+
+</table>
diff --git a/template/default/prefs/permissions.tmpl b/template/default/prefs/permissions.tmpl
new file mode 100644
index 000000000..56429a78d
--- /dev/null
+++ b/template/default/prefs/permissions.tmpl
@@ -0,0 +1,56 @@
+[%# 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:
+ # has_bits: array of strings. May be empty.
+ # Descriptions of the permission bits the user has.
+ # set_bits: array of strings. May be empty.
+ # Descriptions of the permission bits the user can set for
+ # other people.
+ #%]
+
+<table>
+ <tr>
+ <td>
+ [% IF has_bits.size %]
+ You have the following permission bits set on your account:
+ <ul>
+ [% FOREACH bit_description = has_bits %]
+ <li>[% bit_description %]</li>
+ [% END %]
+ </ul>
+ [% ELSE %]
+ There are no permission bits set on your account.
+ [% END %]
+
+ [% IF set_bits.size %]
+ And you can turn on or off the following bits for
+ <a HREF="editusers.cgi">other users</a>:
+ <p>
+ <ul>
+ [% FOREACH bit_description = set_bits %]
+ <li>[% bit_description %]</li>
+ [% END %]
+ </ul>
+ </p>
+ [% END %]
+ </td>
+ </tr>
+</table>
diff --git a/template/default/prefs/userprefs.tmpl b/template/default/prefs/userprefs.tmpl
new file mode 100644
index 000000000..ba14521df
--- /dev/null
+++ b/template/default/prefs/userprefs.tmpl
@@ -0,0 +1,105 @@
+[%# 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:
+ # login: string. The user's Bugzilla login email address.
+ # tabs: List of hashes. May not be empty. Each hash has three members:
+ # name: string. Name of the tab (used internally.)
+ # description: string. Description of the tab (used in tab title.)
+ # saveable: boolean. True if tab has a form which can be submitted.
+ # True if user is not receiving self-generated mail.
+ # Note: For each tab name, a template "prefs/${tab.name}.tmpl" must exist,
+ # and its interface must be fulfilled.
+ # current_tab: A direct reference to one of the hashes in the tabs list.
+ # This tab will be displayed.
+ # changes_saved: boolean. True if the CGI processed form data before
+ # displaying anything.
+ #%]
+
+[% INCLUDE global/header
+ title = "User Preferences"
+ h2 = login
+ style = "td.selected_tab {
+ border-width: 2px 2px 0px;
+ border-style: solid;
+ }
+ td.unselected_tab, td.spacer {
+ border-width: 0px 0px 2px 0px;
+ border-style: solid;
+ }"
+ %]
+
+<center>
+ <table cellspacing="0" cellpadding="10" border="0" width="100%">
+ <tr>
+ <td class="spacer">&nbsp;</td>
+
+ [% FOREACH tab = tabs %]
+ [% IF tab.name == current_tab.name %]
+ <td align="center" bgcolor="lightblue" class="selected_tab">
+ [% tab.description %]
+ </td>
+ [% ELSE %]
+ <td align="center" bgcolor="#BBBBEE" class="unselected_tab">
+ <a HREF="userprefs.cgi?tab=[% tab.name %]">[% tab.description %]</a>
+ </td>
+ [% END %]
+ [% END %]
+
+ <td class="spacer">&nbsp;</td>
+ </tr>
+ </table>
+</center>
+
+[% IF changes_saved %]
+ <p>
+ <font color="red">
+ The changes to your
+ [% current_tab.description FILTER lower %] have been saved.
+ </font>
+ </p>
+[% END %]
+
+<h3>[% current_tab.description %]</h3>
+
+<form method="post">
+ <input type="hidden" name="tab" value="[% current_tab.name %]">
+
+ [% INCLUDE "prefs/${current_tab.name}.tmpl" %]
+
+ [% IF current_tab.saveable %]
+ <input type="hidden" name="dosave" value="1">
+
+ <table>
+ <tr>
+ <td width="150"></td>
+ <td>
+ <input type="submit" value="Submit Changes">
+ </td>
+ </tr>
+ </table>
+ [% END %]
+
+</form>
+
+[% INCLUDE global/footer %]
+
+
+
diff --git a/userprefs.cgi b/userprefs.cgi
index eb823326a..d86282d08 100755
--- a/userprefs.cgi
+++ b/userprefs.cgi
@@ -18,6 +18,7 @@
# Alan Raetz <al_raetz@yahoo.com>
# David Miller <justdave@syndicomm.com>
# Christopher Aillon <christopher@aillon.com>
+# Gervase Markham <gerv@gerv.net>
use diagnostics;
use strict;
@@ -28,7 +29,7 @@ require "CGI.pl";
use RelationSet;
-# Shut up misguided -w warnings about "used only once". "use vars" just
+# Shut up misguided -w warnings about "used only once". "use vars" just
# doesn't work for me.
sub sillyness {
my $zz;
@@ -36,618 +37,313 @@ sub sillyness {
$zz = $::usergroupset;
}
+# Use global template variables.
+use vars qw($template $vars);
+
my $userid;
-my $showNewEmailTech;
-
-# Note the use of arrays instead of hashes: we want the items
-# displayed in the same order as they appear in the array.
-
-my @emailGroups = (
- 'Owner', 'the Bug Owner',
- 'Reporter', 'the Reporter',
- 'QAcontact', 'the QA contact',
- 'CClist', 'on the CC list',
- 'Voter', 'a Voter'
- );
-
-my @emailFlags = (
- 'Removeme', 'When I\'m added to or removed from this capacity',
- 'Comments', 'New Comments',
- 'Attachments', 'New Attachments',
- 'Status', 'Priority, status, severity, and milestone changes',
- 'Resolved', 'When the bug is resolved or verified',
- 'Keywords', 'Keywords field changes',
- 'CC', 'CC field changes',
- 'Other', 'Any field not mentioned above changes'
- );
-
-my $defaultEmailFlagString =
- 'ExcludeSelf~' . 'on~' .
-
- 'emailOwnerRemoveme~' . 'on~' .
- 'emailOwnerComments~' . 'on~' .
- 'emailOwnerAttachments~' . 'on~' .
- 'emailOwnerStatus~' . 'on~' .
- 'emailOwnerResolved~' . 'on~' .
- 'emailOwnerKeywords~' . 'on~' .
- 'emailOwnerCC~' . 'on~' .
- 'emailOwnerOther~' . 'on~' .
-
- 'emailReporterRemoveme~' . 'on~' .
- 'emailReporterComments~' . 'on~' .
- 'emailReporterAttachments~' . 'on~' .
- 'emailReporterStatus~' . 'on~' .
- 'emailReporterResolved~' . 'on~' .
- 'emailReporterKeywords~' . 'on~' .
- 'emailReporterCC~' . 'on~' .
- 'emailReporterOther~' . 'on~' .
-
- 'emailQAcontactRemoveme~' . 'on~' .
- 'emailQAcontactComments~' . 'on~' .
- 'emailQAcontactAttachments~' . 'on~' .
- 'emailQAcontactStatus~' . 'on~' .
- 'emailQAcontactResolved~' . 'on~' .
- 'emailQAcontactKeywords~' . 'on~' .
- 'emailQAcontactCC~' . 'on~' .
- 'emailQAcontactOther~' . 'on~' .
-
- 'emailCClistRemoveme~' . 'on~' .
- 'emailCClistComments~' . 'on~' .
- 'emailCClistAttachments~' . 'on~' .
- 'emailCClistStatus~' . 'on~' .
- 'emailCClistResolved~' . 'on~' .
- 'emailCClistKeywords~' . 'on~' .
- 'emailCClistCC~' . 'on~' .
- 'emailCClistOther~' . 'on~' .
-
- 'emailVoterRemoveme~' . 'on~' .
- 'emailVoterComments~' . 'on~' .
- 'emailVoterAttachments~' . 'on~' .
- 'emailVoterStatus~' . 'on~' .
- 'emailVoterResolved~' . 'on~' .
- 'emailVoterKeywords~' . 'on~' .
- 'emailVoterCC~' . 'on~' .
- 'emailVoterOther~' . 'on' ;
-
-sub EmitEntry {
- my ($description, $entry) = (@_);
- print qq{<TR><TH ALIGN="right">$description:</TH><TD>$entry</TD></TR>\n};
-}
+# The default email flags leave all email on.
+my $defaultflagstring = "ExcludeSelf~on~";
-sub Error {
- my ($msg) = (@_);
- print qq{
-$msg
-<P>
-Please hit <B>back</B> and try again.
-};
- PutFooter();
- exit();
+foreach my $role ("Owner", "Reporter", "QAcontact", "CClist", "Voter") {
+ foreach my $reason ("Removeme", "Comments", "Attachments", "Status",
+ "Resolved", "Keywords", "CC", "Other")
+ {
+ $defaultflagstring .= "email$role$reason~on~";
+ }
}
+# Remove final "~".
+chop $defaultflagstring;
-sub ShowAccount {
+###############################################################################
+# Each panel has two functions - panel Foo has a DoFoo, to get the data
+# necessary for displaying the panel, and a SaveFoo, to save the panel's
+# contents from the form data (if appropriate.)
+# SaveFoo may be called before DoFoo.
+###############################################################################
+sub DoAccount {
SendSQL("SELECT realname FROM profiles WHERE userid = $userid");
- my ($realname) = (FetchSQLData());
-
- $realname = value_quote($realname);
-
- EmitEntry("Old password",
- qq|<input type=hidden name="Bugzilla_login" value="$::COOKIE{Bugzilla_login}">| .
- qq|<input type=password name="Bugzilla_password">|);
- EmitEntry("New password",
- qq{<input type=password name="pwd1">});
- EmitEntry("Re-enter new password",
- qq{<input type=password name="pwd2">});
- EmitEntry("Your real name (optional)",
- qq{<INPUT SIZE=35 NAME="realname" VALUE="$realname">});
+ $vars->{'realname'} = FetchSQLData();
}
sub SaveAccount {
- if ($::FORM{'Bugzilla_password'} ne ""
- || $::FORM{'pwd1'} ne "" || $::FORM{'pwd2'} ne "") {
+ if ($::FORM{'Bugzilla_password'} ne "" ||
+ $::FORM{'new_password1'} ne "" ||
+ $::FORM{'new_password2'} ne "")
+ {
my $old = SqlQuote($::FORM{'Bugzilla_password'});
- my $pwd1 = SqlQuote($::FORM{'pwd1'});
- my $pwd2 = SqlQuote($::FORM{'pwd2'});
+ my $pwd1 = SqlQuote($::FORM{'new_password1'});
+ my $pwd2 = SqlQuote($::FORM{'new_password2'});
SendSQL("SELECT cryptpassword FROM profiles WHERE userid = $userid");
my $oldcryptedpwd = FetchOneColumn();
- if ( !$oldcryptedpwd ) {
- Error("I was unable to retrieve your old password from the database.");
+ if (!$oldcryptedpwd) {
+ DisplayError("I was unable to retrieve your old password from the database.");
+ exit;
}
- if ( crypt($::FORM{'Bugzilla_password'}, $oldcryptedpwd) ne $oldcryptedpwd ) {
- Error("You did not enter your old password correctly.");
+ if (crypt($::FORM{'Bugzilla_password'}, $oldcryptedpwd) ne
+ $oldcryptedpwd)
+ {
+ DisplayError("You did not enter your old password correctly.");
+ exit;
}
if ($pwd1 ne $pwd2) {
- Error("The two passwords you entered did not match.");
+ DisplayError("The two passwords you entered did not match.");
+ exit;
}
- if ($::FORM{'pwd1'} eq '') {
- Error("You must enter a new password.");
+ if ($::FORM{'new_password1'} eq '') {
+ DisplayError("You must enter a new password.");
+ exit;
}
- my $passworderror = ValidatePassword($::FORM{'pwd1'});
- Error($passworderror) if $passworderror;
-
- my $cryptedpassword = SqlQuote(Crypt($::FORM{'pwd1'}));
- SendSQL("UPDATE profiles
- SET cryptpassword = $cryptedpassword
- WHERE userid = $userid");
+ my $passworderror = ValidatePassword($::FORM{'new_password1'});
+ (DisplayError($passworderror) && exit) if $passworderror;
+
+ my $cryptedpassword = SqlQuote(Crypt($::FORM{'new_password1'}));
+ SendSQL("UPDATE profiles
+ SET cryptpassword = $cryptedpassword
+ WHERE userid = $userid");
# Invalidate all logins except for the current one
InvalidateLogins($userid, $::COOKIE{"Bugzilla_logincookie"});
}
+
SendSQL("UPDATE profiles SET " .
"realname = " . SqlQuote(trim($::FORM{'realname'})) .
" WHERE userid = $userid");
}
-#
-# Set email flags in database based on the parameter string.
-#
-sub setEmailFlags ($) {
-
- my $emailFlagString = $_[0];
-
- SendSQL("UPDATE profiles SET emailflags = " .
- SqlQuote($emailFlagString) . " WHERE userid = $userid");
-}
-
-
-sub ShowEmailOptions () {
+sub DoEmail {
if (Param("supportwatchers")) {
my $watcheduserSet = new RelationSet;
$watcheduserSet->mergeFromDB("SELECT watched FROM watch WHERE" .
" watcher=$userid");
- my $watchedusers = $watcheduserSet->toString();
-
- print qq{
-<TR><TD COLSPAN="4"><HR></TD></TR>
-<TR><TD COLSPAN="4">
-If you want to help cover for someone when they're on vacation, or if
-you need to do the QA related to all of their bugs, you can tell bugzilla
-to send mail related to their bugs to you also. List the email addresses
-of any users you wish to watch here, separated by commas.
-</TD></TR>};
-
- EmitEntry("Users to watch",
- qq{<INPUT SIZE=35 NAME="watchedusers" VALUE="$watchedusers">});
+ $vars->{'watchedusers'} = $watcheduserSet->toString();
}
- print qq{<TR><TD COLSPAN="2"><HR></TD></TR>};
-
- showAdvancedEmailFilterOptions();
-
-print qq {
-<TABLE CELLSPACING="0" CELLPADDING="10" BORDER=0 WIDTH="100%">
-<TR><TD>};
-
-}
-
-sub showAdvancedEmailFilterOptions () {
-
- my $flags;
- my $notify;
- my %userEmailFlags = ();
-
- print qq{
- <TR><TD COLSPAN="2"><center>
- <font size=+1>Advanced Email Filtering Options</font>
- </center>
- </TD></TR><tr><td colspan="2">
- <p>
- <center>
- If you don't like getting a notification for "trivial"
- changes to bugs, you can use the settings below to
- filter some (or even all) notifications.
- </center></td></tr></table>
- <hr width=800 align=center>
- };
-
SendSQL("SELECT emailflags FROM profiles WHERE userid = $userid");
- ($flags) = FetchSQLData();
+ my ($flagstring) = FetchSQLData();
- # if the emailflags haven't been set before, that means that this user
- # hasn't been to (the email pane of?) userprefs.cgi since the change to
- # use emailflags. create a default flagset for them, based on
+ # If the emailflags haven't been set before, that means that this user
+ # hasn't been to the email pane of userprefs.cgi since the change to
+ # use emailflags. Create a default flagset for them, based on
# static defaults.
- #
- if ( !$flags ) {
- $flags = $defaultEmailFlagString;
- setEmailFlags($flags);
+ if (!$flagstring) {
+ $flagstring = $defaultflagstring;
+ SendSQL("UPDATE profiles SET emailflags = " .
+ SqlQuote($flagstring) . " WHERE userid = $userid");
}
- # the 255 param is here, because without a third param, split will
- # trim any trailing null fields, which causes perl to eject lots of
- # warnings. any suitably large number would do.
- #
- %userEmailFlags = split(/~/ , $flags, 255);
-
- showExcludeSelf(\%userEmailFlags);
-
- # print STDERR "$flags\n";
-
- print qq{
- <hr width=800 align=left>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- <b>Field/recipient specific options:</b><br><br>
- };
-
-
- my @tmpGroups = @emailGroups;
- while ((my $groupName,my $groupText) = splice(@tmpGroups,0,2) ) {
- printEmailPrefGroup($groupName,$groupText,\%userEmailFlags);
- }
-
-}
-
-sub showExcludeSelf (\%) {
+ # The 255 param is here, because without a third param, split will
+ # trim any trailing null fields, which causes Perl to eject lots of
+ # warnings. Any suitably large number would do.
+ my %emailflags = split(/~/, $flagstring, 255);
- my %CurrentFlags = %{$_[0]};
-
- my $excludeSelf = " ";
+ $vars->{'excludeself'} = 0;
- while ( my ($key,$value) = each (%CurrentFlags) ) {
-
- # print qq{flag name: $key value: $value<br>};
-
- if ( $key eq 'ExcludeSelf' ) {
-
- if ( $value eq 'on' ) {
-
- $excludeSelf = "CHECKED";
- }
- }
+ # Parse the info into a hash of hashes; the first hash keyed by role,
+ # the second by reason, and the value being 1 or 0 (undef).
+ foreach my $key (keys %emailflags) {
+ # ExcludeSelf is special.
+ if ($key eq 'ExcludeSelf' && $emailflags{$key} eq 'on') {
+ $vars->{'excludeself'} = 1;
+ next;
}
- print qq {
- <table><tr><td colspan=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- <b>Global options:</b></tr>
- <tr><td width=150></td><td>
- Only email me reports of changes made by other people
- <input type="checkbox" name="ExcludeSelf" VALUE="on" $excludeSelf>
- <br>
- </td>
- </tr>
- </table>
- };
-
-}
-
-sub printEmailPrefGroup ($$\%) {
-
- my ($groupName,$textName,$refCurrentFlags) = @_[0,1,2];
- my @tmpFlags = @emailFlags;
-
- print qq {<table cellspacing=0 cellpadding=6> };
- print qq {<tr><td colspan=2> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- When I\'m $textName, email me:</td></tr> };
-
- while ((my $flagName,my $flagText) = splice(@tmpFlags,0,2)) {
-
- printEmailOption($groupName . $flagName, $flagText, $refCurrentFlags);
- }
- print qq { </table> };
- print qq { <hr WIDTH=320 ALIGN=left> };
-}
-
-sub printEmailOption ($$\%) {
-
- my $value= '';
-
- my ($optionName,$description,$refCurrentFlags) = @_[0,1,2];
-
- #print qq{ email$optionName: $$refCurrentFlags{"email$optionName"} <br>};
-
- # if the db value is 'on', then mark that checkbox
- if ($$refCurrentFlags{"email$optionName"} eq 'on'){
- $value = 'CHECKED';
- }
-
- # **** Kludge ... also mark on if the value in $$refCurrentFlags in undef
- if (!defined($$refCurrentFlags{"email$optionName"})) {
- $value = 'CHECKED';
+ # All other keys match this regexp.
+ $key =~ /email([A-Z]+[a-z]+)([A-Z]+[a-z]*)/;
+
+ # Create a new hash if we don't have one...
+ if (!defined($vars->{$1})) {
+ $vars->{$1} = {};
+ }
+
+ if ($emailflags{$key} eq "on") {
+ $vars->{$1}{$2} = 1;
+ }
}
-
- print qq{
- <tr><td width=320></td>
- <td><input type="checkbox" name="email$optionName" VALUE="on" $value>
- $description</td>
- </tr>
- };
}
-sub SaveEmailOptions () {
-
- # I don't understand: global variables and %FORM variables are
- # not preserved between ShowEmailOptions() and SaveEmailOptions()
- # The form value here is from a hidden variable just before the SUBMIT.
-
- my $useNewEmailTech = $::FORM{'savedEmailTech'};
- my $updateString;
-
- if ( defined $::FORM{'ExcludeSelf'}) {
+# Note: we no longer store "off" values in the database.
+sub SaveEmail {
+ my $updateString = "";
+
+ if (defined $::FORM{'ExcludeSelf'}) {
$updateString .= 'ExcludeSelf~on';
} else {
$updateString .= 'ExcludeSelf~';
}
- my @tmpGroups = @emailGroups;
-
- while ((my $groupName,my $groupText) = splice(@tmpGroups,0,2) ) {
-
- my @tmpFlags = @emailFlags;
-
- while ((my $flagName,my $flagText) = splice(@tmpFlags,0,2) ) {
-
- my $entry = 'email' . $groupName . $flagName;
- my $entryValue;
-
- if (!defined $::FORM{$entry} ) {
- $entryValue = "";
- } else {
- $entryValue = $::FORM{$entry};
- }
-
- $updateString .= '~' . $entry . '~' . $entryValue;
+
+ foreach my $key (keys %::FORM) {
+ if ($key =~ /email([A-Z]+[a-z]+)([A-Z]+[a-z]*)/) {
+ $updateString .= "~$key~on";
}
}
-
- #open(FID,">updateString");
- #print qq{UPDATE STRING: $updateString <br>};
- #close(FID);
-
- SendSQL("UPDATE profiles SET emailflags = " .
- SqlQuote($updateString) . " WHERE userid = $userid");
-
- if (Param("supportwatchers") ) {
-
- if (exists $::FORM{'watchedusers'}) {
-
- # Just in case. Note that this much locking is actually overkill:
- # we don't really care if anyone reads the watch table. So
- # some small amount of contention could be gotten rid of by
- # using user-defined locks rather than table locking.
- #
- SendSQL("LOCK TABLES watch WRITE, profiles READ");
-
- # what the db looks like now
- #
- my $origWatchedUsers = new RelationSet;
- $origWatchedUsers->mergeFromDB("SELECT watched FROM watch WHERE" .
- " watcher=$userid");
-
- # update the database to look like the form
- #
- my $newWatchedUsers = new RelationSet($::FORM{'watchedusers'});
- my @CCDELTAS = $origWatchedUsers->generateSqlDeltas(
- $newWatchedUsers,
- "watch",
- "watcher",
- $userid,
- "watched");
- $CCDELTAS[0] eq "" || SendSQL($CCDELTAS[0]);
- $CCDELTAS[1] eq "" || SendSQL($CCDELTAS[1]);
-
- # all done
- #
- SendSQL("UNLOCK TABLES");
-
- }
+
+ SendSQL("UPDATE profiles SET emailflags = " . SqlQuote($updateString) .
+ " WHERE userid = $userid");
+
+ if (Param("supportwatchers") && exists $::FORM{'watchedusers'}) {
+ # Just in case. Note that this much locking is actually overkill:
+ # we don't really care if anyone reads the watch table. So
+ # some small amount of contention could be gotten rid of by
+ # using user-defined locks rather than table locking.
+ SendSQL("LOCK TABLES watch WRITE, profiles READ");
+
+ # what the db looks like now
+ my $origWatchedUsers = new RelationSet;
+ $origWatchedUsers->mergeFromDB("SELECT watched FROM watch WHERE" .
+ " watcher=$userid");
+
+ # Update the database to look like the form
+ my $newWatchedUsers = new RelationSet($::FORM{'watchedusers'});
+ my @CCDELTAS = $origWatchedUsers->generateSqlDeltas(
+ $newWatchedUsers,
+ "watch",
+ "watcher",
+ $userid,
+ "watched");
+ ($CCDELTAS[0] eq "") || SendSQL($CCDELTAS[0]);
+ ($CCDELTAS[1] eq "") || SendSQL($CCDELTAS[1]);
+
+ SendSQL("UNLOCK TABLES");
}
}
-
-sub ShowFooter {
+sub DoFooter {
SendSQL("SELECT mybugslink FROM profiles " .
"WHERE userid = $userid");
- my ($mybugslink) = (FetchSQLData());
- my $entry =
- BuildPulldown("mybugslink",
- [["1", "should appear"],
- ["0", "should not be displayed"]],
- $mybugslink);
- EmitEntry("The 'My bugs' link at the footer of each page", $entry);
+ $vars->{'mybugslink'} = FetchSQLData();
+
SendSQL("SELECT name, linkinfooter FROM namedqueries " .
"WHERE userid = $userid");
- my $count = 0;
+
+ my @queries;
while (MoreSQLData()) {
- my ($name, $linkinfooter) = (FetchSQLData());
- if ($name eq $::defaultqueryname) {
- next;
- }
- my $entry =
- BuildPulldown("query-$count",
- [["0", "should only appear in the query page"],
- ["1", "should appear on the footer of every page"]],
- $linkinfooter);
- EmitEntry("Your query named '$name'", $entry);
- my $q = value_quote($name);
- print qq{<INPUT TYPE=HIDDEN NAME="name-$count" VALUE="$q">\n};
- $count++;
- }
- print qq{<INPUT TYPE=HIDDEN NAME="numqueries" VALUE="$count">\n};
- if (!$count) {
- print qq{
-<TR><TD COLSPAN="4">
-If you go create remembered queries in the <A HREF="query.cgi">query page</A>,
-you can then come to this page and choose to have some of them appear in the
-footer of each Bugzilla page.
-</TD></TR>};
+ my ($name, $footer) = (FetchSQLData());
+ next if ($name eq $::defaultqueryname);
+
+ push (@queries, { name => $name, footer => $footer });
}
+
+ $vars->{'queries'} = \@queries;
}
-
sub SaveFooter {
my %old;
SendSQL("SELECT name, linkinfooter FROM namedqueries " .
"WHERE userid = $userid");
while (MoreSQLData()) {
- my ($name, $linkinfooter) = (FetchSQLData());
- $old{$name} = $linkinfooter;
+ my ($name, $footer) = (FetchSQLData());
+ $old{$name} = $footer;
}
- for (my $c=0 ; $c<$::FORM{'numqueries'} ; $c++) {
+ for (my $c = 0; $c < $::FORM{'numqueries'}; $c++) {
my $name = $::FORM{"name-$c"};
if (exists $old{$name}) {
my $new = $::FORM{"query-$c"};
if ($new ne $old{$name}) {
+ detaint_natural($new);
SendSQL("UPDATE namedqueries SET linkinfooter = $new " .
"WHERE userid = $userid " .
"AND name = " . SqlQuote($name));
}
} else {
- Error("Hmm, the $name query seems to have gone away.");
+ DisplayError("Hmm, the $name query seems to have gone away.");
}
}
- SendSQL("UPDATE profiles SET mybugslink = " . SqlQuote($::FORM{'mybugslink'}) .
- " WHERE userid = $userid");
+ SendSQL("UPDATE profiles SET mybugslink = " .
+ SqlQuote($::FORM{'mybugslink'}) . " WHERE userid = $userid");
}
-
-
-sub ShowPermissions {
- print "<TR><TD>You have the following permission bits set on your account:\n";
- print "<P><UL>\n";
- my $found = 0;
+
+sub DoPermissions {
+ my (@has_bits, @set_bits);
+
SendSQL("SELECT description FROM groups " .
"WHERE bit & $::usergroupset != 0 " .
"ORDER BY bit");
while (MoreSQLData()) {
- my ($description) = (FetchSQLData());
- print "<LI>$description\n";
- $found = 1;
- }
- if ($found == 0) {
- print "<LI>(No extra permission bits have been set).\n";
+ push(@has_bits, FetchSQLData());
}
- print "</UL>\n";
+
SendSQL("SELECT blessgroupset FROM profiles WHERE userid = $userid");
my $blessgroupset = FetchOneColumn();
if ($blessgroupset) {
- print "And you can turn on or off the following bits for\n";
- print qq{<A HREF="editusers.cgi">other users</A>:\n};
- print "<P><UL>\n";
SendSQL("SELECT description FROM groups " .
"WHERE bit & $blessgroupset != 0 " .
"ORDER BY bit");
while (MoreSQLData()) {
- my ($description) = (FetchSQLData());
- print "<LI>$description\n";
+ push(@set_bits, FetchSQLData());
}
- print "</UL>\n";
}
- print "</TR></TD>\n";
+
+ $vars->{'has_bits'} = \@has_bits;
+ $vars->{'set_bits'} = \@set_bits;
}
-
-
-
-
-######################################################################
-################# Live code (not sub defs) starts here ###############
+# No SavePermissions() because this panel has no changeable fields.
+###############################################################################
+# Live code (not subroutine definitions) starts here
+###############################################################################
confirm_login();
-print "Content-type: text/html\n\n";
-
GetVersionTable();
-PutHeader("User Preferences", "User Preferences", $::COOKIE{'Bugzilla_login'});
-
-# foreach my $k (sort(keys(%::FORM))) {
-# print "<pre>" . value_quote($k) . ": " . value_quote($::FORM{$k}) . "\n</pre>";
-# }
-
-my $bank = $::FORM{'bank'} || "account";
-
-my @banklist = (
- ["account", "Account settings",
- \&ShowAccount, \&SaveAccount],
- ["diffs", "Email settings",
- \&ShowEmailOptions, \&SaveEmailOptions],
- ["footer", "Page footer",
- \&ShowFooter, \&SaveFooter],
- ["permissions", "Permissions",
- \&ShowPermissions, undef]
- );
+$userid = DBNameToIdAndCheck($::COOKIE{'Bugzilla_login'});
+$vars->{'login'} = $::COOKIE{'Bugzilla_login'};
+$vars->{'changes_saved'} = $::FORM{'dosave'};
-my $numbanks = @banklist;
-my $numcols = $numbanks + 2;
+my $current_tab_name = $::FORM{'tab'} || "account";
-my $headcol = '"lightblue"';
+my @tabs = ( { name => "account", description => "Account settings",
+ saveable => "1" },
+ { name => "email", description => "Email settings",
+ saveable => "1" },
+ { name => "footer", description => "Page footer",
+ saveable => "1" },
+ { name => "permissions", description => "Permissions",
+ saveable => "0" } );
-print qq{
-<CENTER>
-<TABLE CELLSPACING="0" CELLPADDING="10" BORDER=0 WIDTH="100%">
-<TR>
-<TH COLSPAN="$numcols" BGCOLOR="lightblue">User preferences</TH>
-</TR>
-<TR><TD BGCOLOR=$headcol>&nbsp;</TD>
-};
-
-
-my $bankdescription;
-my $showfunc;
-my $savefunc;
-
-foreach my $i (@banklist) {
- my ($name, $description) = (@$i);
- my $color = "";
- if ($name eq $bank) {
- print qq{<TD ALIGN="center">$description</TD>};
- my $zz;
- ($zz, $bankdescription, $showfunc, $savefunc) = (@$i);
- } else {
- print qq{<TD ALIGN="center" BGCOLOR="lightblue"><A HREF="userprefs.cgi?bank=$name">$description</A></TD>};
+# Work out the current tab
+foreach my $tab (@tabs) {
+ if ($tab->{'name'} eq $current_tab_name) {
+ $vars->{'current_tab'} = $tab;
+ last;
}
}
-print qq{
-<TD BGCOLOR=$headcol>&nbsp;</TD></TR>
-</TABLE>
-</CENTER>
-<P>
-};
-
-
-
-if (defined $bankdescription) {
- $userid = DBNameToIdAndCheck($::COOKIE{'Bugzilla_login'});
+$vars->{'tabs'} = \@tabs;
- if ($::FORM{'dosave'}) {
- &$savefunc;
- print "Your changes have been saved.";
- }
- print qq{<H3>$bankdescription</H3><FORM METHOD="POST"><TABLE>};
-
- # execute subroutine from @banklist based on bank selected.
- &$showfunc;
-
- print qq{</TABLE><INPUT TYPE="hidden" NAME="dosave" VALUE="1">};
- print qq{<INPUT TYPE="hidden" NAME="savedEmailTech" VALUE="};
-
- # default this to 0 if it's not already set
- #
- if (defined $showNewEmailTech) {
- print qq{$showNewEmailTech">};
- } else {
- print qq{0">};
- }
- print qq{<INPUT TYPE="hidden" NAME="bank" VALUE="$bank"> };
-
- if ($savefunc) {
- print qq{<table><tr><td width=150></td><td>
- <INPUT TYPE="submit" VALUE="Submit Changes">
- </td></tr></table> };
- }
- print qq{</FORM>\n};
-} else {
- print "<P>Please choose from the above links which settings you wish to change.</P>";
+# Do any saving, and then display the current tab.
+SWITCH: for ($current_tab_name) {
+ /^account$/ && do {
+ SaveAccount() if $::FORM{'dosave'};
+ DoAccount();
+ last SWITCH;
+ };
+ /^email$/ && do {
+ SaveEmail() if $::FORM{'dosave'};
+ DoEmail();
+ last SWITCH;
+ };
+ /^footer$/ && do {
+ SaveFooter() if $::FORM{'dosave'};
+ DoFooter();
+ last SWITCH;
+ };
+ /^permissions$/ && do {
+ DoPermissions();
+ last SWITCH;
+ };
}
+# Generate and return the UI (HTML page) from the appropriate template.
+print "Content-type: text/html\n\n";
+$template->process("prefs/userprefs.tmpl", $vars)
+ || DisplayError("Template process failed: " . $template->error())
+ && exit;
-print "<P>";
-
-
-PutFooter();