[prev in list] [next in list] [prev in thread] [next in thread] 

List:       dspam-users
Subject:    [dspam-users] dspam.cgi Quarantine view: AJAX'ed!
From:       "Yoon Kit Yong" <yoonkit () gmail ! com>
Date:       2008-02-15 8:13:29
Message-ID: fb710ff20802150013y3ff76585q8eb97bf2ef7ffc54 () mail ! gmail ! com
[Download RAW message or body]

Hi guys,

I have modified the quarantine view of dspam.cgi so that its AJAXed.
If you have the job of scouring the quarantine list every day, which
may fill up to 20K records, this may help you clear off the junk.

1) "Delete Selected" is now called as an AJAX GET
2) "del" by each line deletes the spam, as well as all the entries
which share the same subject line.
3) "hash" marks the spam on the checkbox, and also marks for every
other spam with the same Subject line
4) After 100 items are marked a AJAX call to delete the items will trigger.
5) No page refresh is required unless you want to see any new incoming
spam. This speeds up the clearing process especially when your
quarantine is large.

I hope this helps!

Included is the patch for dspam.cgi v1.26. the code is very raw at the
moment, mainly because its my first time hacking perl. Most of the
modifications is Javascript stuff.

Comments are welcomed.


yk.

["dspam.ajax.patch" (text/x-diff)]

--- dspam.cgi	2007-08-01 19:53:11.000000000 +0800
+++ dspam.ajax.cgi	2008-02-13 17:07:53.000000000 +0800
@@ -145,7 +145,8 @@
     $MYURL .= "&sortby=$FORM{'sortby'}" if ($FORM{'sortby'} ne "");
     if ($FORM{'command'} eq "processQuarantine") {
       &ProcessQuarantine;
-      redirect($MYURL);
+# 080212  yky  Dont need to show the Quarantine list if its an ajax call.
+      if ($FORM{'ajax'} ne "true") {  redirect($MYURL); };
     } elsif ($FORM{'command'} eq "processFalsePositive") {
       &ProcessFalsePositive;
       redirect($MYURL);
@@ -1102,6 +1103,160 @@
   }
   $DATA{'SORT_SELECTOR'} .=  "</a>";
 
