This patch adds the ability to easily select multiple rows on the 
quarantine and history pages.  It implements the common local GUI
convention of selecting one row, holding shift, and selecting a
second row, and having the application select all the intermediate
rows as well.

This implementation has been tested in Firefox, Epiphany, and Konqueror.

Author: Scott Worley <sworley@chkno.net>

diff -Naur dspam-3.8.0.orig/webui/cgi-bin/dspam.cgi dspam-3.8.0/webui/cgi-bin/dspam.cgi
--- dspam-3.8.0.orig/webui/cgi-bin/dspam.cgi	2006-06-01 19:14:14.000000000 +0000
+++ dspam-3.8.0/webui/cgi-bin/dspam.cgi	2008-01-20 23:11:12.000000000 +0000
@@ -289,7 +289,9 @@
   @buffer = splice(@buffer, $begin,$CONFIG{'HISTORY_PER_PAGE'});
 
   my $retrain_checked_msg_no = 0;
+  my $counter = 0;
   while ($rec = pop@buffer) {
+    $counter++;
     my($time, $class, $from, $signature, $subject, $info, $messageid);
 
     $time = $rec->{'time'};
@@ -411,7 +413,7 @@
 <tr>
 	<td class="$cl $rowclass" nowrap="true"><small>$cllabel</td>
         <td class="$rowclass" nowrap="true"><small>
-	 <input name="msgid$retrain_checked_msg_no" type="checkbox" value="$rclass:$signature">
+	 <input name="msgid$retrain_checked_msg_no" type="checkbox" value="$rclass:$signature" id="checkbox-$counter" onclick="checkboxclicked(this)">
 	 $retrain</td>
 	<td class="$rowclass" nowrap="true"><small>$ctime</td>
 	<td class="$rowclass" nowrap="true"><small>$from</td>
@@ -1103,9 +1105,11 @@
   $DATA{'SORT_SELECTOR'} .=  "</a>";
 
 
-  my($row, $rowclass);
+  my($row, $rowclass, $counter);
   $rowclass = "rowEven";
+  $counter = 0;
   for $row (@headings) {
+    $counter++;
     my($rating, $url, $markclass, $outclass);
     $rating = sprintf("%3.0f%%", $row->{'rating'} * 100.0);
     if ($row->{'rating'} > 0.8) {
@@ -1158,7 +1162,7 @@
 
     $DATA{'QUARANTINE'} .= <<_END;
 <tr>
-	<td class="$outclass" nowrap="true"><input type="checkbox" name="$row->{'X-DSPAM-Signature'}"></td>
+	<td class="$outclass" nowrap="true"><input type="checkbox" name="$row->{'X-DSPAM-Signature'}" id="checkbox-$counter" onclick="checkboxclicked(this)"></td>
 	<td class="$outclass $markclass" nowrap="true">$rating</td>
         <td class="$outclass" nowrap="true">$ptime</td>
 	<td class="$outclass" nowrap="true">$row->{'From'}</td>
diff -Naur dspam-3.8.0.orig/webui/cgi-bin/templates/nav_history.html dspam-3.8.0/webui/cgi-bin/templates/nav_history.html
--- dspam-3.8.0.orig/webui/cgi-bin/templates/nav_history.html	2006-05-13 01:13:01.000000000 +0000
+++ dspam-3.8.0/webui/cgi-bin/templates/nav_history.html	2008-01-20 23:05:32.000000000 +0000
@@ -1,6 +1,7 @@
 <HTML>
 <HEAD><TITLE>DSPAM v3 Control Center</TITLE>
 <LINK REL="STYLESHEET" HREF="$WEB_ROOT$/base.css">
+<script type="text/javascript" src="$WEB_ROOT$/dspam.js"></script>
 </HEAD>
 <BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#000000 VLINK=#000000 ALINK=#000000>
 <div id="header">
diff -Naur dspam-3.8.0.orig/webui/cgi-bin/templates/nav_quarantine.html dspam-3.8.0/webui/cgi-bin/templates/nav_quarantine.html
--- dspam-3.8.0.orig/webui/cgi-bin/templates/nav_quarantine.html	2006-05-13 01:13:01.000000000 +0000
+++ dspam-3.8.0/webui/cgi-bin/templates/nav_quarantine.html	2008-01-20 23:05:26.000000000 +0000
@@ -1,6 +1,7 @@
 <HTML>
 <HEAD><TITLE>DSPAM v3 Control Center</TITLE>
 <LINK REL="STYLESHEET" HREF="$WEB_ROOT$/base.css">
+<script type="text/javascript" src="$WEB_ROOT$/dspam.js"></script>
 </HEAD>
 <BODY BGCOLOR=#FFFFFF TEXT=#000000 LINK=#000000 VLINK=#000000 ALINK=#000000>
 <div id="header">
diff -Naur dspam-3.8.0.orig/webui/htdocs/Makefile.am dspam-3.8.0/webui/htdocs/Makefile.am
--- dspam-3.8.0.orig/webui/htdocs/Makefile.am	2005-07-02 03:59:52.000000000 +0000
+++ dspam-3.8.0/webui/htdocs/Makefile.am	2008-01-20 23:19:37.000000000 +0000
@@ -4,5 +4,6 @@
 
 EXTRA_DIST =		\
 	base.css	\
-	dspam-logo-small.gif
+	dspam-logo-small.gif \
+	dspam.js
 
diff -Naur dspam-3.8.0.orig/webui/htdocs/Makefile.in dspam-3.8.0/webui/htdocs/Makefile.in
--- dspam-3.8.0.orig/webui/htdocs/Makefile.in	2007-03-18 16:46:12.000000000 +0000
+++ dspam-3.8.0/webui/htdocs/Makefile.in	2008-01-20 23:20:03.000000000 +0000
@@ -201,7 +201,8 @@
 target_alias = @target_alias@
 EXTRA_DIST = \
 	base.css	\
-	dspam-logo-small.gif
+	dspam-logo-small.gif \
+	dspam.js
 
 all: all-am
 
diff -Naur dspam-3.8.0.orig/webui/htdocs/dspam.js dspam-3.8.0/webui/htdocs/dspam.js
--- dspam-3.8.0.orig/webui/htdocs/dspam.js	1970-01-01 00:00:00.000000000 +0000
+++ dspam-3.8.0/webui/htdocs/dspam.js	2008-01-20 23:05:39.000000000 +0000
@@ -0,0 +1,27 @@
+// Select intermediate checkboxes on shift-click
+var shifty = false;
+var lastcheckboxchecked = false;
+function checkboxclicked(checkbox)
+{
+	var num = checkbox.id.split('-')[1];
+
+	if (lastcheckboxchecked && shifty) {
+		var start = Math.min(num, lastcheckboxchecked) + 1;
+		var end   = Math.max(num, lastcheckboxchecked) - 1;
+		var value = checkbox.checked;
+		for (i=start; i <= end; ++i) {
+			document.getElementById("checkbox-"+i).checked = value;
+		}
+	}
+	lastcheckboxchecked = num;
+}
+
+function recordshiftiness(e)
+{
+	e = e || window.event || window.Event;
+	shifty = e && ((typeof (e.shiftKey) != 'undefined' && e.shiftKey) ||
+		       e.modifiers & Event.SHIFT_MASK);
+}
+
+if (window.Event) document.captureEvents (Event.MOUSEDOWN);
+document.onmousedown = recordshiftiness;
