https://www.mediawiki.org/wiki/Special:Code/MediaWiki/114928

Revision: 114928
Author:   reedy
Date:     2012-04-16 19:05:24 +0000 (Mon, 16 Apr 2012)
Log Message:
-----------
Importing https://www.mediawiki.org/wiki/Extension:AkismetKlik/source

Also bringing in https://github.com/achingbrain/php5-akismet/


Needs some love!

Added Paths:
-----------
    trunk/extensions/AkismetKlik/
    trunk/extensions/AkismetKlik/Akismet.class.php
    trunk/extensions/AkismetKlik/AkismetKlik.php

Added: trunk/extensions/AkismetKlik/Akismet.class.php
===================================================================
--- trunk/extensions/AkismetKlik/Akismet.class.php                              
(rev 0)
+++ trunk/extensions/AkismetKlik/Akismet.class.php      2012-04-16 19:05:24 UTC 
(rev 114928)
@@ -0,0 +1,474 @@
+<?php
+
+/**
+ * Akismet anti-comment spam service
+ *
+ * The class in this package allows use of the {@link http://akismet.com 
Akismet} anti-comment spam service in any PHP5 application.
+ *
+ * This service performs a number of checks on submitted data and returns 
whether or not the data is likely to be spam.
+ *
+ * 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.
+ *
+ * For commercial use, please {@link http://akismet.com/commercial/ visit the 
Akismet commercial licensing page}.
+ *
+ * Please be aware that this class is PHP5 only.  Attempts to run it under 
PHP4 will most likely fail.
+ *
+ * See the Akismet class documentation page linked to below for usage 
information.
+ *
+ * @package            akismet
+ * @author             Alex Potsides, {@link http://www.achingbrain.net 
http://www.achingbrain.net}
+ * @version            0.5
+ * @copyright  Alex Potsides, {@link http://www.achingbrain.net 
http://www.achingbrain.net}
+ * @license            http://www.opensource.org/licenses/bsd-license.php BSD 
License
+ */
+
+/**
+ * The Akismet PHP5 Class
+ *
+ * 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.
+ *
+ * The original plugin is {@link http://akismet.com/download/ available on the 
Akismet website}.
+ *
+ * <code>
+ * $akismet = new Akismet('http://www.example.com/blog/', 'aoeu1aoue');
+ * $akismet->setCommentAuthor($name);
+ * $akismet->setCommentAuthorEmail($email);
+ * $akismet->setCommentAuthorURL($url);
+ * $akismet->setCommentContent($comment);
+ * $akismet->setPermalink('http://www.example.com/blog/alex/someurl/');
+ *
+ * if($akismet->isCommentSpam())
+ *   // store the comment but mark it as spam (in case of a mis-diagnosis)
+ * else
+ *   // store the comment normally
+ * </code>
+ *
+ * Optionally you may wish to check if your WordPress API key is valid as in 
the example below.
+ *
+ * <code>
+ * $akismet = new Akismet('http://www.example.com/blog/', 'aoeu1aoue');
+ *
+ * if($akismet->isKeyValid()) {
+ *   // api key is okay
+ * } else {
+ *   // api key is invalid
+ * }
+ * </code>
+ *
+ * @package    akismet
+ * @name       Akismet
+ * @version    0.5
+ * @author     Alex Potsides
+ * @link       http://www.achingbrain.net/
+ */
+class Akismet {
+       private $version = '0.5';
+       private $wordPressAPIKey;
+       private $blogURL;
+       private $comment;
+       private $apiPort;
+       private $akismetServer;
+       private $akismetVersion;
+       private $requestFactory;
+
+       // This prevents some potentially sensitive information from being sent 
accross the wire.
+       private $ignore = array('HTTP_COOKIE',
+                                                       'HTTP_X_FORWARDED_FOR',
+                                                       'HTTP_X_FORWARDED_HOST',
+                                                       'HTTP_MAX_FORWARDS',
+                                                       
'HTTP_X_FORWARDED_SERVER',
+                                                       'REDIRECT_STATUS',
+                                                       'SERVER_PORT',
+                                                       'PATH',
+                                                       'DOCUMENT_ROOT',
+                                                       'SERVER_ADMIN',
+                                                       'QUERY_STRING',
+                                                       'PHP_SELF' );
+
+       /**
+        * @param       string  $blogURL                        The URL of your 
blog.
+        * @param       string  $wordPressAPIKey        WordPress API key.
+        */
+       public function __construct($blogURL, $wordPressAPIKey) {
+               $this->blogURL = $blogURL;
+               $this->wordPressAPIKey = $wordPressAPIKey;
+
+               // Set some default values
+               $this->apiPort = 80;
+               $this->akismetServer = 'rest.akismet.com';
+               $this->akismetVersion = '1.1';
+               $this->requestFactory = new SocketWriteReadFactory();
+
+               // Start to populate the comment data
+               $this->comment['blog'] = $blogURL;
+
+               if(isset($_SERVER['HTTP_USER_AGENT'])) {
+                       $this->comment['user_agent'] = 
$_SERVER['HTTP_USER_AGENT'];
+               }
+
+               if(isset($_SERVER['HTTP_REFERER'])) {
+                       $this->comment['referrer'] = $_SERVER['HTTP_REFERER'];
+               }
+
+               /*
+                * This is necessary if the server PHP5 is running on has been 
set up to run PHP4 and
+                * PHP5 concurently and is actually running through a separate 
proxy al a these instructions:
+                * 
http://www.schlitt.info/applications/blog/archives/83_How_to_run_PHP4_and_PHP_5_parallel.html
+                * and http://wiki.coggeshall.org/37.html
+                * Otherwise the user_ip appears as the IP address of the PHP4 
server passing the requests to the
+                * PHP5 one...
+                */
+               if(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] != 
getenv('SERVER_ADDR')) {
+                       $this->comment['user_ip'] = $_SERVER['REMOTE_ADDR'];
+               } else {
+                       $this->comment['user_ip'] = 
getenv('HTTP_X_FORWARDED_FOR');
+               }
+       }
+
+       /**
+        * Makes a request to the Akismet service to see if the API key passed 
to the constructor is valid.
+        *
+        * Use this method if you suspect your API key is invalid.
+        *
+        * @return bool True is if the key is valid, false if not.
+        */
+       public function isKeyValid() {
+               // Check to see if the key is valid
+               $response = $this->sendRequest('key=' . $this->wordPressAPIKey 
. '&blog=' . $this->blogURL, $this->akismetServer, '/' . $this->akismetVersion 
. '/verify-key');
+               return $response[1] == 'valid';
+       }
+
+       // makes a request to the Akismet service
+       private function sendRequest($request, $host, $path) {
+               $http_request  = "POST " . $path . " HTTP/1.0\r\n";
+               $http_request .= "Host: " . $host . "\r\n";
+               $http_request .= "Content-Type: 
application/x-www-form-urlencoded; charset=utf-8\r\n";
+               $http_request .= "Content-Length: " . strlen($request) . "\r\n";
+               $http_request .= "User-Agent: Akismet PHP5 Class " . 
$this->version . " | Akismet/1.11\r\n";
+               $http_request .= "\r\n";
+               $http_request .= $request;
+
+               $requestSender = $this->requestFactory->createRequestSender();
+               $response = $requestSender->send($host, $this->apiPort, 
$http_request);
+
+               return explode("\r\n\r\n", $response, 2);
+       }
+
+       // Formats the data for transmission
+       private function getQueryString() {
+               foreach($_SERVER as $key => $value) {
+                       if(!in_array($key, $this->ignore)) {
+                               if($key == 'REMOTE_ADDR') {
+                                       $this->comment[$key] = 
$this->comment['user_ip'];
+                               } else {
+                                       $this->comment[$key] = $value;
+                               }
+                       }
+               }
+
+               $query_string = '';
+
+               foreach($this->comment as $key => $data) {
+                       if(!is_array($data)) {
+                               $query_string .= $key . '=' . 
urlencode(stripslashes($data)) . '&';
+                       }
+               }
+
+               return $query_string;
+       }
+
+       /**
+        * Tests for spam.
+        *
+        * 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.
+        *
+        * @return      bool    True if the comment is spam, false if not
+        * @throws      Will throw an exception if the API key passed to the 
constructor is invalid.
+        */
+       public function isCommentSpam() {
+               $response = $this->sendRequest($this->getQueryString(), 
$this->wordPressAPIKey . '.rest.akismet.com', '/' . $this->akismetVersion . 
'/comment-check');
+
+               if($response[1] == 'invalid' && !$this->isKeyValid()) {
+                       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/');
+               }
+
+               return ($response[1] == 'true');
+       }
+
+       /**
+        * Submit spam that is incorrectly tagged as ham.
+        *
+        * 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.
+        */
+       public function submitSpam() {
+               $this->sendRequest($this->getQueryString(), 
$this->wordPressAPIKey . '.' . $this->akismetServer, '/' . 
$this->akismetVersion . '/submit-spam');
+       }
+
+       /**
+        * Submit ham that is incorrectly tagged as spam.
+        *
+        * 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.
+        */
+       public function submitHam() {
+               $this->sendRequest($this->getQueryString(), 
$this->wordPressAPIKey . '.' . $this->akismetServer, '/' . 
$this->akismetVersion . '/submit-ham');
+       }
+
+       /**
+        * To override the user IP address when submitting spam/ham later on
+        *
+        * @param string $userip        An IP address.  Optional.
+        */
+       public function setUserIP($userip) {
+               $this->comment['user_ip'] = $userip;
+       }
+
+       /**
+        * To override the referring page when submitting spam/ham later on
+        *
+        * @param string $referrer      The referring page.  Optional.
+        */
+       public function setReferrer($referrer) {
+               $this->comment['referrer'] = $referrer;
+       }
+
+       /**
+        * A permanent URL referencing the blog post the comment was submitted 
to.
+        *
+        * @param string $permalink     The URL.  Optional.
+        */
+       public function setPermalink($permalink) {
+               $this->comment['permalink'] = $permalink;
+       }
+
+       /**
+        * The type of comment being submitted.
+        *
+        * May be blank, comment, trackback, pingback, or a made up value like 
"registration" or "wiki".
+        */
+       public function setCommentType($commentType) {
+               $this->comment['comment_type'] = $commentType;
+       }
+
+       /**
+        *      The name that the author submitted with the comment.
+        */
+       public function setCommentAuthor($commentAuthor) {
+               $this->comment['comment_author'] = $commentAuthor;
+       }
+
+       /**
+        * The email address that the author submitted with the comment.
+        *
+        * The address is assumed to be valid.
+        */
+       public function setCommentAuthorEmail($authorEmail) {
+               $this->comment['comment_author_email'] = $authorEmail;
+       }
+
+       /**
+        * The URL that the author submitted with the comment.
+        */
+       public function setCommentAuthorURL($authorURL) {
+               $this->comment['comment_author_url'] = $authorURL;
+       }
+
+       /**
+        * The comment's body text.
+        */
+       public function setCommentContent($commentBody) {
+               $this->comment['comment_content'] = $commentBody;
+       }
+
+       /**
+        * Lets you override the user agent used to submit the comment.
+        * you may wish to do this when submitting ham/spam.
+        * Defaults to $_SERVER['HTTP_USER_AGENT']
+        */
+       public function setCommentUserAgent($userAgent) {
+               $this->comment['user_agent'] = $userAgent;
+       }
+
+       /**
+        * Defaults to 80
+        */
+       public function setAPIPort($apiPort) {
+               $this->apiPort = $apiPort;
+       }
+
+       /**
+        * Defaults to rest.akismet.com
+        */
+       public function setAkismetServer($akismetServer) {
+               $this->akismetServer = $akismetServer;
+       }
+
+       /**
+        * Defaults to '1.1'
+        *
+        * @param string $akismetVersion
+        */
+       public function setAkismetVersion($akismetVersion) {
+               $this->akismetVersion = $akismetVersion;
+       }
+
+       /**
+        * Used by unit tests to mock transport layer
+        *
+        * @param AkismetRequestFactory $requestFactory
+        */
+       public function setRequestFactory($requestFactory) {
+               $this->requestFactory = $requestFactory;
+       }
+}
+
+/**
+ * Used internally by Akismet
+ *
+ * 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.
+ *
+ * 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}.
+ *
+ * N.B. It is not necessary to call this class directly to use the Akismet 
class.
+ *
+ * @package    akismet
+ * @name       SocketWriteRead
+ * @version    0.5
+ * @author     Alex Potsides
+ * @link       http://www.achingbrain.net/
+ */
+class SocketWriteRead implements AkismetRequestSender {
+       private $response;
+       private $errorNumber;
+       private $errorString;
+
+       public function __construct() {
+               $this->errorNumber = 0;
+               $this->errorString = '';
+       }
+
+       /**
+        *  Sends the data to the remote host.
+        *
+        * @param       string  $host                   The host to 
send/receive data.
+        * @param       int             $port                   The port on the 
remote host.
+        * @param       string  $request                The data to send.
+        * @param       int             $responseLength The amount of data to 
read.  Defaults to 1160 bytes.
+        * @throws      An exception is thrown if a connection cannot be made 
to the remote host.
+        * @returns     The server response
+        */
+       public function send($host, $port, $request, $responseLength = 1160) {
+               $response = '';
+
+               $fs = fsockopen($host, $port, $this->errorNumber, 
$this->errorString, 3);
+
+               if($this->errorNumber != 0) {
+                       throw new Exception('Error connecting to host: ' . 
$host . ' Error number: ' . $this->errorNumber . ' Error message: ' . 
$this->errorString);
+               }
+
+               if($fs !== false) {
+                       @fwrite($fs, $request);
+
+                       while(!feof($fs)) {
+                               $response .= fgets($fs, $responseLength);
+                       }
+
+                       fclose($fs);
+               }
+
+               return $response;
+       }
+
+       /**
+        * Returns the server response text
+        *
+        * @return      string
+        */
+       public function getResponse() {
+               return $this->response;
+       }
+
+       /**
+        * Returns the error number
+        *
+        * If there was no error, 0 will be returned.
+        *
+        * @return int
+        */
+       public function getErrorNumner() {
+               return $this->errorNumber;
+       }
+
+       /**
+        * Returns the error string
+        *
+        * If there was no error, an empty string will be returned.
+        *
+        * @return string
+        */
+       public function getErrorString() {
+               return $this->errorString;
+       }
+}
+
+/**
+ * Used internally by the Akismet class and to mock the Akismet anti spam 
service in
+ * the unit tests.
+ *
+ * N.B. It is not necessary to call this class directly to use the Akismet 
class.
+ *
+ * @package    akismet
+ * @name       SocketWriteReadFactory
+ * @version    0.5
+ * @author     Alex Potsides
+ * @link       http://www.achingbrain.net/
+ */
+class SocketWriteReadFactory implements AkismetRequestFactory {
+
+       public function createRequestSender() {
+               return new SocketWriteRead();
+       }
+}
+
+/**
+ * Used internally by the Akismet class and to mock the Akismet anti spam 
service in
+ * the unit tests.
+ *
+ * N.B. It is not necessary to implement this class to use the Akismet class.
+ *
+ * @package    akismet
+ * @name       AkismetRequestSender
+ * @version    0.5
+ * @author     Alex Potsides
+ * @link       http://www.achingbrain.net/
+ */
+interface AkismetRequestSender {
+
+       /**
+        *  Sends the data to the remote host.
+        *
+        * @param       string  $host                   The host to 
send/receive data.
+        * @param       int             $port                   The port on the 
remote host.
+        * @param       string  $request                The data to send.
+        * @param       int             $responseLength The amount of data to 
read.  Defaults to 1160 bytes.
+        * @throws      An exception is thrown if a connection cannot be made 
to the remote host.
+        * @returns     The server response
+        */
+       public function send($host, $port, $request, $responseLength = 1160);
+}
+
+/**
+ * Used internally by the Akismet class and to mock the Akismet anti spam 
service in
+ * the unit tests.
+ *
+ * N.B. It is not necessary to implement this class to use the Akismet class.
+ *
+ * @package    akismet
+ * @name       AkismetRequestFactory
+ * @version    0.5
+ * @author     Alex Potsides
+ * @link       http://www.achingbrain.net/
+ */
+interface AkismetRequestFactory {
+
+       public function createRequestSender();
+}


