source: extensions/rv_akismet/akismet.class.php @ 29055

Last change on this file since 29055 was 6506, checked in by rvelices, 14 years ago

added rv_akismet extension to svn

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
RevLine 
[6506]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
39define("AKISMET_SERVER_NOT_FOUND",  0);
40define("AKISMET_RESPONSE_FAILED", 1);
41define("AKISMET_INVALID_KEY",   2);
42
43
44
45// Base class to assist in error handling between Akismet classes
46class 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
116class 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.0\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!
189class 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?>
Note: See TracBrowser for help on using the repository browser.