+# 080212  yky  New Controls for the AJAX calls. Will cleanup later.
+  $DATA{'SORT_SELECTOR'} .= "  <input type=\"button\" id=\"ajax_delete\" value=\"AJAX Delete 
+Selected\" 
+onclick=\"ajaxDeleteSelected()\"> <input type=\"text\" id=\"rating_val\" value=\"85\" size=5> 
+<input 
+type=\"button\" id=\"mark_rating\" value=\"Mark Rating\" 
+onclick=\"markRating()\" >  
+<div id=\"ajax_display\"></div> ";
+
+# 080212  yky  Adding Javascript stuff
+$DATA{'SORT_SELECTOR'} .= <<_END;
+
+<script>
+
+var gScript = 
+"dspam.ajax.cgi?command=processQuarantine&template=quarantine&user=dspam&sortby=Rating&ajax=true&";
+
+var gDisplay = document.getElementById("ajax_display");
+var gbtnAjaxDelete = document.getElementById("ajax_delete");
+
+var gTotalSelected = 0;
+
+function ajaxDelete( pSig )
+{ // 080212  yky  To delete just one item. Mainly for testing, but it works too.
+    var vParams = pSig+"=on";
+    var vFunc = null;
+    do_ajax( gScript, vParams,  "deleted :" +pSig );
+
+    var tr = document.getElementById( pSig );
+    tr.parentNode.removeChild( tr );
+    gDisplay.innerHTML = "deleting :" +pSig;
+}
+
+function ajaxSingleDelete( pHash )
+{
+	hashDelete( pHash );
+	ajaxDeleteSelected();
+}
+
+function ajaxDeleteSelected()
+{ // 080212  yky  To scroll through all the check boxes. Will tag off 200 items, and then HTTP GET 
+  //              to delete off the quarantined items. Anything more than 200 will cause problems
+
+	if (gbtnAjaxDelete.enabled == false) return false;
+
+	var xpath = document.evaluate( "//input[\@type='checkbox']",  document, 
+null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
+	var j = 0;
+	var vStr = "";
+	for( var i = 0; i < xpath.snapshotLength; i++)
+	{
+		var cb = xpath.snapshotItem(i);
+		if (cb.checked)
+		{
+			j++;
+			vStr += cb.name+"=on&";
+			var tr = cb.parentNode.parentNode;
+			tr.parentNode.removeChild( tr );
+		}
+		if (j > 200)
+		{
+			gTotalSelected -= j;
+			gDisplay.innerHTML = "deleting 200";
+			do_ajax( gScript, vStr, "deleted 200 / " + gTotalSelected );
+			return false;
+			j = 0;
+		}
+	}
+	if (j>0)
+	{
+		gDisplay.innerHTML = "deleting " + j;
+		gTotalSelected -= j;
+		do_ajax( gScript, vStr, "deleted " + j + " / " + gTotalSelected  );
+                return false;
+	}
+}
+
+function markRating( )
+{ // 080212  yky  Function to scroll down all the high prob spams. 
+  //		It will also check of equivalent hashes by calling hashDelete
+
+	var pRate = parseFloat( document.getElementById("rating_val").value ) / 100;
+	var vTotal = gTotalSelected;
+	gTotalSelected = 0;
+
+	var xpath = document.evaluate( "//tr[\@rating > "+pRate+" ]", document, null,
+XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
+	for( var i=0; i < xpath.snapshotLength; i++)
+	{
+                var vtr = xpath.snapshotItem(i);
+		hashDelete( vtr.attributes['hash'].nodeValue );
+		vTotal += gTotalSelected;
+		gTotalSelected = 0;
+	}
+	gTotalSelected = vTotal;
+	gDisplay.innerHTML = 'marking ' + vTotal + ' at ' + pRate;
+}
+
+function hashDelete( pHash )
+{ //  080212  yky Function to equate similar type spams and checkbox them.
+
+	var  xpath = document.evaluate( "//tr[\@hash='"+pHash+"']",  document, null, 
+XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
+	var vArr = new Array();
+	var vStr = "";
+	var i=0;
+
+	for(i=0; i < xpath.snapshotLength; i++ )
+	{
+		var vtr = xpath.snapshotItem(i);
+                var cb = vtr.getElementsByTagName('input')[0];
+                if (cb.checked == true) continue;
+ 
+		vArr.push( vtr.id );
+		vStr += vtr.id + "=on&";
+		cb.checked = true;
+	}
+	gTotalSelected += i;
+	gDisplay.innerHTML = "selected " + i + " / " + gTotalSelected;
+	
+	if (gTotalSelected > 100 ) ajaxDeleteSelected();
+}
+
+function do_ajax( pURL, pParams, pMesg )
+{ // 080212  yky  simple AJAX call to the server instead of a page refresh.
+
+    gbtnAjaxDelete.enabled = false;
+    var xmlHttpReq = false;
+    
+    if (window.XMLHttpRequest) {  // Mozilla/Safari
+        xmlHttpReq = new XMLHttpRequest();
+    }
+    else if (window.ActiveXObject) {  // IE
+        xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
+    }
+
+    xmlHttpReq.open('GET', pURL+pParams, true);
+    xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+    xmlHttpReq.onreadystatechange = function() {
+        if (xmlHttpReq.readyState == 4) {
+           // if (pFunc != null) pFunc(xmlHttpReq.responseText);
+		gDisplay.innerHTML = pMesg;
+		gbtnAjaxDelete.enabled = true;
+        }
+    }
+    xmlHttpReq.send(pParams);
+
+    return false;
+}
+
+</script>
+
+_END
+
 
   my($row, $rowclass);
   $rowclass = "rowEven";
@@ -1156,13 +1311,22 @@
       $ptime = "$ptfields[1] $ptfields[2] $times[0]:$times[1]$mer";
       }
 
+    my($sig) = $row->{'X-DSPAM-Signature'};
+    my($hash) = perlhash($row->{'Subject'});
+
     $DATA{'QUARANTINE'} .= <<_END;
-<tr>
-	<td class="$outclass" nowrap="true"><input type="checkbox" name="$row->{'X-DSPAM-Signature'}"></td>
+<tr id="$sig" hash="$hash" rating="$row->{'rating'}" >
+	<td class="$outclass" nowrap="true"><input type="checkbox" 
+id="cb_{$sig}" name="$row->{'X-DSPAM-Signature'}"></td>
 	<td class="$outclass $markclass" nowrap="true">$rating</td>
         <td class="$outclass" nowrap="true">$ptime</td>
 	<td class="$outclass" nowrap="true">$row->{'From'}</td>
-	<td class="$outclass" nowrap="true"><a href="$CONFIG{'ME'}?$url">$row->{'Subject'}</a></td>
+	<td class="$outclass" nowrap="true">
+		<a href="$CONFIG{'ME'}?$url">$row->{'Subject'}</a> &nbsp; </td>
+	<td class="$outclass" nowrap="true" align="right" >
+		<a onclick="ajaxSingleDelete( '$hash' )" >del</a> &nbsp;
+		<a onclick="hashDelete( '$hash' )">hash</a>
+	</td>
 </tr>
 _END
 
@@ -1176,6 +1340,20 @@
   &output(%DATA);
 }
 
+# Return the hashed value of a string: $hash = perlhash("key")
+# (Defined by the PERL_HASH macro in hv.h)
+# 080212  yky  From http://www.perl.com/pub/a/2002/10/01/hashes.html
+
+sub perlhash
+{
+      my($hash) = 0;
+      foreach (split //, shift) {
+          $hash = $hash*33 + ord($_);
+	  if ($hash > 9000000000000000) { return $hash; };
+      }
+      return $hash;
+}
+
 #
 # Performance Functions
 #


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic