| webmaster@64 | 1 <?php | 
| webmaster@64 | 2 /** | 
| webmaster@64 | 3  * 01.07.2008 22:32:28est | 
| webmaster@64 | 4  * | 
| webmaster@64 | 5  * Akismet PHP4 class | 
| webmaster@64 | 6  * | 
| webmaster@64 | 7  * <b>Usage</b> | 
| webmaster@64 | 8  * <code> | 
| webmaster@64 | 9  *    $comment = array( | 
| webmaster@64 | 10  *           'author'    => 'viagra-test-123', | 
| webmaster@64 | 11  *           'email'     => 'test@example.com', | 
| webmaster@64 | 12  *           'website'   => 'http://www.example.com/', | 
| webmaster@64 | 13  *           'body'      => 'This is a test comment', | 
| webmaster@64 | 14  *           'permalink' => 'http://yourdomain.com/yourblogpost.url', | 
| webmaster@64 | 15  *        ); | 
| webmaster@64 | 16  * | 
| webmaster@64 | 17  *    $akismet = new Akismet('http://www.yourdomain.com/', 'YOUR_WORDPRESS_API_KEY', $comment); | 
| webmaster@64 | 18  * | 
| webmaster@64 | 19  *    if($akismet->errorsExist()) { | 
| webmaster@64 | 20  *        echo"Couldn't connected to Akismet server!"; | 
| webmaster@64 | 21  *    } else { | 
| webmaster@64 | 22  *        if($akismet->isSpam()) { | 
| webmaster@64 | 23  *            echo"Spam detected"; | 
| webmaster@64 | 24  *        } else { | 
| webmaster@64 | 25  *            echo"yay, no spam!"; | 
| webmaster@64 | 26  *        } | 
| webmaster@64 | 27  *    } | 
| webmaster@64 | 28  * </code> | 
| webmaster@64 | 29  * | 
| webmaster@64 | 30  * @author Bret Kuhns {@link www.miphp.net} | 
| webmaster@64 | 31  * @link http://www.miphp.net/blog/view/new_akismet_class/ | 
| webmaster@64 | 32  * @version 0.3.4 | 
| webmaster@64 | 33  * @license http://www.opensource.org/licenses/mit-license.php MIT License | 
| webmaster@64 | 34  */ | 
| webmaster@64 | 35 | 
| webmaster@64 | 36 | 
| webmaster@64 | 37 | 
| webmaster@64 | 38 // Error constants | 
| webmaster@64 | 39 define("AKISMET_SERVER_NOT_FOUND",	0); | 
| webmaster@64 | 40 define("AKISMET_RESPONSE_FAILED",	1); | 
| webmaster@64 | 41 define("AKISMET_INVALID_KEY",		2); | 
| webmaster@64 | 42 | 
| webmaster@64 | 43 | 
| webmaster@64 | 44 | 
| webmaster@64 | 45 // Base class to assist in error handling between Akismet classes | 
| webmaster@64 | 46 class AkismetObject { | 
| webmaster@64 | 47 	var $errors = array(); | 
| webmaster@64 | 48 | 
| webmaster@64 | 49 | 
| webmaster@64 | 50 	/** | 
| webmaster@64 | 51 	 * Add a new error to the errors array in the object | 
| webmaster@64 | 52 	 * | 
| webmaster@64 | 53 	 * @param	String	$name	A name (array key) for the error | 
| webmaster@64 | 54 	 * @param	String	$string	The error message | 
| webmaster@64 | 55 	 * @return void | 
| webmaster@64 | 56 	 */ | 
| webmaster@64 | 57 	// Set an error in the object | 
| webmaster@64 | 58 	function setError($name, $message) { | 
| webmaster@64 | 59 		$this->errors[$name] = $message; | 
| webmaster@64 | 60 	} | 
| webmaster@64 | 61 | 
| webmaster@64 | 62 | 
| webmaster@64 | 63 	/** | 
| webmaster@64 | 64 	 * Return a specific error message from the errors array | 
| webmaster@64 | 65 	 * | 
| webmaster@64 | 66 	 * @param	String	$name	The name of the error you want | 
| webmaster@64 | 67 	 * @return mixed	Returns a String if the error exists, a false boolean if it does not exist | 
| webmaster@64 | 68 	 */ | 
| webmaster@64 | 69 	function getError($name) { | 
| webmaster@64 | 70 		if($this->isError($name)) { | 
| webmaster@64 | 71 			return $this->errors[$name]; | 
| webmaster@64 | 72 		} else { | 
| webmaster@64 | 73 			return false; | 
| webmaster@64 | 74 		} | 
| webmaster@64 | 75 	} | 
| webmaster@64 | 76 | 
| webmaster@64 | 77 | 
| webmaster@64 | 78 	/** | 
| webmaster@64 | 79 	 * Return all errors in the object | 
| webmaster@64 | 80 	 * | 
| webmaster@64 | 81 	 * @return String[] | 
| webmaster@64 | 82 	 */ | 
| webmaster@64 | 83 	function getErrors() { | 
| webmaster@64 | 84 		return (array)$this->errors; | 
| webmaster@64 | 85 	} | 
| webmaster@64 | 86 | 
| webmaster@64 | 87 | 
| webmaster@64 | 88 	/** | 
| webmaster@64 | 89 	 * Check if a certain error exists | 
| webmaster@64 | 90 	 * | 
| webmaster@64 | 91 	 * @param	String	$name	The name of the error you want | 
| webmaster@64 | 92 	 * @return boolean | 
| webmaster@64 | 93 	 */ | 
| webmaster@64 | 94 	function isError($name) { | 
| webmaster@64 | 95 		return isset($this->errors[$name]); | 
| webmaster@64 | 96 	} | 
| webmaster@64 | 97 | 
| webmaster@64 | 98 | 
| webmaster@64 | 99 	/** | 
| webmaster@64 | 100 	 * Check if any errors exist | 
| webmaster@64 | 101 	 * | 
| webmaster@64 | 102 	 * @return boolean | 
| webmaster@64 | 103 	 */ | 
| webmaster@64 | 104 	function errorsExist() { | 
| webmaster@64 | 105 		return (count($this->errors) > 0); | 
| webmaster@64 | 106 	} | 
| webmaster@64 | 107 | 
| webmaster@64 | 108 | 
| webmaster@64 | 109 } | 
| webmaster@64 | 110 | 
| webmaster@64 | 111 | 
| webmaster@64 | 112 | 
| webmaster@64 | 113 | 
| webmaster@64 | 114 | 
| webmaster@64 | 115 // Used by the Akismet class to communicate with the Akismet service | 
| webmaster@64 | 116 class AkismetHttpClient extends AkismetObject { | 
| webmaster@64 | 117 	var $akismetVersion = '1.1'; | 
| webmaster@64 | 118 	var $con; | 
| webmaster@64 | 119 	var $host; | 
| webmaster@64 | 120 	var $port; | 
| webmaster@64 | 121 	var $apiKey; | 
| webmaster@64 | 122 	var $blogUrl; | 
| webmaster@64 | 123 	var $errors = array(); | 
| webmaster@64 | 124 | 
| webmaster@64 | 125 | 
| webmaster@64 | 126 	// Constructor | 
| webmaster@64 | 127 	function AkismetHttpClient($host, $blogUrl, $apiKey, $port = 80) { | 
| webmaster@64 | 128 		$this->host = $host; | 
| webmaster@64 | 129 		$this->port = $port; | 
| webmaster@64 | 130 		$this->blogUrl = $blogUrl; | 
| webmaster@64 | 131 		$this->apiKey = $apiKey; | 
| webmaster@64 | 132 	} | 
| webmaster@64 | 133 | 
| webmaster@64 | 134 | 
| webmaster@64 | 135 	// Use the connection active in $con to get a response from the server and return that response | 
| webmaster@64 | 136 	function getResponse($request, $path, $type = "post", $responseLength = 1160) { | 
| webmaster@64 | 137 		$this->_connect(); | 
| webmaster@64 | 138 | 
| webmaster@64 | 139 		if($this->con && !$this->isError(AKISMET_SERVER_NOT_FOUND)) { | 
| webmaster@64 | 140 			$request  = | 
| webmaster@64 | 141 					strToUpper($type)." /{$this->akismetVersion}/$path HTTP/1.1\r\n" . | 
| webmaster@64 | 142 					"Host: ".((!empty($this->apiKey)) ? $this->apiKey."." : null)."{$this->host}\r\n" . | 
| webmaster@64 | 143 					"Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n" . | 
| webmaster@64 | 144 					"Content-Length: ".strlen($request)."\r\n" . | 
| webmaster@64 | 145 					"User-Agent: Akismet PHP4 Class\r\n" . | 
| webmaster@64 | 146 					"\r\n" . | 
| webmaster@64 | 147 					$request | 
| webmaster@64 | 148 				; | 
| webmaster@64 | 149 			$response = ""; | 
| webmaster@64 | 150 | 
| webmaster@64 | 151 			@fwrite($this->con, $request); | 
| webmaster@64 | 152 | 
| webmaster@64 | 153 			while(!feof($this->con)) { | 
| webmaster@64 | 154 				$response .= @fgets($this->con, $responseLength); | 
| webmaster@64 | 155 			} | 
| webmaster@64 | 156 | 
| webmaster@64 | 157 			$response = explode("\r\n\r\n", $response, 2); | 
| webmaster@64 | 158 			return $response[1]; | 
| webmaster@64 | 159 		} else { | 
| webmaster@64 | 160 			$this->setError(AKISMET_RESPONSE_FAILED, "The response could not be retrieved."); | 
| webmaster@64 | 161 		} | 
| webmaster@64 | 162 | 
| webmaster@64 | 163 		$this->_disconnect(); | 
| webmaster@64 | 164 	} | 
| webmaster@64 | 165 | 
| webmaster@64 | 166 | 
| webmaster@64 | 167 	// Connect to the Akismet server and store that connection in the instance variable $con | 
| webmaster@64 | 168 	function _connect() { | 
| webmaster@64 | 169 		if(!($this->con = @fsockopen($this->host, $this->port))) { | 
| webmaster@64 | 170 			$this->setError(AKISMET_SERVER_NOT_FOUND, "Could not connect to akismet server."); | 
| webmaster@64 | 171 		} | 
| webmaster@64 | 172 	} | 
| webmaster@64 | 173 | 
| webmaster@64 | 174 | 
| webmaster@64 | 175 	// Close the connection to the Akismet server | 
| webmaster@64 | 176 	function _disconnect() { | 
| webmaster@64 | 177 		@fclose($this->con); | 
| webmaster@64 | 178 	} | 
| webmaster@64 | 179 | 
| webmaster@64 | 180 | 
| webmaster@64 | 181 } | 
| webmaster@64 | 182 | 
| webmaster@64 | 183 | 
| webmaster@64 | 184 | 
| webmaster@64 | 185 | 
| webmaster@64 | 186 | 
| webmaster@64 | 187 // The controlling class. This is the ONLY class the user should instantiate in | 
| webmaster@64 | 188 // order to use the Akismet service! | 
| webmaster@64 | 189 class Akismet extends AkismetObject { | 
| webmaster@64 | 190 	var $apiPort = 80; | 
| webmaster@64 | 191 	var $akismetServer = 'rest.akismet.com'; | 
| webmaster@64 | 192 	var $akismetVersion = '1.1'; | 
| webmaster@64 | 193 	var $http; | 
| webmaster@64 | 194 | 
| webmaster@64 | 195 	var $ignore = array( | 
| webmaster@64 | 196 			'HTTP_COOKIE', | 
| webmaster@64 | 197 			'HTTP_X_FORWARDED_FOR', | 
| webmaster@64 | 198 			'HTTP_X_FORWARDED_HOST', | 
| webmaster@64 | 199 			'HTTP_MAX_FORWARDS', | 
| webmaster@64 | 200 			'HTTP_X_FORWARDED_SERVER', | 
| webmaster@64 | 201 			'REDIRECT_STATUS', | 
| webmaster@64 | 202 			'SERVER_PORT', | 
| webmaster@64 | 203 			'PATH', | 
| webmaster@64 | 204 			'DOCUMENT_ROOT', | 
| webmaster@64 | 205 			'SERVER_ADMIN', | 
| webmaster@64 | 206 			'QUERY_STRING', | 
| webmaster@64 | 207 			'PHP_SELF', | 
| webmaster@64 | 208 			'argv' | 
| webmaster@64 | 209 		); | 
| webmaster@64 | 210 | 
| webmaster@64 | 211 	var $blogUrl = ""; | 
| webmaster@64 | 212 	var $apiKey  = ""; | 
| webmaster@64 | 213 	var $comment = array(); | 
| webmaster@64 | 214 | 
| webmaster@64 | 215 | 
| webmaster@64 | 216 	/** | 
| webmaster@64 | 217 	 * Constructor | 
| webmaster@64 | 218 	 * | 
| webmaster@64 | 219 	 * Set instance variables, connect to Akismet, and check API key | 
| webmaster@64 | 220 	 * | 
| webmaster@64 | 221 	 * @param	String	$blogUrl	The URL to your own blog | 
| webmaster@64 | 222 	 * @param 	String	$apiKey		Your wordpress API key | 
| webmaster@64 | 223 	 * @param 	String[]	$comment	A formatted comment array to be examined by the Akismet service | 
| webmaster@64 | 224 	 * @return	Akismet | 
| webmaster@64 | 225 	 */ | 
| webmaster@64 | 226 	function Akismet($blogUrl, $apiKey, $comment = array()) { | 
| webmaster@64 | 227 		$this->blogUrl = $blogUrl; | 
| webmaster@64 | 228 		$this->apiKey  = $apiKey; | 
| webmaster@64 | 229 		$this->setComment($comment); | 
| webmaster@64 | 230 | 
| webmaster@64 | 231 		// Connect to the Akismet server and populate errors if they exist | 
| webmaster@64 | 232 		$this->http = new AkismetHttpClient($this->akismetServer, $blogUrl, $apiKey); | 
| webmaster@64 | 233 		if($this->http->errorsExist()) { | 
| webmaster@64 | 234 			$this->errors = array_merge($this->errors, $this->http->getErrors()); | 
| webmaster@64 | 235 		} | 
| webmaster@64 | 236 | 
| webmaster@64 | 237 		// Check if the API key is valid | 
| webmaster@64 | 238 		if(!$this->_isValidApiKey($apiKey)) { | 
| webmaster@64 | 239 			$this->setError(AKISMET_INVALID_KEY, "Your Akismet API key is not valid."); | 
| webmaster@64 | 240 		} | 
| webmaster@64 | 241 	} | 
| webmaster@64 | 242 | 
| webmaster@64 | 243 | 
| webmaster@64 | 244 	/** | 
| webmaster@64 | 245 	 * Query the Akismet and determine if the comment is spam or not | 
| webmaster@64 | 246 	 * | 
| webmaster@64 | 247 	 * @return	boolean | 
| webmaster@64 | 248 	 */ | 
| webmaster@64 | 249 	function isSpam() { | 
| webmaster@64 | 250 		$response = $this->http->getResponse($this->_getQueryString(), 'comment-check'); | 
| webmaster@64 | 251 | 
| webmaster@64 | 252 		return ($response == "true"); | 
| webmaster@64 | 253 	} | 
| webmaster@64 | 254 | 
| webmaster@64 | 255 | 
| webmaster@64 | 256 	/** | 
| webmaster@64 | 257 	 * Submit this comment as an unchecked spam to the Akismet server | 
| webmaster@64 | 258 	 * | 
| webmaster@64 | 259 	 * @return	void | 
| webmaster@64 | 260 	 */ | 
| webmaster@64 | 261 	function submitSpam() { | 
| webmaster@64 | 262 		$this->http->getResponse($this->_getQueryString(), 'submit-spam'); | 
| webmaster@64 | 263 	} | 
| webmaster@64 | 264 | 
| webmaster@64 | 265 | 
| webmaster@64 | 266 	/** | 
| webmaster@64 | 267 	 * Submit a false-positive comment as "ham" to the Akismet server | 
| webmaster@64 | 268 	 * | 
| webmaster@64 | 269 	 * @return	void | 
| webmaster@64 | 270 	 */ | 
| webmaster@64 | 271 	function submitHam() { | 
| webmaster@64 | 272 		$this->http->getResponse($this->_getQueryString(), 'submit-ham'); | 
| webmaster@64 | 273 	} | 
| webmaster@64 | 274 | 
| webmaster@64 | 275 | 
| webmaster@64 | 276 	/** | 
| webmaster@64 | 277 	 * Manually set the comment value of the instantiated object. | 
| webmaster@64 | 278 	 * | 
| webmaster@64 | 279 	 * @param	Array	$comment | 
| webmaster@64 | 280 	 * @return	void | 
| webmaster@64 | 281 	 */ | 
| webmaster@64 | 282 	function setComment($comment) { | 
| webmaster@64 | 283 		$this->comment = $comment; | 
| webmaster@64 | 284 		if(!empty($comment)) { | 
| webmaster@64 | 285 			$this->_formatCommentArray(); | 
| webmaster@64 | 286 			$this->_fillCommentValues(); | 
| webmaster@64 | 287 		} | 
| webmaster@64 | 288 	} | 
| webmaster@64 | 289 | 
| webmaster@64 | 290 | 
| webmaster@64 | 291 	/** | 
| webmaster@64 | 292 	 * Returns the current value of the object's comment array. | 
| webmaster@64 | 293 	 * | 
| webmaster@64 | 294 	 * @return	Array | 
| webmaster@64 | 295 	 */ | 
| webmaster@64 | 296 	function getComment() { | 
| webmaster@64 | 297 		return $this->comment; | 
| webmaster@64 | 298 	} | 
| webmaster@64 | 299 | 
| webmaster@64 | 300 | 
| webmaster@64 | 301 	/** | 
| webmaster@64 | 302 	 * Check with the Akismet server to determine if the API key is valid | 
| webmaster@64 | 303 	 * | 
| webmaster@64 | 304 	 * @access	Protected | 
| webmaster@64 | 305 	 * @param	String	$key	The Wordpress API key passed from the constructor argument | 
| webmaster@64 | 306 	 * @return	boolean | 
| webmaster@64 | 307 	 */ | 
| webmaster@64 | 308 	function _isValidApiKey($key) { | 
| webmaster@64 | 309 		$keyCheck = $this->http->getResponse("key=".$this->apiKey."&blog=".$this->blogUrl, 'verify-key'); | 
| webmaster@64 | 310 | 
| webmaster@64 | 311 		return ($keyCheck == "valid"); | 
| webmaster@64 | 312 	} | 
| webmaster@64 | 313 | 
| webmaster@64 | 314 | 
| webmaster@64 | 315 	/** | 
| webmaster@64 | 316 	 * Format the comment array in accordance to the Akismet API | 
| webmaster@64 | 317 	 * | 
| webmaster@64 | 318 	 * @access	Protected | 
| webmaster@64 | 319 	 * @return	void | 
| webmaster@64 | 320 	 */ | 
| webmaster@64 | 321 	function _formatCommentArray() { | 
| webmaster@64 | 322 		$format = array( | 
| webmaster@64 | 323 				'type' => 'comment_type', | 
| webmaster@64 | 324 				'author' => 'comment_author', | 
| webmaster@64 | 325 				'email' => 'comment_author_email', | 
| webmaster@64 | 326 				'website' => 'comment_author_url', | 
| webmaster@64 | 327 				'body' => 'comment_content' | 
| webmaster@64 | 328 			); | 
| webmaster@64 | 329 | 
| webmaster@64 | 330 		foreach($format as $short => $long) { | 
| webmaster@64 | 331 			if(isset($this->comment[$short])) { | 
| webmaster@64 | 332 				$this->comment[$long] = $this->comment[$short]; | 
| webmaster@64 | 333 				unset($this->comment[$short]); | 
| webmaster@64 | 334 			} | 
| webmaster@64 | 335 		} | 
| webmaster@64 | 336 	} | 
| webmaster@64 | 337 | 
| webmaster@64 | 338 | 
| webmaster@64 | 339 	/** | 
| webmaster@64 | 340 	 * Fill any values not provided by the developer with available values. | 
| webmaster@64 | 341 	 * | 
| webmaster@64 | 342 	 * @return	void | 
| webmaster@64 | 343 	 */ | 
| webmaster@64 | 344 	function _fillCommentValues() { | 
| webmaster@64 | 345 		if(!isset($this->comment['user_ip'])) { | 
| webmaster@64 | 346 			$this->comment['user_ip'] = ($_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR')) ? $_SERVER['REMOTE_ADDR'] : getenv('HTTP_X_FORWARDED_FOR'); | 
| webmaster@64 | 347 		} | 
| webmaster@64 | 348 		if(!isset($this->comment['user_agent'])) { | 
| webmaster@64 | 349 			$this->comment['user_agent'] = $_SERVER['HTTP_USER_AGENT']; | 
| webmaster@64 | 350 		} | 
| webmaster@64 | 351 		if(!isset($this->comment['referrer'])) { | 
| webmaster@64 | 352 			$this->comment['referrer'] = $_SERVER['HTTP_REFERER']; | 
| webmaster@64 | 353 		} | 
| webmaster@64 | 354 		if(!isset($this->comment['blog'])) { | 
| webmaster@64 | 355 			$this->comment['blog'] = $this->blogUrl; | 
| webmaster@64 | 356 		} | 
| webmaster@64 | 357 	} | 
| webmaster@64 | 358 | 
| webmaster@64 | 359 | 
| webmaster@64 | 360 	/** | 
| webmaster@64 | 361 	 * Build a query string for use with HTTP requests | 
| webmaster@64 | 362 	 * | 
| webmaster@64 | 363 	 * @access	Protected | 
| webmaster@64 | 364 	 * @return	String | 
| webmaster@64 | 365 	 */ | 
| webmaster@64 | 366 	function _getQueryString() { | 
| webmaster@64 | 367 		foreach($_SERVER as $key => $value) { | 
| webmaster@64 | 368 			if(!in_array($key, $this->ignore)) { | 
| webmaster@64 | 369 				if($key == 'REMOTE_ADDR') { | 
| webmaster@64 | 370 					$this->comment[$key] = $this->comment['user_ip']; | 
| webmaster@64 | 371 				} else { | 
| webmaster@64 | 372 					$this->comment[$key] = $value; | 
| webmaster@64 | 373 				} | 
| webmaster@64 | 374 			} | 
| webmaster@64 | 375 		} | 
| webmaster@64 | 376 | 
| webmaster@64 | 377 		$query_string = ''; | 
| webmaster@64 | 378 | 
| webmaster@64 | 379 		foreach($this->comment as $key => $data) { | 
| webmaster@64 | 380 			$query_string .= $key . '=' . urlencode(stripslashes($data)) . '&'; | 
| webmaster@64 | 381 		} | 
| webmaster@64 | 382 | 
| webmaster@64 | 383 		return $query_string; | 
| webmaster@64 | 384 	} | 
| webmaster@64 | 385 | 
| webmaster@64 | 386 | 
| webmaster@64 | 387 } | 
| webmaster@64 | 388 ?> |