├── Akismet.php
├── Exception.php
├── LICENSE.md
└── composer.json
/Akismet.php:
--------------------------------------------------------------------------------
1 |
8 | * @version 1.1.0
9 | * @copyright Copyright (c) Tijs Verkoyen. All rights reserved.
10 | * @license BSD License
11 | */
12 | class Akismet
13 | {
14 | // internal constant to enable/disable debugging
15 | const DEBUG = false;
16 |
17 | // url for the api
18 | const API_URL = 'http://rest.akismet.com';
19 |
20 | // port for the api
21 | const API_PORT = 80;
22 |
23 | // version of the api
24 | const API_VERSION = '1.1';
25 |
26 | // current version
27 | const VERSION = '1.1.0';
28 |
29 | /**
30 | * The key for the API
31 | * @var string
32 | */
33 | private $apiKey;
34 |
35 | /**
36 | * The timeout
37 | * @var int
38 | */
39 | private $timeOut = 60;
40 |
41 | /**
42 | * The user agent
43 | * @var string
44 | */
45 | private $userAgent;
46 |
47 | /**
48 | * The url
49 | * @var string
50 | */
51 | private $url;
52 |
53 | // class methods
54 | /**
55 | * Default constructor
56 | * Creates an instance of the Akismet Class.
57 | *
58 | * @param string $apiKey API key being verified for use with the API.
59 | * @param string $url The front page or home URL of the instance making
60 | * the request. For a blog or wiki this would be the
61 | * front page. Note: Must be a full URI, including
62 | * http://.
63 | */
64 | public function __construct($apiKey, $url)
65 | {
66 | $this->setApiKey($apiKey);
67 | $this->setUrl($url);
68 | }
69 |
70 | /**
71 | * Make the call
72 | * @param string $url URL to call.
73 | * @param array[optional] $aParameters The parameters to pass.
74 | * @param bool[optional] $authenticate Should we authenticate?
75 | * @return string
76 | */
77 | private function doCall($url, $aParameters = array(), $authenticate = true)
78 | {
79 | // redefine
80 | $url = (string) $url;
81 | $aParameters = (array) $aParameters;
82 | $authenticate = (bool) $authenticate;
83 |
84 | // build url
85 | $url = self::API_URL . '/' . self::API_VERSION . '/' . $url;
86 |
87 | // add key in front of url
88 | if ($authenticate) {
89 | // get api key
90 | $apiKey = $this->getApiKey();
91 |
92 | // validate apiKey
93 | if ($apiKey == '') throw new Exception('Invalid API-key');
94 |
95 | // prepend key
96 | $url = str_replace('http://', 'http://' . $apiKey . '.', $url);
97 | }
98 |
99 | // add url into the parameters
100 | $aParameters['blog'] = $this->getUrl();
101 |
102 | // set options
103 | $options[CURLOPT_URL] = $url;
104 | $options[CURLOPT_PORT] = self::API_PORT;
105 | $options[CURLOPT_USERAGENT] = $this->getUserAgent();
106 | if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {
107 | $options[CURLOPT_FOLLOWLOCATION] = true;
108 | }
109 | $options[CURLOPT_RETURNTRANSFER] = true;
110 | $options[CURLOPT_TIMEOUT] = (int) $this->getTimeOut();
111 | $options[CURLOPT_POST] = true;
112 | $options[CURLOPT_POSTFIELDS] = $aParameters;
113 |
114 | // speed up things, use HTTP 1.0
115 | $options[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
116 |
117 | // init
118 | $curl = curl_init();
119 |
120 | // set options
121 | curl_setopt_array($curl, $options);
122 |
123 | // execute
124 | $response = curl_exec($curl);
125 | $headers = curl_getinfo($curl);
126 |
127 | // fetch errors
128 | $errorNumber = curl_errno($curl);
129 | $errorMessage = curl_error($curl);
130 |
131 | // close
132 | curl_close($curl);
133 |
134 | // invalid headers
135 | if (!in_array($headers['http_code'], array(0, 200))) {
136 | // should we provide debug information
137 | if (self::DEBUG) {
138 | // make it output proper
139 | echo '
';
140 |
141 | // dump the header-information
142 | var_dump($headers);
143 |
144 | // dump the raw response
145 | var_dump($response);
146 |
147 | // end proper format
148 | echo '
';
149 |
150 | // stop the script
151 | exit();
152 | }
153 |
154 | // throw error
155 | throw new Exception(null, (int) $headers['http_code']);
156 | }
157 |
158 | // error?
159 | if ((int) $errorNumber > 0) {
160 | throw new Exception($errorMessage, $errorNumber);
161 | }
162 |
163 | // return
164 | return $response;
165 | }
166 |
167 | /**
168 | * Get the API-key that will be used
169 | *
170 | * @return string
171 | */
172 | private function getApiKey()
173 | {
174 | return (string) $this->apiKey;
175 | }
176 |
177 | /**
178 | * Get the timeout that will be used
179 | *
180 | * @return int
181 | */
182 | public function getTimeOut()
183 | {
184 | return (int) $this->timeOut;
185 | }
186 |
187 | /**
188 | * Get the url of the instance making the request
189 | *
190 | * @return string
191 | */
192 | public function getUrl()
193 | {
194 | return (string) $this->url;
195 | }
196 |
197 | /**
198 | * Get the useragent that will be used.
199 | * Our version will be prepended to yours. It will look like:
200 | * "PHP Akismet/ "
201 | *
202 | * @return string
203 | */
204 | public function getUserAgent()
205 | {
206 | return (string) 'PHP Akismet/' . self::VERSION . ' ' . $this->userAgent;
207 | }
208 |
209 | /**
210 | * Set API key that has to be used
211 | *
212 | * @param string $apiKey API key to use.
213 | */
214 | private function setApiKey($apiKey)
215 | {
216 | $this->apiKey = (string) $apiKey;
217 | }
218 |
219 | /**
220 | * Set the timeout
221 | * After this time the request will stop. You should handle any errors
222 | * triggered by this.
223 | *
224 | * @param int $seconds The timeout in seconds.
225 | */
226 | public function setTimeOut($seconds)
227 | {
228 | $this->timeOut = (int) $seconds;
229 | }
230 |
231 | /**
232 | * Set the url of the instance making the request
233 | * @param string $url The URL making the request.
234 | */
235 | private function setUrl($url)
236 | {
237 | $this->url = (string) $url;
238 | }
239 |
240 | /**
241 | * Set the user-agent for you application
242 | * It will be appended to ours, the result will look like:
243 | * "PHP Akismet/ "
244 | *
245 | * @param string $userAgent The user-agent, it should look like:
246 | * /.
247 | */
248 | public function setUserAgent($userAgent)
249 | {
250 | $this->userAgent = (string) $userAgent;
251 | }
252 |
253 | // api methods
254 | /**
255 | * Verifies the key
256 | * @return bool if the key is valid it will return true, otherwise false
257 | * will be returned.
258 | */
259 | public function verifyKey()
260 | {
261 | // possible answers
262 | $aPossibleResponses = array('valid', 'invalid');
263 |
264 | // build parameters
265 | $aParameters['key'] = $this->getApiKey();
266 |
267 | // make the call
268 | $response = $this->doCall('verify-key', $aParameters, false);
269 |
270 | // validate response
271 | if (!in_array($response, $aPossibleResponses)) {
272 | throw new Exception($response, 400);
273 | }
274 |
275 | // valid key
276 | if ($response == 'valid') return true;
277 |
278 | // fallback
279 | return false;
280 | }
281 |
282 | /**
283 | * Check if the comment is spam or not
284 | * This is basically the core of everything. This call takes a number of
285 | * arguments and characteristics about the submitted content and then
286 | * returns a thumbs up or thumbs down.
287 | * Almost everything is optional, but performance can drop dramatically if
288 | * you exclude certain elements.
289 | * REMARK: If you are having trouble triggering you can send
290 | * "viagra-test-123" as the author and it will trigger a true response,
291 | * always.
292 | *
293 | * @param string[optional] $content The content that was submitted.
294 | * @param string[optional] $author The name.
295 | * @param string[optional] $email The email address.
296 | * @param string[optional] $url The URL.
297 | * @param string[optional] $permalink The permanent location of the entry
298 | * the comment was submitted to.
299 | * @param string[optional] $type The type, can be blank, comment,
300 | * trackback, pingback, or a made up
301 | * value like "registration".
302 | * @return bool If the comment is spam true will be
303 | * returned, otherwise false.
304 | */
305 | public function isSpam(
306 | $content,
307 | $author = null,
308 | $email = null,
309 | $url = null,
310 | $permalink = null,
311 | $type = null
312 | )
313 | {
314 | // possible answers
315 | $aPossibleResponses = array('true', 'false');
316 |
317 | // redefine
318 | $content = (string) $content;
319 | $author = (string) $author;
320 | $email = (string) $email;
321 | $url = (string) $url;
322 | $permalink = (string) $permalink;
323 | $type = (string) $type;
324 |
325 | // get stuff from the $_SERVER-array
326 | if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
327 | $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
328 | } elseif (isset($_SERVER['REMOTE_ADDR'])) {
329 | $ip = $_SERVER['REMOTE_ADDR'];
330 | } else $ip = '';
331 | if (isset($_SERVER['HTTP_USER_AGENT'])) {
332 | $userAgent = (string) $_SERVER['HTTP_USER_AGENT'];
333 | } else $userAgent = '';
334 | if (isset($_SERVER['HTTP_REFERER'])) {
335 | $referrer = (string) $_SERVER['HTTP_REFERER'];
336 | } else $referrer = '';
337 |
338 | // build parameters
339 | $aParameters['user_ip'] = $ip;
340 | $aParameters['user_agent'] = $userAgent;
341 | if ($referrer != '') $aParameters['referrer'] = $referrer;
342 | if ($permalink != '') $aParameters['permalink'] = $permalink;
343 | if ($type != '') $aParameters['comment_type'] = $type;
344 | if ($author != '') $aParameters['comment_author'] = $author;
345 | if ($email != '') $aParameters['comment_author_email'] = $email;
346 | if ($url != '') $aParameters['comment_author_url'] = $url;
347 | $aParameters['comment_content'] = $content;
348 |
349 | // add all stuff from $_SERVER
350 | foreach ($_SERVER as $key => $value) {
351 | // keys to ignore
352 | $aKeysToIgnore = array(
353 | 'HTTP_COOKIE', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_HOST',
354 | 'HTTP_MAX_FORWARDS', 'HTTP_X_FORWARDED_SERVER',
355 | 'REDIRECT_STATUS', 'SERVER_PORT', 'PATH', 'DOCUMENT_ROOT',
356 | 'SERVER_ADMIN', 'QUERY_STRING', 'PHP_SELF', 'argv', 'argc',
357 | 'SCRIPT_FILENAME', 'SCRIPT_NAME'
358 | );
359 |
360 | // add to parameters if not in ignore list
361 | if (!in_array($key, $aKeysToIgnore)) $aParameters[$key] = $value;
362 | }
363 |
364 | // make the call
365 | $response = $this->doCall('comment-check', $aParameters);
366 |
367 | // validate response
368 | if (!in_array($response, $aPossibleResponses)) {
369 | throw new Exception($response, 400);
370 | }
371 |
372 | // process response
373 | if ($response == 'true') return true;
374 |
375 | // fallback
376 | return false;
377 | }
378 |
379 | /**
380 | * Submit ham to Akismet
381 | * This call is intended for the marking of false positives, things that
382 | * were incorrectly marked as spam.
383 | * @param string $userIp The address of the comment submitter.
384 | * @param string $userAgent The agent information.
385 | * @param string[optional] $content The content that was submitted.
386 | * @param string[optional] $author The name of the author.
387 | * @param string[optional] $email The email address.
388 | * @param string[optional] $url The URL.
389 | * @param string[optional] $permalink The permanent location of the entry
390 | * the comment was submitted to.
391 | * @param string[optional] $type The type, can be blank, comment,
392 | * trackback, pingback, or a made up
393 | * value like "registration".
394 | * @param string[optional] $referrer The content of the HTTP_REFERER
395 | * header should be sent here.
396 | * @param array[optional] $others Extra data (the variables from
397 | * $_SERVER).
398 | * @return bool If everything went fine true will be
399 | * returned, otherwise an exception
400 | * will be triggered.
401 | */
402 | public function submitHam(
403 | $userIp,
404 | $userAgent,
405 | $content,
406 | $author = null,
407 | $email = null,
408 | $url = null,
409 | $permalink = null,
410 | $type = null,
411 | $referrer = null,
412 | $others = null
413 | )
414 | {
415 | // possible answers
416 | $aPossibleResponses = array('Thanks for making the web a better place.');
417 |
418 | // redefine
419 | $userIp = (string) $userIp;
420 | $userAgent = (string) $userAgent;
421 | $content = (string) $content;
422 | $author = (string) $author;
423 | $email = (string) $email;
424 | $url = (string) $url;
425 | $permalink = (string) $permalink;
426 | $type = (string) $type;
427 | $referrer = (string) $referrer;
428 | $others = (array) $others;
429 |
430 | // build parameters
431 | $aParameters['user_ip'] = $userIp;
432 | $aParameters['user_agent'] = $userAgent;
433 | if ($referrer != '') $aParameters['referrer'] = $referrer;
434 | if ($permalink != '') $aParameters['permalink'] = $permalink;
435 | if ($type != '') $aParameters['comment_type'] = $type;
436 | if ($author != '') $aParameters['comment_author'] = $author;
437 | if ($email != '') $aParameters['comment_author_email'] = $email;
438 | if ($url != '') $aParameters['comment_author_url'] = $url;
439 | $aParameters['comment_content'] = $content;
440 |
441 | // add other parameters
442 | foreach ($others as $key => $value) $aParameters[$key] = $value;
443 |
444 | // make the call
445 | $response = $this->doCall('submit-ham', $aParameters);
446 |
447 | // validate response
448 | if (in_array($response, $aPossibleResponses)) return true;
449 |
450 | // fallback
451 | throw new Exception($response);
452 | }
453 |
454 | /**
455 | * Submit spam to Akismet
456 | * This call is for submitting comments that weren't marked as spam but
457 | * should have been.
458 | * @param string $userIp The address of the comment submitter.
459 | * @param string $userAgent The agent information.
460 | * @param string[optional] $content The content that was submitted.
461 | * @param string[optional] $author The name of the author.
462 | * @param string[optional] $email The email address.
463 | * @param string[optional] $url The URL.
464 | * @param string[optional] $permalink The permanent location of the entry
465 | * the comment was submitted to.
466 | * @param string[optional] $type The type, can be blank, comment,
467 | * trackback, pingback, or a made up
468 | * value like "registration".
469 | * @param string[optional] $referrer The content of the HTTP_REFERER
470 | * header should be sent here.
471 | * @param array[optional] $others Extra data (the variables from
472 | * $_SERVER).
473 | * @return bool If everything went fine true will be
474 | * returned, otherwise an exception
475 | * will be triggered.
476 | */
477 | public function submitSpam(
478 | $userIp,
479 | $userAgent,
480 | $content,
481 | $author = null,
482 | $email = null,
483 | $url = null,
484 | $permalink = null,
485 | $type = null,
486 | $referrer = null,
487 | $others = null
488 | )
489 | {
490 | // possible answers
491 | $aPossibleResponses = array('Thanks for making the web a better place.');
492 |
493 | // redefine
494 | $userIp = (string) $userIp;
495 | $userAgent = (string) $userAgent;
496 | $content = (string) $content;
497 | $author = (string) $author;
498 | $email = (string) $email;
499 | $url = (string) $url;
500 | $permalink = (string) $permalink;
501 | $type = (string) $type;
502 | $referrer = (string) $referrer;
503 | $others = (array) $others;
504 |
505 | // build parameters
506 | $aParameters['user_ip'] = $userIp;
507 | $aParameters['user_agent'] = $userAgent;
508 | if ($referrer != '') $aParameters['referrer'] = $referrer;
509 | if ($permalink != '') $aParameters['permalink'] = $permalink;
510 | if ($type != '') $aParameters['comment_type'] = $type;
511 | if ($author != '') $aParameters['comment_author'] = $author;
512 | if ($email != '') $aParameters['comment_author_email'] = $email;
513 | if ($url != '') $aParameters['comment_author_url'] = $url;
514 | $aParameters['comment_content'] = $content;
515 |
516 | // add other parameters
517 | foreach ($others as $key => $value) $aParameters[$key] = $value;
518 |
519 | // make the call
520 | $response = $this->doCall('submit-spam', $aParameters);
521 |
522 | // validate response
523 | if (in_array($response, $aPossibleResponses)) return true;
524 |
525 | // fallback
526 | throw new Exception($response);
527 | }
528 | }
529 |
--------------------------------------------------------------------------------
/Exception.php:
--------------------------------------------------------------------------------
1 |
8 | */
9 | class Exception extends \Exception
10 | {
11 | /**
12 | * Http header-codes
13 | *
14 | * @var array
15 | */
16 | private $aStatusCodes = array(
17 | 100 => 'Continue',
18 | 101 => 'Switching Protocols',
19 | 200 => 'OK',
20 | 201 => 'Created',
21 | 202 => 'Accepted',
22 | 203 => 'Non-Authoritative Information',
23 | 204 => 'No Content',
24 | 205 => 'Reset Content',
25 | 206 => 'Partial Content',
26 | 300 => 'Multiple Choices',
27 | 301 => 'Moved Permanently',
28 | 301 => 'Status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.',
29 | 302 => 'Found',
30 | 302 => 'Status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.',
31 | 303 => 'See Other',
32 | 304 => 'Not Modified',
33 | 305 => 'Use Proxy',
34 | 306 => '(Unused)',
35 | 307 => 'Temporary Redirect',
36 | 400 => 'Bad Request',
37 | 401 => 'Unauthorized',
38 | 402 => 'Payment Required',
39 | 403 => 'Forbidden',
40 | 404 => 'Not Found',
41 | 405 => 'Method Not Allowed',
42 | 406 => 'Not Acceptable',
43 | 407 => 'Proxy Authentication Required',
44 | 408 => 'Request Timeout',
45 | 409 => 'Conflict',
46 | 411 => 'Length Required',
47 | 412 => 'Precondition Failed',
48 | 413 => 'Request Entity Too Large',
49 | 414 => 'Request-URI Too Long',
50 | 415 => 'Unsupported Media Type',
51 | 416 => 'Requested Range Not Satisfiable',
52 | 417 => 'Expectation Failed',
53 | 500 => 'Internal Server Error',
54 | 501 => 'Not Implemented',
55 | 502 => 'Bad Gateway',
56 | 503 => 'Service Unavailable',
57 | 504 => 'Gateway Timeout',
58 | 505 => 'HTTP Version Not Supported'
59 | );
60 |
61 | /**
62 | * Default constructor
63 | *
64 | * @param $message string[optional] message.
65 | * @param $code int[optional] error number.
66 | */
67 | public function __construct($message = null, $code = null)
68 | {
69 | // set message
70 | if ($message === null && isset($this->aStatusCodes[(int) $code])) {
71 | $message = $this->aStatusCodes[(int) $code];
72 | }
73 |
74 | // call parent
75 | parent::__construct((string) $message, $code);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) Tijs Verkoyen. All rights reserved.
2 | Redistribution and use in source and binary forms, with or without
3 | modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this
6 | list of conditions and the following disclaimer.
7 | 2. Redistributions in binary form must reproduce the above copyright notice,
8 | this list of conditions and the following disclaimer in the documentation
9 | and/or other materials provided with the distribution.
10 | 3. The name of the author may not be used to endorse or promote products
11 | derived from this software without specific prior written permission.
12 |
13 | This software is provided by the author "as is" and any express or implied
14 | warranties, including, but not limited to, the implied warranties of
15 | merchantability and fitness for a particular purpose are disclaimed. In no event
16 | shall the author be liable for any direct, indirect, incidental, special,
17 | exemplary, or consequential damages (including, but not limited to, procurement
18 | of substitute goods or services; loss of use, data, or profits; or business
19 | interruption) however caused and on any theory of liability, whether in
20 | contract, strict liability, or tort (including negligence or otherwise) arising
21 | in any way out of the use of this software, even if advised of the possibility
22 | of such damage.
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tijsverkoyen/akismet",
3 | "type": "library",
4 | "description": "Akismet is a wrapper-class to communicate with the Akismet API.",
5 | "homepage": "https://github.com/tijsverkoyen/Akismet",
6 | "license": "BSD",
7 | "authors": [
8 | {
9 | "name": "Tijs Verkoyen",
10 | "email": "akismet@verkoyen.eu",
11 | "role": "Developer"
12 | }
13 | ],
14 | "require": {
15 | "php": ">=5.2.0",
16 | "ext-curl": "*"
17 | },
18 | "autoload": {
19 | "classmap": [""]
20 | }
21 | }
--------------------------------------------------------------------------------