annotate includes/akismet.class.php @ 64:d4f26e9767bf

Filtrage via Akismet du spam. Suite aux nombreuses attaques de spammers sur le blog, j'ai du chercher une solution efficace permettant d'y faire face. La solution la plus efficace que j'ai pour le moment, c'est Akismet, qui semble ne pas avoir trop de faux positifs (je n'en ai pas encore eu un seul). Il est necessaire de creer un compte sur WordPress.com pour obtenir une clef permettant d'utiliser le service, c'est totalement gratuit.
author Franck Deroche <webmaster@defr.org>
date Tue, 11 Mar 2008 08:16:11 -0700
parents
children efb93800fe10
rev   line source
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 ?>