From bb3980dd8d0b3c4d35013ee586bf77e300461155 Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Wed, 4 Feb 2009 20:11:27 +0000 Subject: [PATCH] * API: (bug 17007) Add action=import * Add intoken=import to prop=info * Store message key and arguments in WikiErrorMsg --- RELEASE-NOTES | 1 + includes/AutoLoader.php | 2 + includes/WikiError.php | 10 ++ includes/api/ApiBase.php | 11 ++- includes/api/ApiImport.php | 173 ++++++++++++++++++++++++++++++++++ includes/api/ApiMain.php | 1 + includes/api/ApiQueryInfo.php | 15 +++ 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 includes/api/ApiImport.php diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 65f3698f68..db252c83e5 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -160,6 +160,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * (bug 17007) Added export and exportnowrap parameters to action=query * (bug 17326) BREAKING CHANGE: Changed output format for iiprop=metadata * (bug 17355) Added auwitheditsonly parameter to list=allusers +* (bug 17007) Added action=import === Languages updated in 1.15 === diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 4aeb4337de..b1b992b858 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -234,6 +234,8 @@ $wgAutoloadLocalClasses = array( 'ApiFormatXml' => 'includes/api/ApiFormatXml.php', 'ApiFormatYaml' => 'includes/api/ApiFormatYaml.php', 'ApiHelp' => 'includes/api/ApiHelp.php', + 'ApiImport' => 'includes/api/ApiImport.php', + 'ApiImportReporter' => 'includes/api/ApiImport.php', 'ApiLogin' => 'includes/api/ApiLogin.php', 'ApiLogout' => 'includes/api/ApiLogout.php', 'ApiMain' => 'includes/api/ApiMain.php', diff --git a/includes/WikiError.php b/includes/WikiError.php index 41edb2f376..251c1742e9 100644 --- a/includes/WikiError.php +++ b/includes/WikiError.php @@ -75,6 +75,16 @@ class WikiErrorMsg extends WikiError { $args = func_get_args(); array_shift( $args ); $this->mMessage = wfMsgReal( $message, $args, true ); + $this->mMsgKey = $message; + $this->mMsgArgs = $args; + } + + function getMessageKey() { + return $this->mMsgKey; + } + + function getMessageArgs() { + return $this->mMsgArgs; } } diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 292f7db9fb..0922380fe1 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -727,7 +727,16 @@ abstract class ApiBase { 'protect-invalidaction' => array('code' => 'protect-invalidaction', 'info' => "Invalid protection type ``\$1''"), 'protect-invalidlevel' => array('code' => 'protect-invalidlevel', 'info' => "Invalid protection level ``\$1''"), 'toofewexpiries' => array('code' => 'toofewexpiries', 'info' => "\$1 expiry timestamps were provided where \$2 were needed"), - + 'cantimport' => array('code' => 'cantimport', 'info' => "You don't have permission to import pages"), + 'cantimport-upload' => array('code' => 'cantimport-upload', 'info' => "You don't have permission to import uploaded pages"), + 'importnofile' => array('code' => 'nofile', 'info' => "You didn't upload a file"), + 'importuploaderrorsize' => array('code' => 'filetoobig', 'info' => 'The file you uploaded is bigger than the maximum upload size'), + 'importuploaderrorpartial' => array('code' => 'partialupload', 'info' => 'The file was only partially uploaded'), + 'importuploaderrortemp' => array('code' => 'notempdir', 'info' => 'The temporary upload directory is missing'), + 'importcantopen' => array('code' => 'cantopenfile', 'info' => "Couldn't open the uploaded file"), + 'import-noarticle' => array('code' => 'badinterwiki', 'info' => 'Invalid interwiki title specified'), + 'importbadinterwiki' => array('code' => 'badinterwiki', 'info' => 'Invalid interwiki title specified'), + 'import-unknownerror' => array('code' => 'import-unknownerror', 'info' => "Unknown error on import: ``\$1''"), // ApiEditPage messages 'noimageredirect-anon' => array('code' => 'noimageredirect-anon', 'info' => "Anonymous users can't create image redirects"), diff --git a/includes/api/ApiImport.php b/includes/api/ApiImport.php new file mode 100644 index 0000000000..05037a646c --- /dev/null +++ b/includes/api/ApiImport.php @@ -0,0 +1,173 @@ +.@home.nl + * + * 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * http://www.gnu.org/copyleft/gpl.html + */ + +if (!defined('MEDIAWIKI')) { + // Eclipse helper - will be ignored in production + require_once ('ApiBase.php'); +} + +/** + * API module that imports an XML file like Special:Import does + * + * @ingroup API + */ +class ApiImport extends ApiBase { + + public function __construct($main, $action) { + parent :: __construct($main, $action); + } + + public function execute() { + global $wgUser; + $this->getMain()->requestWriteMode(); + if(!$wgUser->isAllowed('import')) + $this->dieUsageMsg(array('cantimport')); + $params = $this->extractRequestParams(); + if(!isset($params['token'])) + $this->dieUsageMsg(array('missingparam', 'token')); + if(!$wgUser->matchEditToken($params['token'])) + $this->dieUsageMsg(array('sessionfailure')); + + $source = null; + $isUpload = false; + if(isset($params['interwikisource'])) + { + if(!isset($params['interwikipage'])) + $this->dieUsageMsg(array('missingparam', 'interwikipage')); + $source = ImportStreamSource::newFromInterwiki( + $params['interwikisource'], + $params['interwikipage'], + $params['fullhistory']); + } + else + { + $isUpload = true; + if(!$wgUser->isAllowed('importupload')) + $this->dieUsageMsg(array('cantimport-upload')); + $source = ImportStreamSource::newFromUpload('xml'); + } + if($source instanceof WikiErrorMsg) + $this->dieUsageMsg(array_merge( + array($source->getMessageKey()), + $source->getMessageArgs())); + else if(WikiError::isError($source)) + // This shouldn't happen + $this->dieUsageMsg(array('import-unknownerror', $source->getMessage())); + + $importer = new WikiImporter($source); + if(isset($params['namespace'])) + $importer->setTargetNamespace($params['namespace']); + $reporter = new ApiImportReporter($importer, $isUpload, + $params['interwikisource'], + $params['summary']); + + $result = $importer->doImport(); + if($result instanceof WikiXmlError) + $this->dieUsageMsg(array('import-xml-error', + $result->mLine, + $result->mColumn, + $result->mByte . $result->mContext, + xml_error_string($result->mXmlError))); + else if(WikiError::isError($result)) + // This shouldn't happen + $this->dieUsageMsg(array('import-unknownerror', $result->getMessage())); + $resultData = $reporter->getData(); + $this->getResult()->setIndexedTagName($resultData, 'page'); + $this->getResult()->addValue(null, $this->getModuleName(), $resultData); + } + + public function mustBePosted() { return true; } + + public function getAllowedParams() { + global $wgImportSources; + return array ( + 'token' => null, + 'summary' => null, + 'xml' => null, + 'interwikisource' => array( + ApiBase :: PARAM_TYPE => $wgImportSources + ), + 'interwikipage' => null, + 'fullhistory' => false, + 'namespace' => array( + ApiBase :: PARAM_TYPE => 'namespace' + ) + ); + } + + public function getParamDescription() { + return array ( + 'token' => 'Import token obtained through prop=info', + 'summary' => 'Import summary', + 'xml' => 'Uploaded XML file', + 'interwikisource' => 'For interwiki imports: wiki to import from', + 'interwikipage' => 'For interwiki imports: page to import', + 'fullhistory' => 'For interwiki imports: import the full history, not just the current version', + 'namespace' => 'For interwiki imports: import to this namespace', + ); + } + + public function getDescription() { + return array ( + 'Import a page from another wiki, or an XML file' + ); + } + + protected function getExamples() { + return array( + 'Import [[meta:Help:Parserfunctions]] to namespace 100 with full history:', + ' api.php?action=import&interwikisource=meta&interwikipage=Help:ParserFunctions&namespace=100&fullhistory&token=123ABC', + ); + } + + public function getVersion() { + return __CLASS__ . ': $Id$'; + } +} + +/** + * Import reporter for the API + * @ingroup API + */ +class ApiImportReporter extends ImportReporter { + private $mResultArr = array(); + + function reportPage($title, $origTitle, $revisionCount, $successCount) + { + // Add a result entry + $r = array(); + ApiQueryBase::addTitleInfo($r, $title); + $r['revisions'] = $successCount; + $this->mResultArr[] = $r; + + // Piggyback on the parent to do the logging + parent::reportPage($title, $origTitle, $revisionCount, $successCount); + } + + function getData() + { + return $this->mResultArr; + } +} diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index 3d8c65482c..33e9cebf3e 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -80,6 +80,7 @@ class ApiMain extends ApiBase { 'emailuser' => 'ApiEmailUser', 'watch' => 'ApiWatch', 'patrol' => 'ApiPatrol', + 'import' => 'ApiImport', ); /** diff --git a/includes/api/ApiQueryInfo.php b/includes/api/ApiQueryInfo.php index 3a0cc78556..92d088c336 100644 --- a/includes/api/ApiQueryInfo.php +++ b/includes/api/ApiQueryInfo.php @@ -70,6 +70,7 @@ class ApiQueryInfo extends ApiQueryBase { 'block' => array( 'ApiQueryInfo', 'getBlockToken' ), 'unblock' => array( 'ApiQueryInfo', 'getUnblockToken' ), 'email' => array( 'ApiQueryInfo', 'getEmailToken' ), + 'import' => array( 'ApiQueryInfo', 'getImportToken' ), ); wfRunHooks('APIQueryInfoTokens', array(&$this->tokenFunctions)); return $this->tokenFunctions; @@ -167,6 +168,20 @@ class ApiQueryInfo extends ApiQueryBase { $cachedEmailToken = $wgUser->editToken(); return $cachedEmailToken; } + + public static function getImportToken($pageid, $title) + { + global $wgUser; + if(!$wgUser->isAllowed('import')) + return false; + + static $cachedImportToken = null; + if(!is_null($cachedImportToken)) + return $cachedImportToken; + + $cachedImportToken = $wgUser->editToken(); + return $cachedImportToken; + } public function execute() { -- 2.20.1