diff -r -u -N /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/bug_form.pl ./bug_form.pl
--- /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/bug_form.pl	Fri Nov  1 11:11:22 2002
+++ ./bug_form.pl	Fri Nov  1 11:10:50 2002
@@ -28,6 +28,167 @@
 # Use the Attachment module to display attachments for the bug.
 use Attachment;
 
+# Prepare a hash for the section of the bug form showing information
+# replicated from the Perforce source code management system by the
+# P4DTI replicator.  Derived from code contributed by Matt Albrecht
+# <matt.albrecht@zilliant.com>.
+
+sub PreparePerforceSection {
+    my ($bug_id) = (@_);
+    my $jobname;
+    my %p4dti;
+    $p4dti{'hasp4dti'} = 0;
+    if (Param("p4dti")) {
+        $p4dti{'hasp4dti'} = 1;
+        
+        # First get the row from p4dti_bugs showing whether or not this bug is
+        # replicated at all.
+        SendSQL("SELECT rid, sid, jobname FROM p4dti_bugs " .
+            "WHERE bug_id = $bug_id");
+        if (!MoreSQLData()) {
+            $p4dti{'isreplicated'} = 0;
+        } else {
+            $p4dti{'isreplicated'} = 1;
+            
+            ($p4dti{'rid'}, $p4dti{'sid'}, $jobname) =
+                (FetchSQLData());
+
+            # Replicating a bug more than once (i.e. to more than one
+            # Perforce server or via more than one replicator) is
+            # currently not supported by the replication system.
+            if (MoreSQLData()) {
+                my ($other_rid, $other_sid) = (FetchSQLData());
+                die "bug $bug_id is replicated by (".$p4dti{'rid'}.", ".
+                    $p4dti{'sid'}.") and ($other_rid, $other_sid).";
+            }
+
+            # Get P4DTI config for this rid/sid combination
+            my %p4dti_config;
+            SendSQL("SELECT config_key, config_value FROM p4dti_config " .
+                "WHERE rid = " . SqlQuote($p4dti{'rid'}) . " AND sid = " .
+                SqlQuote($p4dti{'sid'}));
+            while(MoreSQLData()) {
+                my ($p4dti_config_key, $p4dti_config_value) = FetchSQLData();
+                $p4dti_config{$p4dti_config_key} = $p4dti_config_value;
+            }
+            if (!defined $p4dti_config{'p4_server_description'}) {
+                $p4dti_config{'p4_server_description'} = "";
+            }
+            if (!defined $p4dti_config{'changelist_url'}) {
+                $p4dti_config{'changelist_url'} = "";
+            }
+            if (!defined $p4dti_config{'job_url'}) {
+                $p4dti_config{'job_url'} = "";
+            }
+            if (!defined $p4dti_config{'replicator_user'}) {
+                $p4dti_config{'replicator_user'} = "";
+            }
+            $p4dti{'config'} = \%p4dti_config;
+            
+            $jobname = value_quote($jobname);
+            if ($p4dti_config{"job_url"} ne "") {
+                $p4dti{'jobname'} = sprintf("<a href=\"$p4dti_config{'job_url'}\">$jobname</a>", $jobname);
+            } else { # no job URL pattern.
+                $p4dti{'jobname'} = $jobname;
+            }
+
+            # Get actual fixes.
+            # Every row in the p4dti_fixes table with the right bug_id
+            # is a fix for this bug.  We have to match that up with a row
+            # in the p4dti_changelist table, to get the fix description.
+            # However, if there are multiple replicators running,
+            # there may be more than one row in the p4dti_changelist
+            # table with a given changelist number.  So we make
+            # the SIDs (Perforce server IDs) match.
+            #
+            # We do a LEFT JOIN and get a not-NULL field (the rid)
+            # from the p4dti_changelists table so we can distinguish
+            # the cases in which there is not a p4dti_changelists row
+            # for this changelist.  That indicates a failure in the
+            # replicator, so we want to know about it.
+            SendSQL("SELECT profiles.realname, profiles.login_name, " .
+                    "    p4dti_fixes.changelist, " .
+                    "    p4dti_fixes.status, p4dti_changelists.p4date, " .
+                    "    p4dti_changelists.description, p4dti_changelists.rid, " .
+                    "    p4dti_changelists.flags " .
+                    "FROM p4dti_fixes, profiles " .
+                    "LEFT JOIN p4dti_changelists " .
+                    "       ON (p4dti_changelists.changelist=p4dti_fixes.changelist" .
+                    "           AND p4dti_changelists.sid = p4dti_fixes.sid)" .
+                    "WHERE p4dti_fixes.bug_id = $bug_id " .
+                    "  AND profiles.userid = p4dti_fixes.user " .
+                    "  AND p4dti_fixes.rid = ". SqlQuote($p4dti{'rid'}) .
+                    "  AND p4dti_changelists.rid = ". SqlQuote($p4dti{'rid'}) .
+                    "  AND p4dti_fixes.sid = ". SqlQuote($p4dti{'sid'}) .
+                    "  AND p4dti_changelists.sid = ". SqlQuote($p4dti{'sid'}) .
+                    " ORDER BY p4dti_fixes.changelist");
+            if (MoreSQLData()) {
+                $p4dti{'hasfixes'} = 1;
+                my @fixlist;
+                while (MoreSQLData()) {
+                    my %myset;
+                    my ($realname, $login_name, $changelist, $status, $p4date,
+                    $description, $changelist_rid, $changelist_flags) =
+                        (FetchSQLData());
+                    if (!defined $changelist_rid || $changelist_rid eq "") {
+                        die "p4dti_changelists has no row for changelist $changelist.";
+                    }
+                    $myset{'changelist_rid'} = $changelist_rid;
+                    $myset{'description'} = $description || "(none)";
+                    if ($changelist) {
+                        my $changelist_html;
+                        if ($p4dti_config{"changelist_url"} ne "") {
+                            $myset{'changelist'} =
+                                sprintf("<a href=\"$p4dti_config{'changelist_url'}\">$changelist</a>",
+                                        $changelist);
+                        } else { # no changelist URL pattern.
+                            $myset{'changelist'} = $changelist;
+                        }
+                    } else {
+                        $myset{'changelist'} = "";
+                    }
+                    if ($changelist_flags & 1) {
+                        $myset{'changelist_note'} = "";
+                    } else {
+                        $myset{'changelist_note'} = "(pending)";
+                    }
+                    if ($login_name eq $p4dti_config{"replicator_user"}) {
+                        $myset{'user_field'} = "(unknown)";
+                    } else {
+                        $myset{'user_field'} = ("<a href=\"mailto:$login_name\">" .
+                                   value_quote($realname) . "</a>");
+                    }
+                    $myset{'status'} = $status || "";
+                    $myset{'p4date'} = $p4date || "";
+                    
+                    push( @fixlist, \%myset );
+                }
+                $p4dti{'fixes'} = \@fixlist;
+            } else {
+                $p4dti{'hasfixes'} = 0;
+            }
+            # get filespecs.
+            SendSQL("SELECT filespec " .
+                "FROM p4dti_filespecs " .
+                "WHERE bug_id = $bug_id");
+            if (MoreSQLData()) {
+                $p4dti{'hasfilespecs'} = 1;
+                my @speclist;
+                while (MoreSQLData()) {
+                    my ($filespec) = (FetchSQLData());
+                    push( @speclist, $filespec );
+                }
+                $p4dti{'filespecs'} = \@speclist;
+            } else {
+                $p4dti{'hasfilespecs'} = 0;
+            }
+        }
+    }
+    return \%p4dti;
+}
+
+
+
 sub show_bug {    
     # Shut up misguided -w warnings about "used only once".  For some reason,
     # "use vars" chokes on me when I try it here.
@@ -313,6 +474,8 @@
     # Add the bug and user hashes to the variables
     $vars->{'bug'} = \%bug;
     $vars->{'user'} = \%user;
+    
+    $vars->{'p4dti'} = PreparePerforceSection($bug{'bug_id'});
 
     # Create the <link> elements for browsing bug lists
     $vars->{'navigation_links'} = navigation_links(join(':',@bug_list));
diff -r -u -N /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/defparams.pl ./defparams.pl
--- /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/defparams.pl	Fri Nov  1 11:11:22 2002
+++ ./defparams.pl	Fri Nov  1 11:10:50 2002
@@ -607,4 +607,9 @@
          "t" , 
          '1000');
 
