diff --git a/TitleBlacklist.php b/TitleBlacklist.php index 693c1c79..be3a1a4f 100644 --- a/TitleBlacklist.php +++ b/TitleBlacklist.php @@ -40,6 +40,12 @@ $wgTitleBlacklistCaching = array( 'warningexpiry' => 600, ); +$dir = dirname( __FILE__ ); + +// Register the API method +$wgAutoloadClasses['ApiQueryTitleBlacklist'] = "$dir/api/ApiQueryTitleBlacklist.php"; +$wgAPIModules['titleblacklist'] = 'ApiQueryTitleBlacklist'; + $wgAvailableRights[] = 'tboverride'; // Implies tboverride-account $wgAvailableRights[] = 'tboverride-account'; // For account creation $wgGroupPermissions['sysop']['tboverride'] = true; diff --git a/api/ApiQueryTitleBlacklist.php b/api/ApiQueryTitleBlacklist.php new file mode 100644 index 00000000..81ca41ea --- /dev/null +++ b/api/ApiQueryTitleBlacklist.php @@ -0,0 +1,120 @@ + + * Based on code by Victor Vasiliev, Bryan Tong Minh, Roan Kattouw, and Alex Z. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +/** + * Query module check a title against the blacklist + * + * @ingroup API + * @ingroup Extensions + */ + + +class ApiQueryTitleBlacklist extends ApiQueryBase { + + public function __construct( $query, $moduleName ) { + parent::__construct( $query, $moduleName, 'tb' ); + } + + public function execute() { + global $wgTitleBlacklist; // When in Rome... + + # get the current user. + $context = $this->createContext(); + $user = $context->getUser(); + + $params = $this->extractRequestParams(); + $action = $params['action']; + + // check the blacklist, the same way tbhooks does it. + // + // Some places check createpage, while others check create. + // As it stands, upload does createpage, but normalize both + // to the same action, to stop future similar bugs. + if( $action === 'createpage' || $action === 'createtalk' ) { + $action = 'create'; + } + + // possible actions at the moment: create, edit, upload + efInitTitleBlacklist(); + + $blacklisted = $wgTitleBlacklist->userCannot( $params['title'], $user, $action ); + if( $blacklisted instanceof TitleBlacklistEntry ) { + // this title is blacklisted. + $result = array( + htmlspecialchars( $blacklisted->getRaw() ), + htmlspecialchars( $params['title'] ), + ); + + $this->getResult()->addValue( 'titleblacklist', 'result', 'error' ); + $this->getResult()->addValue( 'titleblacklist', 'error', wfMsg($blacklisted->getErrorMessage('edit'), $result) ); + } else { + // not blacklisted + $this->getResult()->addValue( 'titleblacklist', 'result', 'ok' ); + } + + } + + public function getAllowedParams() { + return array( + 'title' => array( + ApiBase::PARAM_REQUIRED => true, + ), + 'action' => array( + ApiBase::PARAM_DFLT => 'edit', + ApiBase::PARAM_ISMULTI => false, + ApiBase::PARAM_TYPE => array( + 'create', 'edit', 'upload', 'createtalk', 'createpage', + ), + ) + ); + } + + public function getParamDescription() { + return array( + 'title' => 'The string to validate against the blacklist', + 'lang' => 'The current language', + 'action' => 'The thing you\'re trying to do', + ); + } + + public function getDescription() { + return 'Validate an article title, filename, or username against the TitleBlacklist.'; + } + + public function getPossibleErrors() { + + //return array_merge( parent::getPossibleErrors(), array( + //) ); + } + + protected function getExamples() { + return array( + 'api.php?action=titleblacklist&tbtitle=Foo', + 'api.php?action=titleblacklist&tbtitle=Bar&tbaction=create', + ); + } + + public function getVersion() { + return __CLASS__ . ': $Id: $'; + } +} diff --git a/tests/ApiQueryTitleBlacklistTest.php b/tests/ApiQueryTitleBlacklistTest.php new file mode 100644 index 00000000..d00356e9 --- /dev/null +++ b/tests/ApiQueryTitleBlacklistTest.php @@ -0,0 +1,55 @@ + + */ + +ini_set( 'include_path', ini_get('include_path') . ':' . __DIR__ . '/../../../tests/phpunit/includes/api' ); + +class ApiQueryTitleBlacklistTest extends ApiTestCase { + + function setUp() { + parent::setUp(); + $this->doLogin(); + } + + function testApiQueryTitleBlacklist() { + global $wgMetaNamespace, $wgGroupPermissions, $wgTitleBlacklistSources; + + // without this, blacklist applies only to anonymous users. + $wgGroupPermissions['sysop']['tboverride'] = false; + + $wgTitleBlacklistSources = array( + array( + 'type' => TBLSRC_FILE, + 'src' => __DIR__ . '/testSource', + ), + ); + + $unlisted = $this->doApiRequest( array( + 'action' => 'titleblacklist', + 'tbtitle' => 'foo', + 'tbaction' => 'create', + ) ); + + $this->assertEquals( $unlisted[0]['titleblacklist']['result'], 'ok', 'Unlisted title returns ok'); + + $listed = $this->doApiRequest( array( + 'action' => 'titleblacklist', + 'tbtitle' => 'bar', + 'tbaction' => 'create', + ) ); + + $this->assertEquals( $listed[0]['titleblacklist']['result'], 'error', 'Listed title returns error'); + $this->assertEquals( + $listed[0]['titleblacklist']['error'], + "The title \"bar\" has been banned from creation.\nIt matches the following blacklist entry: [Bb]ar # example blacklist entry", + 'Listed title error text is as as expected' + ); + } +} \ No newline at end of file diff --git a/tests/testSource b/tests/testSource new file mode 100644 index 00000000..be6827bf --- /dev/null +++ b/tests/testSource @@ -0,0 +1 @@ +[Bb]ar #example blacklist entry