Articles

Categories

TIMR Web Services
1412 Albatross Ave.
Comox, BC
[email protected]
250.218.5285

A Quick and Dirty SPAM Filter for Jot

As embarrassing as it is to admit - last year when we updated the Articles pages I mis-configured Jot. The comments were being stored but I wasn't getting the email notification. Last month I had time to go in and see why.

It wasn't hard to find the problem and to fix it. However, what was hard to do was sorting the SPAM from the real comments. SPAM vs comment was running at about 25 to 1. I decided to fix that at the same time.

My first option was a Captcha which is supported by Jot.

I don't like Captchas. The simple ones can be read by an Optical Character Recognition (OCR) program and these old tired eyes have trouble with the good ones. The next idea was to integrate Askimet into Modx. I use Askimet on my blog - which runs on WordPress. And, I really like it. However, they ask that developers include some feedback so the system can learn from its mistakes. Not an unreasonable request. But, I am lazy. Pulling apart the Jot code to add this feature seemed like a lot of work. Plus there was the risk I would break the code. Some I looked for a simpler solution.

One of the things I noticed in cleaning up the SPAM was there were always more than one entry from each IP address. These had to be coming from 'bots - since a real person would notice the comments were not getting published. That seemed to be the answer. Create a snippet that would block comments based on the IP address, and a method of adding new IP addresses to the list as I received SPAM comments.

The implementation was straight forward. Run some code at the beginning of every call to Jot to see if the IP address accessing the page had been blocked. In that way I wouldn't need to hack into the Jot code. (Well - just a little.)

I needed to add two items to the Jot code. The first is a modification to jot.comment.tpl. It involves making a copy of the Delete link and adding two extra variables for passing SPAM notification and the IP address of the SPAM comment. (Jot nicely puts this in the 'secip' field.) I also changed the Confirm message and used the event2 icon which looks like a yield sign. (You can make your own icon.)

The modified code looks like this:

<a href="=&spam=1&ip=#jotmod" onclick="return confirm('Are you sure you wish to SPAM this comment?')" title="SPAM Comment"><img src="/manager/media/style/MODx/images/icons/event2.gif" width="16" height="16" alt="SPAM Comment" border="0" /></a>

I put the new code just before the Delete link in jot.comment. I wanted to be able to delete a comment without adding the IP address to the block list.

The second hack is at the very beginning of the Jot code just after the $jotPath definition.

$jotPath = $modx->config['base_path'] . 'assets/snippets/jot/';

It creates an instance of the new SPAM class and calls the two functions. If this is a callback from the moderator and the spam variable is set and equals '1' the IP address is added to the jot_block table and it 'falls through' to the rest of the Jot code.

If the spam variable is not set it calls the showComment function. This function simply looks up the IP address in the jot_block table. If the address is found showComment returns a 'false' and the program exits. None of the Jot code is run. If a 'true' is returned the code again 'falls through' to the rest of the Jot code in the normal manner.

// SPAM filtering
include_once($jotPath.'spam.class.inc.php');
$spam = new SPAM();
if(isset($_REQUEST['spam']) && $_REQUEST['spam'] == 1) {
     $ip = $_REQUEST['ip'];
     $spam->addToSpam($ip);
} else {
     $show = $spam->showComment();
     if($show == false) { return; }
}
// End Spam

The filtering is done by spam.class.inc.php which I put in the Jot directory.

The class has three functions. The constructor SPAM(), addToSpam() and showComment(). I use the PHP4 constructor for those still using PHP4. It sets the tablename into $table and creates the table in mySQL if it doesn't exists. I know - this is an extra trip to the database and you can remove that code once you have everything tested.

class SPAM {
     var $table;      function SPAM() {
          global $modx;           $table = $modx->getFullTableName('jot_block');
          $this->table = $table;
          $sql = "CREATE TABLE IF NOT EXISTS $table(`ip` VARCHAR( 64 ) NOT NULL , INDEX ( `ip` ))";
          $data = $modx->db->query($sql);
     }

     function addToSpam($ip) {
          global $modx;
          $table = $this->table;
          $sql = "SELECT * FROM $table WHERE ip='$ip'";
          $result = $modx->db->query($sql);
          if($modx->db->getRecordCount($result) == '0') {                $sql = "INSERT INTO $table (`ip`) VALUES ('$ip')";
               $result = $modx->db->query($sql);
          }      }

     function showComment() {
          global $modx;
          $ip = $_SERVER['REMOTE_ADDR'];
          $table = $this->table;
          $sql = "SELECT * FROM $table WHERE ip='$ip'";
          $result = $modx->db->query($sql);
          if($modx->db->getRecordCount($result) != '0') {                return false;
          }           return true;
     }
}
?>

addToSpam($ip) first looks to see if the IP address ($ip) being added is already in the table. If it isn't it adds it to the table.

showComment() gets the $_SERVER['REMOTE_ADDR'], the IP accessing the page, and sees if it is in the jot_block table. If it is it returns 'false', if not it returns 'true'.

The code is very fairly simple. There is no way to remove an IP address from the list other than going into the database. We use it on our site and it has cut down on the number of SPAM comments. Feel free to use the code or modify it for your own needs.

If you like the code a link to TIMR - Jot SPAM Filter Code would be appreciated

Leave a Comment