+DefParam("p4dti",
+         "If this is on, Bugzilla uses the Perforce Defect Tracking Integration.",
+         "b",
+         0);
+
 1;
diff -r -u -N /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/doeditparams.cgi ./doeditparams.cgi
--- /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/doeditparams.cgi	Fri Nov  1 11:11:23 2002
+++ ./doeditparams.cgi	Fri Nov  1 11:10:51 2002
@@ -26,6 +26,7 @@
 use lib qw(.);
 
 require "CGI.pl";
+require "globals.pl";
 require "defparams.pl";
 
 # Shut up misguided -w warnings about "used only once":
@@ -74,6 +75,41 @@
 }
 
 
+####
+# ndl@ravenbrook.com 2001-11-23:
+# If the parameters table did not exist, create and populate it.
+# If a parameters table is incorporated into the main Bugzilla sources
+# then it should be created and initially populated from this
+# checksetup.pl, and merely updated in this file.
+
+SendSQL ("SHOW TABLES LIKE 'p4dti_bugzilla_parameters'");
+if (MoreSQLData()) {
+    print("Updating table p4dti_bugzilla_parameters.<br>\n");
+} else {
+    print("Creating table p4dti_bugzilla_parameters.<br>\n");
+    SendSQL("CREATE TABLE p4dti_bugzilla_parameters
+             (parameter_name varchar(255) not null primary key,
+              parameter_value mediumtext)");
+}
+
+foreach my $i (@::param_list) {
+    my $val = SqlQuote($::param{$i});
+    SendSQL("SELECT parameter_value
+             FROM p4dti_bugzilla_parameters
+             WHERE parameter_name = '$i'");
+    if (MoreSQLData()) {
+        SendSQL("UPDATE p4dti_bugzilla_parameters
+                 SET parameter_value = $val
+                 WHERE parameter_name = '$i'");
+    } else {
+        SendSQL("INSERT INTO p4dti_bugzilla_parameters
+                 VALUES ('$i', $val)");
+    }
+}
+
+#
+####
+
 WriteParams();
 
 unlink "data/versioncache";
diff -r -u -N /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/template/en/custom/bug/edit.html.tmpl ./template/en/custom/bug/edit.html.tmpl
--- /home/nb/info.ravenbrook.com/project/p4dti/import/2002-09-30/bugzilla-2.16.1/bugzilla-2.16.1/template/en/custom/bug/edit.html.tmpl	Thu Jan  1 01:00:00 1970
+++ ./template/en/custom/bug/edit.html.tmpl	Fri Nov  1 11:10:51 2002
@@ -0,0 +1,624 @@
+<!-- 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>
+  #%]
+
+[% filtered_desc = bug.short_desc FILTER html %]
+[% UNLESS header_done %]
+  [% PROCESS global/header.html.tmpl 
+    title = "Bug $bug.bug_id - $bug.short_desc"
+    h1 = "Bugzilla Bug $bug.bug_id"
+    h2 = filtered_desc
+    header_html = navigation_links
+   %]
+[% END %]
+
+[% PROCESS bug/navigate.html.tmpl %]
+
+<hr>
+
+<form name="changeform" method="post" action="process_bug.cgi">
+
+  <input type="hidden" name="delta_ts" value="[% bug.delta_ts %]">
+  <input type="hidden" name="longdesclength" value="[% bug.longdesclength %]">
+  <input type="hidden" name="id" value="[% bug.bug_id %]">
+
+[%# *** Platform Reporter Product OS AddCC *** %]
+
+  <table cellspacing="1" cellpadding="1" border="0">
+    <tr>      
+      <td align="right">
+        <b>Bug#:</b>
+      </td>
+      <td>
+        <a href="[% Param('urlbase') %]show_bug.cgi?id=[% bug.bug_id %]">
+          [% bug.bug_id %]</a>
+      </td>
+      
+      <td>&nbsp;</td>
+
+      <td align="right">
+        <b>Platform:</b>
+      </td>
+      [% PROCESS select selname = "rep_platform" %]
+      
+      <td align="right">
+        <b>Reporter:</b>
+      </td>
+      <td>
+        [% bug.reporter FILTER html %]
+      </td>    
+    </tr>
+    
+    <tr>
+      <td align="right">
+        <b>Product:</b>
+      </td>
+      [% PROCESS select selname => "product" %]
+      
+      <td align="right">
+        <b>OS:</b>
+      </td>
+      [% PROCESS select selname => "op_sys" %]
+
+      <td align="right">
+        <b>Add&nbsp;CC:</b>
+      </td>
+      <td>
+        <input name="newcc" size="30" value="">
+      </td>
+    </tr>
+
+[%# *** Component Version CC Priority Severity AssignedTo Milestone *** %]    
+
+    <tr>
+      <td align="right">
+        <b>
+          <a href="describecomponents.cgi?product=[% bug.product FILTER url_quote %]">
+            Component</a>:
+        </b>
+      </td>
+      <td>
+        <select name="component">
+          [% FOREACH x = component_ %]
+            <option value="[% x FILTER html %]"
+              [% " selected" IF x == bug.component %]>[% x FILTER html %]
+            </option>
+          [% END %]
+        </select>
+      </td>
+
+      <td>&nbsp;</td>
+ 
+      <td align="right">
+        <b>Version:</b>
+      </td>
+      [% PROCESS select selname => "version"  %]
+      
+      <td rowspan="4" align="right" valign="top">
+        <b>CC:</b>
+      </td>
+      <td rowspan="4" valign="top"> 
+      [% IF bug.cc %]
+        <select name="cc" multiple="multiple" size="5">
+        [% FOREACH c = bug.cc %]
+          <option value="[% c FILTER html %]">[% c FILTER html %]</option>
+        [% END %]
+        </select>
+        <br>
+        <input type="checkbox" name="removecc">Remove selected CCs
+        <br>
+      [% ELSE %]
+        <input type="hidden" name="cc" value="">
+      [% END %]
+      </td>
+    </tr>
+    
+    <tr>
+      <td align="right">
+        <b>
+          <a href="bug_status.html">Status</a>:
+        </b>
+      </td>
+      <td>[% bug.bug_status FILTER html %]</td>      
+      <td>&nbsp;</td>
+      
+      <td align="right">
+        <b><a href="bug_status.html#priority">Priority</a>:</b>
+      </td>
+      [% PROCESS select selname => "priority" %]
+    </tr>
+    
+    <tr>
+      <td align="right">
+        <b>
+          <a href="bug_status.html">Resolution</a>:
+        </b>
+      </td>
+      <td>[% bug.resolution FILTER html %]</td>      
+      <td>&nbsp;</td>
+      
+      <td align="right">
+        <b><a href="bug_status.html#severity">Severity</a>:</b>
+      </td>
+      [% PROCESS select selname = "bug_severity" %]
+      
+    </tr>
+    
+    <tr>
+      <td align="right">
+        <b>
+          <a href="bug_status.html#assigned_to">Assigned&nbsp;To</a>:
+        </b>
+      </td>
+      <td>[% bug.assigned_to FILTER html %]</td>
+      <td>&nbsp;</td>
+ 
+      [% IF Param("usetargetmilestone") && bug.target_milestone %]
+        <td align="right">
+          <b>
+            <a href="[% bug.milestoneurl FILTER html %]">Target Milestone</a>:
+          </b>
+        </td>
+        [% PROCESS select selname = "target_milestone" %]
+      [% ELSE %]
+        <td colspan="3">&nbsp;</td>
+      [% END %]
+    </tr>
+
+[%# *** QAContact URL Summary Whiteboard Keywords *** %]
+
+   [% IF Param('useqacontact') %]
+     <tr>
+       <td align="right">
+       <b>QA Contact:</b>
+       </td>
+       <td colspan="7">
+         <input name="qa_contact" 
+                value="[% bug.qa_contact FILTER html %]" size="60">
+       </td>
+     </tr>
+   [% END %]
+
+  <tr>
+    <td align="right">
+      <b>
+        [% IF bug.bug_file_loc %]
+          <a href="[% bug.bug_file_loc FILTER html %]">URL</a>:
+        [% ELSE %]
+          URL:
+        [% END %]
+      </b>
+    </td>
+    <td colspan="7">
+      <input name="bug_file_loc" 
+             value="[% bug.bug_file_loc FILTER html %]" size="60">
+    </td>
+  </tr>
+  
+  <tr>
+    <td align="right">
+      <b>Summary:</b>
+    </td>
+    <td colspan="7">
+      <input name="short_desc" 
+             value="[% bug.short_desc FILTER html %]" size="60">
+    </td>
+  </tr>
+
+  [% IF Param('usestatuswhiteboard') %] 
+    <tr>
+      <td align="right">
+        <b>Status Whiteboard:</b>
+      </td>
+      <td colspan="7">
+        <input name="status_whiteboard" 
+               value="[% bug.status_whiteboard FILTER html %]" size="60">
+      </td>
+    </tr>
+  [% END %]
+
+  [% IF use_keywords %]
+    <tr>
+      <td align="right">
+        <b>
+          <a href="describekeywords.cgi">Keywords</a>:
+        </b>
+      <td colspan="7">
+        <input name="keywords" 
+               value="[% bug.keywords.join(', ') FILTER html %]" size="60">
+      </td>
+    </tr> 
+  [% END %]
+  </table>
+  
+[%# *** Attachments *** %]
+
+  [% PROCESS attachment/list.html.tmpl 
+     attachments = bug.attachments 
+     bugid = bug.bug_id %]
+
+[%# *** Dependencies Votes *** %]
+
+  [% IF Param('usedependencies') %]
+  <table>
+    <tr>
+    [% PROCESS dependencies 
+       dep = { title => "depends on", fieldname => "dependson" } %]
+      <td rowspan="2">
+        <a href="showdependencytree.cgi?id=[% bug.bug_id %]">Show 
+        dependency tree</a>  
+
+        [% IF Param('webdotbase') %]  
+          <br>
+          <a href="showdependencygraph.cgi?id=[% bug.bug_id %]">Show 
+          dependency graph</a>
+        [% END %]
+      </td>
+    </tr>
+
+    <tr>
+    [% PROCESS dependencies 
+       dep = { title => "blocks", fieldname => "blocked" } %]
+    </tr>
+  </table>
+  [% END %]
+
+  [% IF use_votes %]
+  <table>
+    <tr>
+      <th>
+        <a href="votehelp.html">Votes</a>:
+      </th>
+      <td>
+        [% bug.votes %]&nbsp;&nbsp;&nbsp;
+        <a href="votes.cgi?action=show_bug&amp;bug_id=[% bug.bug_id %]">Show 
+        votes for this bug</a>&nbsp;&nbsp;&nbsp;
+        <a href="votes.cgi?action=show_user&amp;bug_id=[% bug.bug_id %]">Vote 
+        for this bug</a>
+      </td>
+    </tr>
+  </table>
+  [% END %]
+
+[%# *** Comments Groups *** %]
+
+  <br>
+  <b>Additional Comments:</b>
+  <br>
+  <textarea wrap="hard" name="comment" rows="10" cols="80"
+            accesskey="c"></textarea>
+  <br>
+
+  [% IF groups.size > 0 %]
+    <br>
+    <b>Only users in all of the selected groups can view this bug:</b>
+    <br>
+    <font size="-1">(Unchecking all boxes makes this a public bug.)</font>
+    <br>
+    <br>
+
+    [% FOREACH group = groups %]
+      &nbsp;&nbsp;&nbsp;&nbsp;
+      <input type="checkbox" name="bit-[% group.bit %]" value="1" 
+        [% " checked=\"checked\"" IF group.ison %]
+        [% " disabled=\"disabled\"" IF NOT group.ingroup %]>
+      [% group.description %]
+      <br>
+    [% END %]
+
+    [% IF NOT user.inallgroups %]
+      <b>
+        Only members of a group can change the visibility of a bug for 
+        that group
+      </b>
+    <br>
+    [% END %]
+
+    [% IF bug.inagroup %]
+      <p>
+        <b>But users in the roles selected below can always view this bug:</b>
+        <br>
+        <small>
+          (The assignee                                                
+          [% IF (Param('useqacontact')) %]
+             and QA contact
+          [% END %]
+          can always see a bug, and this section does not take effect unless 
+          the bug is restricted to at least one group.)
+        </small>
+      </p>
+
+      <p>
+        <input type="checkbox" name="reporter_accessible" value="1"
+          [% " checked" IF bug.reporter_accessible %]>Reporter
+        <input type="checkbox" name="cclist_accessible" value="1"
+          [% " checked" IF bug.cclist_accessible %]>CC List
+      </p>  
+    [% END %]
+  [% END %]
+
+[%# *** Knob *** %]
+
+  <br>
+  <input type="radio" name="knob" value="none" checked="checked">
+  Leave as <b>[% bug.bug_status FILTER html %]&nbsp;
+              [% bug.resolution FILTER html %]</b>
+  <br>
+
+  [% knum = 1 %]
+
+  [% IF bug.bug_status == "UNCONFIRMED" && 
+        user.canconfirm %]
+    <input type="radio" name="knob" value="confirm">
+    Confirm bug (change status to <b>NEW</b>)
+    <br>
+    [% knum = knum + 1 %]
+  [% END %]
+
+  [% IF user.canedit %]
+    [% IF bug.isopened %]
+      [% IF bug.bug_status != "ASSIGNED" && user.canconfirm %]
+        <input type="radio" name="knob" value="accept">
+        Accept bug (
+        [% "confirm bug, " IF bug.isunconfirmed %]change
+        status to <b>ASSIGNED</b>)
+        <br>
+        [% knum = knum + 1 %]
+      [% END %]
+
+      [% IF bug.resolution %]
+        <input type="radio" name="knob" value="clearresolution">
+        Clear the resolution (remove the current resolution of
+        <b>[% bug.resolution FILTER html %]</b>)<br>      
+        [% knum = knum + 1 %]
+      [% END %]
+
+      <input type="radio" name="knob" value="resolve">
+      Resolve bug, changing <a href="bug_status.html">resolution</a> to
+      <select name="resolution" 
+              onchange="document.changeform.knob[[% knum %]].checked=true">
+      [% FOREACH r = resolution %]
+        <option value="[% r FILTER html %]">[% r FILTER html %]</option>
+      [% END %]
+      </select>
+      <br>
+      [% knum = knum + 1 %]
+
+      <input type="radio" name="knob" value="duplicate">
+      Resolve bug, mark it as duplicate of bug # 
+      <input name="dup_id" size="6" 
+             onchange="if (this.value != '')
+                       {document.changeform.knob[[% knum %]].checked=true}">
+      <br>
+      [% knum = knum + 1 %]
+
+      <input type="radio" name="knob" value="reassign"> 
+      <a href="bug_status.html#assigned_to">Reassign</a> bug to
+      <input name="assigned_to" size="32" 
+             onchange="if ((this.value != '[% bug.assigned_to_email FILTER js %]') && 
+                            (this.value != '')) {
+                         document.changeform.knob[[% knum %]].checked=true; 
+                       }"  
+             value="[% bug.assigned_to_email FILTER html %]">
+      <br>
+      [% IF bug.isunconfirmed && user.canconfirm %]
+        &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" name="andconfirm">
+        and confirm bug (change status to <b>NEW</b>)
+        <br>
+      [% END %]
+      [% knum = knum + 1 %]
+
+      <input type="radio" name="knob" value="reassignbycomponent">
+      Reassign bug to owner
+      [% "and QA contact" IF useqacontact %]
+      of selected component
+      <br>
+      [% IF bug.isunconfirmed && user.canconfirm %]
+        &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" name="compconfirm">
+        and confirm bug (change status to <b>NEW</b>)
+        <br>
+      [% END %]
+      [% knum = knum + 1 %]
+    [% ELSE %]
+      [% IF bug.resolution != "MOVED" ||
+           (bug.resolution == "MOVED" && user.canmove) %]  
+        <input type="radio" name="knob" value="reopen"> Reopen bug
+        <br>
+        [% knum = knum + 1 %]
+      [% END %]
+      [% IF bug.bug_status == "RESOLVED" %]
+        <input type="radio" name="knob" value="verify">
+        Mark bug as <b>VERIFIED</b><br>
+        [% knum = knum + 1 %]
+      [% END %]
+      [% IF bug.bug_status != "CLOSED" %]
+        <input type="radio" name="knob" value="close">
+        Mark bug as <b>CLOSED</b><br>
+        [% knum = knum + 1 %]
+      [% END %]
+    [% END %]
+  [% END %]  
+  
+  <input type="submit" value="Commit">
+  <input type="hidden" name="form_name" value="process_bug">
+  <p>
+    <font size="+1">
+      <b>
+        <a href="show_activity.cgi?id=[% bug.bug_id %]">View Bug Activity</a>
+        &nbsp; | &nbsp;
+        <a href="long_list.cgi?buglist=[% bug.bug_id %]">Format For Printing</a>
+      </b>
+    </font>
+
+    [% IF user.canmove %]
+      &nbsp; <font size="+1"><b> | </b></font> &nbsp;
+      <input type="submit" name="action" 
+             value="[% Param("move-button-text") %]">
+    [% END %]
+  </p>  
+</form>
+
+[%# *** Additional Comments *** %]
+
+<table>
+  <tr>
+    <td align="left">
+      <b>
+        <a name="c0" href="#c0">Description</a>:
+      </b>
+    </td>
+    <td align="right" width="100%">
+      Opened: [% bug.creation_ts %]
+    </td>
+  </tr>
+</table>
+<hr>
+
+[% PROCESS bug/comments.html.tmpl 
+   comments = bug.comments 
+ %]
+  
+<hr>
+
+[%# P4DTI section.  Derived in part from code contributed by Matt
+  # Albrecht <matt.albrecht@zilliant.com>.
+  #%]
+[% IF p4dti.hasp4dti %]
+    <div class="p4dti">
+
+    [% IF p4dti.isreplicated %]
+    
+        <p><b>Perforce replication:</b></p>
+        <table border="0" cellspacing="0" cellpadding="4">
+            <tr valign="top">
+                <td><b>Job</b></td>
+                <td> [% p4dti.jobname %] </td>
+            </tr>
+            <tr valign="top">
+              <td><b>Server</b></td>
+              <td>
+                [% p4dti.sid FILTER html %]
+                [% IF p4dti.config.p4_server_description %]:
+                [% p4dti.config.p4_server_description FILTER html %]
+                [% END %]
+              </td>
+            </tr>
+            <tr valign="top">
+              <td><b>Replicator ID</b></td>
+              <td>[% p4dti.rid FILTER html %]</td>
+            </tr>
+            <tr valign="top">
+              <td><b>Fixes</b></td>
+              <td>
+              [% IF p4dti.hasfixes %]
+                <table border="1" cellspacing="0" cellpadding="4">
+                  <tr align="left" valign="top">
+                    <th>Change</th>
+                    <th>Effect</th>
+                    <th>Date</th>
+                    <th>User</th>
+                    <th>Description</th>
+                  </tr>
+                [% FOREACH fix = p4dti.fixes %]
+                  <tr valign="top">
+                    <td>[% fix.changelist %]
+                    [% fix.changelist_note %]</td>
+                    <td>[% fix.status FILTER html %]</td>
+                    <td>[% fix.p4date FILTER html %]</td>
+                    <td>[% fix.user_field %]</td>
+                    <td>[% fix.description FILTER html %]</td>
+                  </tr>
+                [% END %]
+                </table>
+              [% ELSE %]
+                None.
+              [% END %]
+              </td>
+            </tr>
+            <tr valign="top">
+              <td><b>Filespecs</b></td>
+              <td>
+              [% IF p4dti.hasfilespecs %]
+                <table>
+                [% FOREACH f = p4dti.filespecs %]
+                  <tr valign="top">
+                    <td>[% f FILTER html %]</td>
+                  </tr>
+                [% END %]
+                </table>
+              [% ELSE %]
+                None.
+              [% END %]
+              </td>
+            </tr>
+        </table>
+    
+    [% ELSE %]
+
+        <p><b>Not replicated in Perforce.</b></p>
+    
+    [% END %]
+    <hr/>
+    </div>
+[% END %]
+
+<hr>
+
+[% PROCESS bug/navigate.html.tmpl %]
+
+<br>
+
+[% PROCESS global/footer.html.tmpl %]
+
+
+[%############################################################################%]
+[%# Block for dependencies                                                   #%]
+[%############################################################################%]
+
+[% BLOCK dependencies %]
+  <th align="right">Bug [% bug.bug_id %] [%+ dep.title %]:</th>
+  <td>
+  [% FOREACH depbug = bug.${dep.fieldname} %]
+    [% GetBugLink(depbug, depbug) %][% " " %]
+  [% END %]
+  </td>
+  <td>
+    <input name="[% dep.fieldname %]" 
+           value="[% bug.${dep.fieldname}.join(', ') %]">
+  </td>
+[% END %]
+
+
+[%############################################################################%]
+[%# Block for SELECT fields                                                  #%]
+[%############################################################################%]
+
+[% BLOCK select %]  
+  <td>
+    <select name="[% selname %]">
+      [% FOREACH x = ${selname} %]
+        <option value="[% x FILTER html %]"
+          [% " selected" IF x == bug.${selname} %]>[% x FILTER html %]
+        </option>
+      [% END %]
+    </select>
+  </td>
+  <td>&nbsp;</td>
+[% END %]