Trap spambots from submitting forms with honeypot and PHP

One of the duties of webmaster is to prevent spambots from submitting web forms. If spammers are not blocked, the data collected from the visitors will contaminated with spams and it's a real nuisance to clean out this data every so often. I have been researching ways to block spams on web forms we have on our website, and found a solution that works reasonably well.

The solution is based on Giorgos Tsiledakis' work, which he posted in Google Project and PHPClasses.org named formSpamBotBlocker (v0.3). I have greatly simplified the class, and made the form values URL friendly so that the class can be used to make ajax calls. I've also made the public methods static, so that the class can be used without instantiating an object. You may download the source file as a text file.

// This script has been re-written from Giorgos Tsiledakis' 
// formSpamBotBlocker v0.3. The new script removes session 
// checking feature. The form values are 
// URL friendly for ajax use, and the script has been simplified greatly.
//
// By Scott Seong
// Last Update: 2013-04-01
//
// Edit the private variables for security and customization.

class SpamTrap
{
	private static $version = "0.2";  // Release Version
        // A hash key used to encrypt/decrypt a string.
	private static $hashKey = "4SeCuRiTy";  
	private static $minSubmitTime = 3;    // 3 Seconds.
	private static $maxSubmitTime = 43200;  // 24 Hours. 
        // Name of field where visitor info will be stored.
	private static $visitorName = "_visitor";  
        // Honeypot Field - leave blank to disable. 
        // Do not use typical field name such as
        // "honey", "trap" or "honeypot" in the name.
	private static $honeypotName = "company";
	
	public static function display()
	{
		$visitor = self::encrypt($_SERVER['HTTP_USER_AGENT'] 
                  . $_SERVER['REMOTE_ADDR']);
		$data = "\n";
		$name = "_" . substr($visitor, 0, 8);
		$value = self::encrypt(time());
		$data .= "\n";
		if (!empty(self::$honeypotName)) {
			$data .= "\n";
			$data .= "\n";
			$data .= "\n";
		}
		return $data;
	}
	
	public static function encrypt($data)
	{
		// Base64 is not URL friendly, so translate non-URL friendly characters
		// to URL friendly characters.
		return strtr(base64_encode($data . self::$hashKey), '+=/', '-_:');
	}

	public static function decrypt($data)
	{
		return  preg_replace('/'.self::$hashKey.'$/', '', 
                          base64_decode(strtr($data, '-_:', '+=/')));
	}
	
	public static function isSpam($data)
	{
		// Check visitor info (user agent and IP).
		$visitorNew = $_SERVER['HTTP_USER_AGENT'] 
                    . $_SERVER['REMOTE_ADDR'];
		$visitorOld = self::decrypt($data[self::$visitorName]);
		if ($visitorNew != $visitorOld) {
			return true;
		}
		
		// If honeypot tag is enabled, make sure it's empty.
		if (!empty(self::$honeypotName)) {
			if ($data[self::$honeypotName] != "") {
				return true;
			}
		}
		
		// Verify the form submit took at least $minSubmitTime;
		$name = "_" . substr($data[self::$visitorName], 0, 8);
		$elapsed = time() - self::decrypt($data[$name]);
		if (($elapsed <= self::$minSubmitTime) || 
                    ($elapsed > self::$maxSubmitTime)) {
			return true;
		}
		
		return false;
	}
	
	public static function debug($data)
	{
		$message = "";
		
		// Check visitor info (user agent and IP).
		$visitorNew = $_SERVER['HTTP_USER_AGENT']
                   . $_SERVER['REMOTE_ADDR'];
		$visitorOld = self::decrypt($data[self::$visitorName]);
		if ($visitorNew != $visitorOld) {
			$message .= "Different user agent or IP address. ";
		}
	
		// If honeypot tag is enabled, make sure it's empty.
		if (!empty(self::$honeypotName)) {
			if ($data[self::$honeypotName] != "") {
				$message .= "Honeypot trapped. ";
			}
		}
	
		// Verify the form submit took at least $minSubmitTime;
		$name = "_" . substr($data[self::$visitorName], 0, 8);
		$elapsed = time() - self::decrypt($data[$name]);
		if (($elapsed <= self::$minSubmitTime) || 
                   ($elapsed > self::$maxSubmitTime)) {
			$message .= "Form submitted in {$elapsed} second(s).";
		}
		
		$message .= " Form submitted from " 
                   . $_SERVER['REMOTE_ADDR'] . ".";
		return $message;
	}
}

References:
Form Spam Bot Blocker by Giorgos Tsiledakis.