Property changes on: trunk/extensions/AkismetKlik/Akismet.class.php
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/extensions/AkismetKlik/AkismetKlik.php
===================================================================
--- trunk/extensions/AkismetKlik/AkismetKlik.php                                
(rev 0)
+++ trunk/extensions/AkismetKlik/AkismetKlik.php        2012-04-16 19:05:24 UTC 
(rev 114928)
@@ -0,0 +1,151 @@
+<?php
+if ( !defined( 'MEDIAWIKI' ) ) {
+       exit;
+}
+
+#
+# Include PHP5 Akismet class from http://www.achingbrain.net/stuff/akismet 
(GPL)
+#
+require_once('Akismet.class.php');
+
+#Extension credits
+$wgExtensionCredits['other'][] = array(
+       'name' => 'AkismetKlik',
+       'author' => 'Carl Austin Bennett',
+       'url' => 'http://www.mediawiki.org/wiki/Extension:AkismetKlik',
+       'description' => 'Rejects edits from suspected comment spammers on 
Akismet\'s blacklist.',
+);
+
+# Set site-specific configuration values
+#$wgAKkey='867-5309';
+#$siteURL='http://wiki.example.org';
+
+#
+# MediaWiki hooks
+#
+# Loader for spam blacklist feature
+# Include this from LocalSettings.php
+
+global $wgAkismetFilterCallback, $wgPreAkismetFilterCallback, $wgUser;
+$wgPreAkismetFilterCallback = false;
+
+if ( defined( 'MW_SUPPORTS_EDITFILTERMERGED' ) ) {
+       $wgHooks['EditFilterMerged'][] = 'wfAkismetFilterMerged';
+} else {
+       if ( $wgFilterCallback ) {
+               $wgPreAkismetFilterCallback = $wgFilterCallback;
+       }
+       $wgFilterCallback = 'wfAkismetFilter';
+}
+
+#$wgHooks['EditFilter'][] = 'wfAkismetFilter';
+
+/**
+ * Get an instance of AkismetKlik and do some first-call initialisation.
+ * All actual functionality is implemented in that object
+ */
+function wfAkismetKlikObject() {
+       global $wgSpamBlacklistSettings, $wgPreSpamFilterCallback;
+       static $spamObj;
+       if ( !$spamObj ) {
+               $spamObj = new AkismetKlik ( $wgSpamBlacklistSettings );
+               $spamObj->previousFilter = $wgPreSpamFilterCallback;
+       }
+       return $spamObj;
+}
+
+/**
+ * Hook function for $wgFilterCallback
+ */
+function wfAkismetFilter( &$title, $text, $section ) {
+       $spamObj = wfAkismetKlikObject();
+       return $spamObj->filter( $title, $text, $section );
+}
+
+/**
+ * Hook function for EditFilterMerged, replaces wfAkismetFilter
+ */
+function wfAkismetFilterMerged( $editPage, $text ) {
+       $spamObj = new AkismetKlik();
+       $ret = $spamObj->filter( $editPage->mArticle->getTitle(), $text, '', 
$editPage );
+       // Return convention for hooks is the inverse of 
$wgAkismetFilterCallback
+       return !$ret;
+}
+
+#
+# This class provides the interface to the filters
+#
+class AkismetKlik {
+
+       function AkismetKlik( $settings = array() ) {
+               foreach ( $settings as $name => $value ) {
+                       $this->$name = $value;
+                       echo $value;
+               }
+       }
+
+       /**
+        * @param Title $title
+        * @param string $text Text of section, or entire text if 
$editPage!=false
+        * @param string $section Section number or name
+        * @param EditPage $editPage EditPage if EditFilterMerged was called, 
false otherwise
+        * @return True if the edit should not be allowed, false otherwise
+        * If the return value is true, an error will have been sent to $wgOut
+        */
+       function filter( &$title, $text, $section, $editPage = false ) {
+               global $wgArticle, $wgVersion, $wgOut, $wgParser, $wgUser;
+               global $siteURL, $wgAKkey;
+
+               $fname = 'wfAkismetKlikFilter';
+               wfProfileIn( $fname );
+
+               # Call the rest of the hook chain first
+               if ( $this->previousFilter ) {
+                       $f = $this->previousFilter;
+                       if ( $f( $title, $text, $section ) ) {
+                               wfProfileOut( $fname );
+                               return true;
+                       }
+               }
+
+               $this->title = $title;
+               $this->text = $text;
+               $this->section = $section;
+               $text = str_replace( '.', '.', $text );
+
+               # Run parser to strip SGML comments and such out of the markup
+               if ( $editPage ) {
+                       $editInfo = $editPage->mArticle->prepareTextForEdit( 
$text );
+                       $out = $editInfo->output;
+                       $pgtitle = $title;
+               } else {
+                       $options = new ParserOptions();
+                       $text = $wgParser->preSaveTransform( $text, $title, 
$wgUser, $options );
+                       $out = $wgParser->parse( $text, $title, $options );
+                       $pgtitle = "";
+               }
+               $links = implode( "\n", array_keys( $out->getExternalLinks()));
+
+               # Do the match
+               if ($wgUser->mName == "") $user = $IP;
+               else $user = $wgUser->mName;
+               $akismet = new Akismet($siteURL, $wgAKkey);
+               $akismet->setCommentAuthor($user);
+               $akismet->setCommentAuthorEmail($wgUser->mEmail);
+               $akismet->setCommentAuthorURL($links);
+               $akismet->setCommentContent($text);
+               $akismet->setCommentType("wiki");
+               $akismet->setPermalink($siteURL . '/wiki/' . $pgtitle);
+               if($akismet->isCommentSpam()&&!$wgUser->isAllowed( 
'bypassakismet' ))
+               {
+                       wfDebugLog( 'AkismetKlik', "Match!\n" );
+                       if ( $editPage ) {
+                               $editPage->spamPage( "http://akismet.com 
blacklist error" );
+                       } else {
+                               EditPage::spamPage( "http://akismet.com 
blacklist error" );
+                       }
+                       return true;
+               }
+               return false;
+       }
+}


Property changes on: trunk/extensions/AkismetKlik/AkismetKlik.php
___________________________________________________________________
Added: svn:eol-style
   + native


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to