Index: trunk/extensions/AkismetKlik/Akismet.class.php |
— | — | @@ -0,0 +1,474 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Akismet anti-comment spam service |
| 6 | + * |
| 7 | + * The class in this package allows use of the {@link http://akismet.com Akismet} anti-comment spam service in any PHP5 application. |
| 8 | + * |
| 9 | + * This service performs a number of checks on submitted data and returns whether or not the data is likely to be spam. |
| 10 | + * |
| 11 | + * Please note that in order to use this class, you must have a vaild {@link http://wordpress.com/api-keys/ WordPress API key}. They are free for non/small-profit types and getting one will only take a couple of minutes. |
| 12 | + * |
| 13 | + * For commercial use, please {@link http://akismet.com/commercial/ visit the Akismet commercial licensing page}. |
| 14 | + * |
| 15 | + * Please be aware that this class is PHP5 only. Attempts to run it under PHP4 will most likely fail. |
| 16 | + * |
| 17 | + * See the Akismet class documentation page linked to below for usage information. |
| 18 | + * |
| 19 | + * @package akismet |
| 20 | + * @author Alex Potsides, {@link http://www.achingbrain.net http://www.achingbrain.net} |
| 21 | + * @version 0.5 |
| 22 | + * @copyright Alex Potsides, {@link http://www.achingbrain.net http://www.achingbrain.net} |
| 23 | + * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
| 24 | + */ |
| 25 | + |
| 26 | +/** |
| 27 | + * The Akismet PHP5 Class |
| 28 | + * |
| 29 | + * This class takes the functionality from the Akismet WordPress plugin written by {@link http://photomatt.net/ Matt Mullenweg} and allows it to be integrated into any PHP5 application or website. |
| 30 | + * |
| 31 | + * The original plugin is {@link http://akismet.com/download/ available on the Akismet website}. |
| 32 | + * |
| 33 | + * <code> |
| 34 | + * $akismet = new Akismet('http://www.example.com/blog/', 'aoeu1aoue'); |
| 35 | + * $akismet->setCommentAuthor($name); |
| 36 | + * $akismet->setCommentAuthorEmail($email); |
| 37 | + * $akismet->setCommentAuthorURL($url); |
| 38 | + * $akismet->setCommentContent($comment); |
| 39 | + * $akismet->setPermalink('http://www.example.com/blog/alex/someurl/'); |
| 40 | + * |
| 41 | + * if($akismet->isCommentSpam()) |
| 42 | + * // store the comment but mark it as spam (in case of a mis-diagnosis) |
| 43 | + * else |
| 44 | + * // store the comment normally |
| 45 | + * </code> |
| 46 | + * |
| 47 | + * Optionally you may wish to check if your WordPress API key is valid as in the example below. |
| 48 | + * |
| 49 | + * <code> |
| 50 | + * $akismet = new Akismet('http://www.example.com/blog/', 'aoeu1aoue'); |
| 51 | + * |
| 52 | + * if($akismet->isKeyValid()) { |
| 53 | + * // api key is okay |
| 54 | + * } else { |
| 55 | + * // api key is invalid |
| 56 | + * } |
| 57 | + * </code> |
| 58 | + * |
| 59 | + * @package akismet |
| 60 | + * @name Akismet |
| 61 | + * @version 0.5 |
| 62 | + * @author Alex Potsides |
| 63 | + * @link http://www.achingbrain.net/ |
| 64 | + */ |
| 65 | +class Akismet { |
| 66 | + private $version = '0.5'; |
| 67 | + private $wordPressAPIKey; |
| 68 | + private $blogURL; |
| 69 | + private $comment; |
| 70 | + private $apiPort; |
| 71 | + private $akismetServer; |
| 72 | + private $akismetVersion; |
| 73 | + private $requestFactory; |
| 74 | + |
| 75 | + // This prevents some potentially sensitive information from being sent accross the wire. |
| 76 | + private $ignore = array('HTTP_COOKIE', |
| 77 | + 'HTTP_X_FORWARDED_FOR', |
| 78 | + 'HTTP_X_FORWARDED_HOST', |
| 79 | + 'HTTP_MAX_FORWARDS', |
| 80 | + 'HTTP_X_FORWARDED_SERVER', |
| 81 | + 'REDIRECT_STATUS', |
| 82 | + 'SERVER_PORT', |
| 83 | + 'PATH', |
| 84 | + 'DOCUMENT_ROOT', |
| 85 | + 'SERVER_ADMIN', |
| 86 | + 'QUERY_STRING', |
| 87 | + 'PHP_SELF' ); |
| 88 | + |
| 89 | + /** |
| 90 | + * @param string $blogURL The URL of your blog. |
| 91 | + * @param string $wordPressAPIKey WordPress API key. |
| 92 | + */ |
| 93 | + public function __construct($blogURL, $wordPressAPIKey) { |
| 94 | + $this->blogURL = $blogURL; |
| 95 | + $this->wordPressAPIKey = $wordPressAPIKey; |
| 96 | + |
| 97 | + // Set some default values |
| 98 | + $this->apiPort = 80; |
| 99 | + $this->akismetServer = 'rest.akismet.com'; |
| 100 | + $this->akismetVersion = '1.1'; |
| 101 | + $this->requestFactory = new SocketWriteReadFactory(); |
| 102 | + |
| 103 | + // Start to populate the comment data |
| 104 | + $this->comment['blog'] = $blogURL; |
| 105 | + |
| 106 | + if(isset($_SERVER['HTTP_USER_AGENT'])) { |
| 107 | + $this->comment['user_agent'] = $_SERVER['HTTP_USER_AGENT']; |
| 108 | + } |
| 109 | + |
| 110 | + if(isset($_SERVER['HTTP_REFERER'])) { |
| 111 | + $this->comment['referrer'] = $_SERVER['HTTP_REFERER']; |
| 112 | + } |
| 113 | + |
| 114 | + /* |
| 115 | + * This is necessary if the server PHP5 is running on has been set up to run PHP4 and |
| 116 | + * PHP5 concurently and is actually running through a separate proxy al a these instructions: |
| 117 | + * http://www.schlitt.info/applications/blog/archives/83_How_to_run_PHP4_and_PHP_5_parallel.html |
| 118 | + * and http://wiki.coggeshall.org/37.html |
| 119 | + * Otherwise the user_ip appears as the IP address of the PHP4 server passing the requests to the |
| 120 | + * PHP5 one... |
| 121 | + */ |
| 122 | + if(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR')) { |
| 123 | + $this->comment['user_ip'] = $_SERVER['REMOTE_ADDR']; |
| 124 | + } else { |
| 125 | + $this->comment['user_ip'] = getenv('HTTP_X_FORWARDED_FOR'); |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + /** |
| 130 | + * Makes a request to the Akismet service to see if the API key passed to the constructor is valid. |
| 131 | + * |
| 132 | + * Use this method if you suspect your API key is invalid. |
| 133 | + * |
| 134 | + * @return bool True is if the key is valid, false if not. |
| 135 | + */ |
| 136 | + public function isKeyValid() { |
| 137 | + // Check to see if the key is valid |
| 138 | + $response = $this->sendRequest('key=' . $this->wordPressAPIKey . '&blog=' . $this->blogURL, $this->akismetServer, '/' . $this->akismetVersion . '/verify-key'); |
| 139 | + return $response[1] == 'valid'; |
| 140 | + } |
| 141 | + |
| 142 | + // makes a request to the Akismet service |
| 143 | + private function sendRequest($request, $host, $path) { |
| 144 | + $http_request = "POST " . $path . " HTTP/1.0\r\n"; |
| 145 | + $http_request .= "Host: " . $host . "\r\n"; |
| 146 | + $http_request .= "Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n"; |
| 147 | + $http_request .= "Content-Length: " . strlen($request) . "\r\n"; |
| 148 | + $http_request .= "User-Agent: Akismet PHP5 Class " . $this->version . " | Akismet/1.11\r\n"; |
| 149 | + $http_request .= "\r\n"; |
| 150 | + $http_request .= $request; |
| 151 | + |
| 152 | + $requestSender = $this->requestFactory->createRequestSender(); |
| 153 | + $response = $requestSender->send($host, $this->apiPort, $http_request); |
| 154 | + |
| 155 | + return explode("\r\n\r\n", $response, 2); |
| 156 | + } |
| 157 | + |
| 158 | + // Formats the data for transmission |
| 159 | + private function getQueryString() { |
| 160 | + foreach($_SERVER as $key => $value) { |
| 161 | + if(!in_array($key, $this->ignore)) { |
| 162 | + if($key == 'REMOTE_ADDR') { |
| 163 | + $this->comment[$key] = $this->comment['user_ip']; |
| 164 | + } else { |
| 165 | + $this->comment[$key] = $value; |
| 166 | + } |
| 167 | + } |
| 168 | + } |
| 169 | + |
| 170 | + $query_string = ''; |
| 171 | + |
| 172 | + foreach($this->comment as $key => $data) { |
| 173 | + if(!is_array($data)) { |
| 174 | + $query_string .= $key . '=' . urlencode(stripslashes($data)) . '&'; |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + return $query_string; |
| 179 | + } |
| 180 | + |
| 181 | + /** |
| 182 | + * Tests for spam. |
| 183 | + * |
| 184 | + * Uses the web service provided by {@link http://www.akismet.com Akismet} to see whether or not the submitted comment is spam. Returns a boolean value. |
| 185 | + * |
| 186 | + * @return bool True if the comment is spam, false if not |
| 187 | + * @throws Will throw an exception if the API key passed to the constructor is invalid. |
| 188 | + */ |
| 189 | + public function isCommentSpam() { |
| 190 | + $response = $this->sendRequest($this->getQueryString(), $this->wordPressAPIKey . '.rest.akismet.com', '/' . $this->akismetVersion . '/comment-check'); |
| 191 | + |
| 192 | + if($response[1] == 'invalid' && !$this->isKeyValid()) { |
| 193 | + throw new exception('The Wordpress API key passed to the Akismet constructor is invalid. Please obtain a valid one from http://wordpress.com/api-keys/'); |
| 194 | + } |
| 195 | + |
| 196 | + return ($response[1] == 'true'); |
| 197 | + } |
| 198 | + |
| 199 | + /** |
| 200 | + * Submit spam that is incorrectly tagged as ham. |
| 201 | + * |
| 202 | + * Using this function will make you a good citizen as it helps Akismet to learn from its mistakes. This will improve the service for everybody. |
| 203 | + */ |
| 204 | + public function submitSpam() { |
| 205 | + $this->sendRequest($this->getQueryString(), $this->wordPressAPIKey . '.' . $this->akismetServer, '/' . $this->akismetVersion . '/submit-spam'); |
| 206 | + } |
| 207 | + |
| 208 | + /** |
| 209 | + * Submit ham that is incorrectly tagged as spam. |
| 210 | + * |
| 211 | + * Using this function will make you a good citizen as it helps Akismet to learn from its mistakes. This will improve the service for everybody. |
| 212 | + */ |
| 213 | + public function submitHam() { |
| 214 | + $this->sendRequest($this->getQueryString(), $this->wordPressAPIKey . '.' . $this->akismetServer, '/' . $this->akismetVersion . '/submit-ham'); |
| 215 | + } |
| 216 | + |
| 217 | + /** |
| 218 | + * To override the user IP address when submitting spam/ham later on |
| 219 | + * |
| 220 | + * @param string $userip An IP address. Optional. |
| 221 | + */ |
| 222 | + public function setUserIP($userip) { |
| 223 | + $this->comment['user_ip'] = $userip; |
| 224 | + } |
| 225 | + |
| 226 | + /** |
| 227 | + * To override the referring page when submitting spam/ham later on |
| 228 | + * |
| 229 | + * @param string $referrer The referring page. Optional. |
| 230 | + */ |
| 231 | + public function setReferrer($referrer) { |
| 232 | + $this->comment['referrer'] = $referrer; |
| 233 | + } |
| 234 | + |
| 235 | + /** |
| 236 | + * A permanent URL referencing the blog post the comment was submitted to. |
| 237 | + * |
| 238 | + * @param string $permalink The URL. Optional. |
| 239 | + */ |
| 240 | + public function setPermalink($permalink) { |
| 241 | + $this->comment['permalink'] = $permalink; |
| 242 | + } |
| 243 | + |
| 244 | + /** |
| 245 | + * The type of comment being submitted. |
| 246 | + * |
| 247 | + * May be blank, comment, trackback, pingback, or a made up value like "registration" or "wiki". |
| 248 | + */ |
| 249 | + public function setCommentType($commentType) { |
| 250 | + $this->comment['comment_type'] = $commentType; |
| 251 | + } |
| 252 | + |
| 253 | + /** |
| 254 | + * The name that the author submitted with the comment. |
| 255 | + */ |
| 256 | + public function setCommentAuthor($commentAuthor) { |
| 257 | + $this->comment['comment_author'] = $commentAuthor; |
| 258 | + } |
| 259 | + |
| 260 | + /** |
| 261 | + * The email address that the author submitted with the comment. |
| 262 | + * |
| 263 | + * The address is assumed to be valid. |
| 264 | + */ |
| 265 | + public function setCommentAuthorEmail($authorEmail) { |
| 266 | + $this->comment['comment_author_email'] = $authorEmail; |
| 267 | + } |
| 268 | + |
| 269 | + /** |
| 270 | + * The URL that the author submitted with the comment. |
| 271 | + */ |
| 272 | + public function setCommentAuthorURL($authorURL) { |
| 273 | + $this->comment['comment_author_url'] = $authorURL; |
| 274 | + } |
| 275 | + |
| 276 | + /** |
| 277 | + * The comment's body text. |
| 278 | + */ |
| 279 | + public function setCommentContent($commentBody) { |
| 280 | + $this->comment['comment_content'] = $commentBody; |
| 281 | + } |
| 282 | + |
| 283 | + /** |
| 284 | + * Lets you override the user agent used to submit the comment. |
| 285 | + * you may wish to do this when submitting ham/spam. |
| 286 | + * Defaults to $_SERVER['HTTP_USER_AGENT'] |
| 287 | + */ |
| 288 | + public function setCommentUserAgent($userAgent) { |
| 289 | + $this->comment['user_agent'] = $userAgent; |
| 290 | + } |
| 291 | + |
| 292 | + /** |
| 293 | + * Defaults to 80 |
| 294 | + */ |
| 295 | + public function setAPIPort($apiPort) { |
| 296 | + $this->apiPort = $apiPort; |
| 297 | + } |
| 298 | + |
| 299 | + /** |
| 300 | + * Defaults to rest.akismet.com |
| 301 | + */ |
| 302 | + public function setAkismetServer($akismetServer) { |
| 303 | + $this->akismetServer = $akismetServer; |
| 304 | + } |
| 305 | + |
| 306 | + /** |
| 307 | + * Defaults to '1.1' |
| 308 | + * |
| 309 | + * @param string $akismetVersion |
| 310 | + */ |
| 311 | + public function setAkismetVersion($akismetVersion) { |
| 312 | + $this->akismetVersion = $akismetVersion; |
| 313 | + } |
| 314 | + |
| 315 | + /** |
| 316 | + * Used by unit tests to mock transport layer |
| 317 | + * |
| 318 | + * @param AkismetRequestFactory $requestFactory |
| 319 | + */ |
| 320 | + public function setRequestFactory($requestFactory) { |
| 321 | + $this->requestFactory = $requestFactory; |
| 322 | + } |
| 323 | +} |
| 324 | + |
| 325 | +/** |
| 326 | + * Used internally by Akismet |
| 327 | + * |
| 328 | + * This class is used by Akismet to do the actual sending and receiving of data. It opens a connection to a remote host, sends some data and the reads the response and makes it available to the calling program. |
| 329 | + * |
| 330 | + * The code that makes up this class originates in the Akismet WordPress plugin, which is {@link http://akismet.com/download/ available on the Akismet website}. |
| 331 | + * |
| 332 | + * N.B. It is not necessary to call this class directly to use the Akismet class. |
| 333 | + * |
| 334 | + * @package akismet |
| 335 | + * @name SocketWriteRead |
| 336 | + * @version 0.5 |
| 337 | + * @author Alex Potsides |
| 338 | + * @link http://www.achingbrain.net/ |
| 339 | + */ |
| 340 | +class SocketWriteRead implements AkismetRequestSender { |
| 341 | + private $response; |
| 342 | + private $errorNumber; |
| 343 | + private $errorString; |
| 344 | + |
| 345 | + public function __construct() { |
| 346 | + $this->errorNumber = 0; |
| 347 | + $this->errorString = ''; |
| 348 | + } |
| 349 | + |
| 350 | + /** |
| 351 | + * Sends the data to the remote host. |
| 352 | + * |
| 353 | + * @param string $host The host to send/receive data. |
| 354 | + * @param int $port The port on the remote host. |
| 355 | + * @param string $request The data to send. |
| 356 | + * @param int $responseLength The amount of data to read. Defaults to 1160 bytes. |
| 357 | + * @throws An exception is thrown if a connection cannot be made to the remote host. |
| 358 | + * @returns The server response |
| 359 | + */ |
| 360 | + public function send($host, $port, $request, $responseLength = 1160) { |
| 361 | + $response = ''; |
| 362 | + |
| 363 | + $fs = fsockopen($host, $port, $this->errorNumber, $this->errorString, 3); |
| 364 | + |
| 365 | + if($this->errorNumber != 0) { |
| 366 | + throw new Exception('Error connecting to host: ' . $host . ' Error number: ' . $this->errorNumber . ' Error message: ' . $this->errorString); |
| 367 | + } |
| 368 | + |
| 369 | + if($fs !== false) { |
| 370 | + @fwrite($fs, $request); |
| 371 | + |
| 372 | + while(!feof($fs)) { |
| 373 | + $response .= fgets($fs, $responseLength); |
| 374 | + } |
| 375 | + |
| 376 | + fclose($fs); |
| 377 | + } |
| 378 | + |
| 379 | + return $response; |
| 380 | + } |
| 381 | + |
| 382 | + /** |
| 383 | + * Returns the server response text |
| 384 | + * |
| 385 | + * @return string |
| 386 | + */ |
| 387 | + public function getResponse() { |
| 388 | + return $this->response; |
| 389 | + } |
| 390 | + |
| 391 | + /** |
| 392 | + * Returns the error number |
| 393 | + * |
| 394 | + * If there was no error, 0 will be returned. |
| 395 | + * |
| 396 | + * @return int |
| 397 | + */ |
| 398 | + public function getErrorNumner() { |
| 399 | + return $this->errorNumber; |
| 400 | + } |
| 401 | + |
| 402 | + /** |
| 403 | + * Returns the error string |
| 404 | + * |
| 405 | + * If there was no error, an empty string will be returned. |
| 406 | + * |
| 407 | + * @return string |
| 408 | + */ |
| 409 | + public function getErrorString() { |
| 410 | + return $this->errorString; |
| 411 | + } |
| 412 | +} |
| 413 | + |
| 414 | +/** |
| 415 | + * Used internally by the Akismet class and to mock the Akismet anti spam service in |
| 416 | + * the unit tests. |
| 417 | + * |
| 418 | + * N.B. It is not necessary to call this class directly to use the Akismet class. |
| 419 | + * |
| 420 | + * @package akismet |
| 421 | + * @name SocketWriteReadFactory |
| 422 | + * @version 0.5 |
| 423 | + * @author Alex Potsides |
| 424 | + * @link http://www.achingbrain.net/ |
| 425 | + */ |
| 426 | +class SocketWriteReadFactory implements AkismetRequestFactory { |
| 427 | + |
| 428 | + public function createRequestSender() { |
| 429 | + return new SocketWriteRead(); |
| 430 | + } |
| 431 | +} |
| 432 | + |
| 433 | +/** |
| 434 | + * Used internally by the Akismet class and to mock the Akismet anti spam service in |
| 435 | + * the unit tests. |
| 436 | + * |
| 437 | + * N.B. It is not necessary to implement this class to use the Akismet class. |
| 438 | + * |
| 439 | + * @package akismet |
| 440 | + * @name AkismetRequestSender |
| 441 | + * @version 0.5 |
| 442 | + * @author Alex Potsides |
| 443 | + * @link http://www.achingbrain.net/ |
| 444 | + */ |
| 445 | +interface AkismetRequestSender { |
| 446 | + |
| 447 | + /** |
| 448 | + * Sends the data to the remote host. |
| 449 | + * |
| 450 | + * @param string $host The host to send/receive data. |
| 451 | + * @param int $port The port on the remote host. |
| 452 | + * @param string $request The data to send. |
| 453 | + * @param int $responseLength The amount of data to read. Defaults to 1160 bytes. |
| 454 | + * @throws An exception is thrown if a connection cannot be made to the remote host. |
| 455 | + * @returns The server response |
| 456 | + */ |
| 457 | + public function send($host, $port, $request, $responseLength = 1160); |
| 458 | +} |
| 459 | + |
| 460 | +/** |
| 461 | + * Used internally by the Akismet class and to mock the Akismet anti spam service in |
| 462 | + * the unit tests. |
| 463 | + * |
| 464 | + * N.B. It is not necessary to implement this class to use the Akismet class. |
| 465 | + * |
| 466 | + * @package akismet |
| 467 | + * @name AkismetRequestFactory |
| 468 | + * @version 0.5 |
| 469 | + * @author Alex Potsides |
| 470 | + * @link http://www.achingbrain.net/ |
| 471 | + */ |
| 472 | +interface AkismetRequestFactory { |
| 473 | + |
| 474 | + public function createRequestSender(); |
| 475 | +} |
Property changes on: trunk/extensions/AkismetKlik/Akismet.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 476 | + native |
Index: trunk/extensions/AkismetKlik/AkismetKlik.php |
— | — | @@ -0,0 +1,151 @@ |
| 2 | +<?php |
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 4 | + exit; |
| 5 | +} |
| 6 | + |
| 7 | +# |
| 8 | +# Include PHP5 Akismet class from http://www.achingbrain.net/stuff/akismet (GPL) |
| 9 | +# |
| 10 | +require_once('Akismet.class.php'); |
| 11 | + |
| 12 | +#Extension credits |
| 13 | +$wgExtensionCredits['other'][] = array( |
| 14 | + 'name' => 'AkismetKlik', |
| 15 | + 'author' => 'Carl Austin Bennett', |
| 16 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:AkismetKlik', |
| 17 | + 'description' => 'Rejects edits from suspected comment spammers on Akismet\'s blacklist.', |
| 18 | +); |
| 19 | + |
| 20 | +# Set site-specific configuration values |
| 21 | +#$wgAKkey='867-5309'; |
| 22 | +#$siteURL='http://wiki.example.org'; |
| 23 | + |
| 24 | +# |
| 25 | +# MediaWiki hooks |
| 26 | +# |
| 27 | +# Loader for spam blacklist feature |
| 28 | +# Include this from LocalSettings.php |
| 29 | + |
| 30 | +global $wgAkismetFilterCallback, $wgPreAkismetFilterCallback, $wgUser; |
| 31 | +$wgPreAkismetFilterCallback = false; |
| 32 | + |
| 33 | +if ( defined( 'MW_SUPPORTS_EDITFILTERMERGED' ) ) { |
| 34 | + $wgHooks['EditFilterMerged'][] = 'wfAkismetFilterMerged'; |
| 35 | +} else { |
| 36 | + if ( $wgFilterCallback ) { |
| 37 | + $wgPreAkismetFilterCallback = $wgFilterCallback; |
| 38 | + } |
| 39 | + $wgFilterCallback = 'wfAkismetFilter'; |
| 40 | +} |
| 41 | + |
| 42 | +#$wgHooks['EditFilter'][] = 'wfAkismetFilter'; |
| 43 | + |
| 44 | +/** |
| 45 | + * Get an instance of AkismetKlik and do some first-call initialisation. |
| 46 | + * All actual functionality is implemented in that object |
| 47 | + */ |
| 48 | +function wfAkismetKlikObject() { |
| 49 | + global $wgSpamBlacklistSettings, $wgPreSpamFilterCallback; |
| 50 | + static $spamObj; |
| 51 | + if ( !$spamObj ) { |
| 52 | + $spamObj = new AkismetKlik ( $wgSpamBlacklistSettings ); |
| 53 | + $spamObj->previousFilter = $wgPreSpamFilterCallback; |
| 54 | + } |
| 55 | + return $spamObj; |
| 56 | +} |
| 57 | + |
| 58 | +/** |
| 59 | + * Hook function for $wgFilterCallback |
| 60 | + */ |
| 61 | +function wfAkismetFilter( &$title, $text, $section ) { |
| 62 | + $spamObj = wfAkismetKlikObject(); |
| 63 | + return $spamObj->filter( $title, $text, $section ); |
| 64 | +} |
| 65 | + |
| 66 | +/** |
| 67 | + * Hook function for EditFilterMerged, replaces wfAkismetFilter |
| 68 | + */ |
| 69 | +function wfAkismetFilterMerged( $editPage, $text ) { |
| 70 | + $spamObj = new AkismetKlik(); |
| 71 | + $ret = $spamObj->filter( $editPage->mArticle->getTitle(), $text, '', $editPage ); |
| 72 | + // Return convention for hooks is the inverse of $wgAkismetFilterCallback |
| 73 | + return !$ret; |
| 74 | +} |
| 75 | + |
| 76 | +# |
| 77 | +# This class provides the interface to the filters |
| 78 | +# |
| 79 | +class AkismetKlik { |
| 80 | + |
| 81 | + function AkismetKlik( $settings = array() ) { |
| 82 | + foreach ( $settings as $name => $value ) { |
| 83 | + $this->$name = $value; |
| 84 | + echo $value; |
| 85 | + } |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * @param Title $title |
| 90 | + * @param string $text Text of section, or entire text if $editPage!=false |
| 91 | + * @param string $section Section number or name |
| 92 | + * @param EditPage $editPage EditPage if EditFilterMerged was called, false otherwise |
| 93 | + * @return True if the edit should not be allowed, false otherwise |
| 94 | + * If the return value is true, an error will have been sent to $wgOut |
| 95 | + */ |
| 96 | + function filter( &$title, $text, $section, $editPage = false ) { |
| 97 | + global $wgArticle, $wgVersion, $wgOut, $wgParser, $wgUser; |
| 98 | + global $siteURL, $wgAKkey; |
| 99 | + |
| 100 | + $fname = 'wfAkismetKlikFilter'; |
| 101 | + wfProfileIn( $fname ); |
| 102 | + |
| 103 | + # Call the rest of the hook chain first |
| 104 | + if ( $this->previousFilter ) { |
| 105 | + $f = $this->previousFilter; |
| 106 | + if ( $f( $title, $text, $section ) ) { |
| 107 | + wfProfileOut( $fname ); |
| 108 | + return true; |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + $this->title = $title; |
| 113 | + $this->text = $text; |
| 114 | + $this->section = $section; |
| 115 | + $text = str_replace( '.', '.', $text ); |
| 116 | + |
| 117 | + # Run parser to strip SGML comments and such out of the markup |
| 118 | + if ( $editPage ) { |
| 119 | + $editInfo = $editPage->mArticle->prepareTextForEdit( $text ); |
| 120 | + $out = $editInfo->output; |
| 121 | + $pgtitle = $title; |
| 122 | + } else { |
| 123 | + $options = new ParserOptions(); |
| 124 | + $text = $wgParser->preSaveTransform( $text, $title, $wgUser, $options ); |
| 125 | + $out = $wgParser->parse( $text, $title, $options ); |
| 126 | + $pgtitle = ""; |
| 127 | + } |
| 128 | + $links = implode( "\n", array_keys( $out->getExternalLinks())); |
| 129 | + |
| 130 | + # Do the match |
| 131 | + if ($wgUser->mName == "") $user = $IP; |
| 132 | + else $user = $wgUser->mName; |
| 133 | + $akismet = new Akismet($siteURL, $wgAKkey); |
| 134 | + $akismet->setCommentAuthor($user); |
| 135 | + $akismet->setCommentAuthorEmail($wgUser->mEmail); |
| 136 | + $akismet->setCommentAuthorURL($links); |
| 137 | + $akismet->setCommentContent($text); |
| 138 | + $akismet->setCommentType("wiki"); |
| 139 | + $akismet->setPermalink($siteURL . '/wiki/' . $pgtitle); |
| 140 | + if($akismet->isCommentSpam()&&!$wgUser->isAllowed( 'bypassakismet' )) |
| 141 | + { |
| 142 | + wfDebugLog( 'AkismetKlik', "Match!\n" ); |
| 143 | + if ( $editPage ) { |
| 144 | + $editPage->spamPage( "http://akismet.com blacklist error" ); |
| 145 | + } else { |
| 146 | + EditPage::spamPage( "http://akismet.com blacklist error" ); |
| 147 | + } |
| 148 | + return true; |
| 149 | + } |
| 150 | + return false; |
| 151 | + } |
| 152 | +} |
Property changes on: trunk/extensions/AkismetKlik/AkismetKlik.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 153 | + native |