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