示例#1
0
	/**
	 * Constructor
	 * @param $dbSource ApiBase Module implementing getDB().
	 *        Allows PageSet to reuse existing db connection from the shared state like ApiQuery.
	 * @param int $flags Zero or more flags like DISABLE_GENERATORS
	 * @param int $defaultNamespace the namespace to use if none is specified by a prefix.
	 * @since 1.21 accepts $flags instead of two boolean values
	 */
	public function __construct( ApiBase $dbSource, $flags = 0, $defaultNamespace = NS_MAIN ) {
		parent::__construct( $dbSource->getMain(), $dbSource->getModuleName() );
		$this->mDbSource = $dbSource;
		$this->mAllowGenerator = ( $flags & ApiPageSet::DISABLE_GENERATORS ) == 0;
		$this->mDefaultNamespace = $defaultNamespace;

		$this->profileIn();
		$this->mParams = $this->extractRequestParams();
		$this->mResolveRedirects = $this->mParams['redirects'];
		$this->mConvertTitles = $this->mParams['converttitles'];
		$this->profileOut();
	}
 /**
  * APIAfterExecute hook handler
  * @see: https://www.mediawiki.org/wiki/Manual:Hooks/
  * @param ApiBase $module
  * @return bool
  */
 public static function onAPIAfterExecute(ApiBase &$module)
 {
     global $wgMFSpecialCaseMainPage;
     if ($module->getModuleName() == 'parse') {
         if (defined('ApiResult::META_CONTENT')) {
             $data = $module->getResult()->getResultData();
         } else {
             $data = $module->getResultData();
         }
         $params = $module->extractRequestParams();
         if (isset($data['parse']['text']) && $params['mobileformat']) {
             $result = $module->getResult();
             $result->reset();
             $title = Title::newFromText($data['parse']['title']);
             $text = $data['parse']['text'];
             if (is_array($text)) {
                 if (defined('ApiResult::META_CONTENT') && isset($text[ApiResult::META_CONTENT])) {
                     $contentKey = $text[ApiResult::META_CONTENT];
                 } else {
                     $contentKey = '*';
                 }
                 $html = MobileFormatter::wrapHTML($text[$contentKey]);
             } else {
                 $html = MobileFormatter::wrapHTML($text);
             }
             $mf = new MobileFormatter($html, $title);
             $mf->setRemoveMedia($params['noimages']);
             $mf->setIsMainPage($params['mainpage'] && $wgMFSpecialCaseMainPage);
             $mf->enableExpandableSections(!$params['mainpage']);
             // HACK: need a nice way to request a TOC- and edit link-free HTML in the first place
             // FIXME: Should this be .mw-editsection?
             $mf->remove(array('.toc', 'mw-editsection', '.mw-headline-anchor'));
             $mf->filterContent();
             if (is_array($text)) {
                 $text[$contentKey] = $mf->getText();
             } else {
                 $text = $mf->getText();
             }
             $data['parse']['text'] = $text;
             $result->addValue(null, $module->getModuleName(), $data['parse']);
         }
     }
     return true;
 }
示例#3
0
 /**
  * Execute an action, and in case of an error, erase whatever partial results
  * have been accumulated, and replace it with an error message and a help screen.
  */
 protected function executeActionWithErrorHandling()
 {
     // Verify the CORS header before executing the action
     if (!$this->handleCORS()) {
         // handleCORS() has sent a 403, abort
         return;
     }
     // Exit here if the request method was OPTIONS
     // (assume there will be a followup GET or POST)
     if ($this->getRequest()->getMethod() === 'OPTIONS') {
         return;
     }
     // In case an error occurs during data output,
     // clear the output buffer and print just the error information
     $obLevel = ob_get_level();
     ob_start();
     $t = microtime(true);
     $isError = false;
     try {
         $this->executeAction();
         $runTime = microtime(true) - $t;
         $this->logRequest($runTime);
         if ($this->mModule->isWriteMode() && $this->getRequest()->wasPosted()) {
             $this->getStats()->timing('api.' . $this->mModule->getModuleName() . '.executeTiming', 1000 * $runTime);
         }
     } catch (Exception $e) {
         $this->handleException($e);
         $this->logRequest(microtime(true) - $t, $e);
         $isError = true;
     }
     // Commit DBs and send any related cookies and headers
     MediaWiki::preOutputCommit($this->getContext());
     // Send cache headers after any code which might generate an error, to
     // avoid sending public cache headers for errors.
     $this->sendCacheHeaders($isError);
     // Executing the action might have already messed with the output
     // buffers.
     while (ob_get_level() > $obLevel) {
         ob_end_flush();
     }
 }
示例#4
0
 /**
  * @deprecated since 1.25
  * @param ApiBase $module
  * @param string $paramName What type of request is this? e.g. action,
  *    query, list, prop, meta, format
  * @return string
  */
 public static function makeHelpMsgHeader($module, $paramName)
 {
     wfDeprecated(__METHOD__, '1.25');
     $modulePrefix = $module->getModulePrefix();
     if (strval($modulePrefix) !== '') {
         $modulePrefix = "({$modulePrefix}) ";
     }
     return "* {$paramName}={$module->getModuleName()} {$modulePrefix}*";
 }
示例#5
0
 /**
  * Set the continuation parameter for the generator module
  *
  * @since 1.24
  * @param ApiBase $module
  * @param string $paramName
  * @param string|array $paramValue
  */
 public function setGeneratorContinueParam(ApiBase $module, $paramName, $paramValue)
 {
     $name = $module->getModuleName();
     $paramName = $module->encodeParamName($paramName);
     if (is_array($paramValue)) {
         $paramValue = join('|', $paramValue);
     }
     $this->generatorContinuationData[$name][$paramName] = $paramValue;
 }
示例#6
0
 /**
  * @param ApiBase $module
  * @return ApiResult
  */
 private function getModuleInfo($module)
 {
     $ret = [];
     $path = $module->getModulePath();
     $ret['name'] = $module->getModuleName();
     $ret['classname'] = get_class($module);
     $ret['path'] = $path;
     if (!$module->isMain()) {
         $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup($module->getModuleName());
     }
     $ret['prefix'] = $module->getModulePrefix();
     $sourceInfo = $module->getModuleSourceInfo();
     if ($sourceInfo) {
         $ret['source'] = $sourceInfo['name'];
         if (isset($sourceInfo['namemsg'])) {
             $ret['sourcename'] = $this->context->msg($sourceInfo['namemsg'])->text();
         } else {
             $ret['sourcename'] = $ret['source'];
         }
         $link = SpecialPage::getTitleFor('Version', 'License/' . $sourceInfo['name'])->getFullURL();
         if (isset($sourceInfo['license-name'])) {
             $ret['licensetag'] = $sourceInfo['license-name'];
             $ret['licenselink'] = (string) $link;
         } elseif (SpecialVersion::getExtLicenseFileName(dirname($sourceInfo['path']))) {
             $ret['licenselink'] = (string) $link;
         }
     }
     $this->formatHelpMessages($ret, 'description', $module->getFinalDescription());
     foreach ($module->getHelpFlags() as $flag) {
         $ret[$flag] = true;
     }
     $ret['helpurls'] = (array) $module->getHelpUrls();
     if (isset($ret['helpurls'][0]) && $ret['helpurls'][0] === false) {
         $ret['helpurls'] = [];
     }
     ApiResult::setIndexedTagName($ret['helpurls'], 'helpurl');
     if ($this->helpFormat !== 'none') {
         $ret['examples'] = [];
         $examples = $module->getExamplesMessages();
         foreach ($examples as $qs => $msg) {
             $item = ['query' => $qs];
             $msg = ApiBase::makeMessage($msg, $this->context, [$module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()]);
             $this->formatHelpMessages($item, 'description', [$msg]);
             if (isset($item['description'])) {
                 if (is_array($item['description'])) {
                     $item['description'] = $item['description'][0];
                 } else {
                     ApiResult::setSubelementsList($item, 'description');
                 }
             }
             $ret['examples'][] = $item;
         }
         ApiResult::setIndexedTagName($ret['examples'], 'example');
     }
     $ret['parameters'] = [];
     $params = $module->getFinalParams(ApiBase::GET_VALUES_FOR_HELP);
     $paramDesc = $module->getFinalParamDescription();
     foreach ($params as $name => $settings) {
         if (!is_array($settings)) {
             $settings = [ApiBase::PARAM_DFLT => $settings];
         }
         $item = ['name' => $name];
         if (isset($paramDesc[$name])) {
             $this->formatHelpMessages($item, 'description', $paramDesc[$name], true);
         }
         $item['required'] = !empty($settings[ApiBase::PARAM_REQUIRED]);
         if (!empty($settings[ApiBase::PARAM_DEPRECATED])) {
             $item['deprecated'] = true;
         }
         if ($name === 'token' && $module->needsToken()) {
             $item['tokentype'] = $module->needsToken();
         }
         if (!isset($settings[ApiBase::PARAM_TYPE])) {
             $dflt = isset($settings[ApiBase::PARAM_DFLT]) ? $settings[ApiBase::PARAM_DFLT] : null;
             if (is_bool($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'boolean';
             } elseif (is_string($dflt) || is_null($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'string';
             } elseif (is_int($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'integer';
             }
         }
         if (isset($settings[ApiBase::PARAM_DFLT])) {
             switch ($settings[ApiBase::PARAM_TYPE]) {
                 case 'boolean':
                     $item['default'] = (bool) $settings[ApiBase::PARAM_DFLT];
                     break;
                 case 'string':
                 case 'text':
                 case 'password':
                     $item['default'] = strval($settings[ApiBase::PARAM_DFLT]);
                     break;
                 case 'integer':
                 case 'limit':
                     $item['default'] = intval($settings[ApiBase::PARAM_DFLT]);
                     break;
                 case 'timestamp':
                     $item['default'] = wfTimestamp(TS_ISO_8601, $settings[ApiBase::PARAM_DFLT]);
                     break;
                 default:
                     $item['default'] = $settings[ApiBase::PARAM_DFLT];
                     break;
             }
         }
         $item['multi'] = !empty($settings[ApiBase::PARAM_ISMULTI]);
         if ($item['multi']) {
             $item['limit'] = $this->getMain()->canApiHighLimits() ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_SML1;
             $item['lowlimit'] = ApiBase::LIMIT_SML1;
             $item['highlimit'] = ApiBase::LIMIT_SML2;
         }
         if (!empty($settings[ApiBase::PARAM_ALLOW_DUPLICATES])) {
             $item['allowsduplicates'] = true;
         }
         if (isset($settings[ApiBase::PARAM_TYPE])) {
             if ($settings[ApiBase::PARAM_TYPE] === 'submodule') {
                 if (isset($settings[ApiBase::PARAM_SUBMODULE_MAP])) {
                     ksort($settings[ApiBase::PARAM_SUBMODULE_MAP]);
                     $item['type'] = array_keys($settings[ApiBase::PARAM_SUBMODULE_MAP]);
                     $item['submodules'] = $settings[ApiBase::PARAM_SUBMODULE_MAP];
                 } else {
                     $item['type'] = $module->getModuleManager()->getNames($name);
                     sort($item['type']);
                     $prefix = $module->isMain() ? '' : $module->getModulePath() . '+';
                     $item['submodules'] = [];
                     foreach ($item['type'] as $v) {
                         $item['submodules'][$v] = $prefix . $v;
                     }
                 }
                 if (isset($settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX])) {
                     $item['submoduleparamprefix'] = $settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX];
                 }
             } elseif ($settings[ApiBase::PARAM_TYPE] === 'tags') {
                 $item['type'] = ChangeTags::listExplicitlyDefinedTags();
             } else {
                 $item['type'] = $settings[ApiBase::PARAM_TYPE];
             }
             if (is_array($item['type'])) {
                 // To prevent sparse arrays from being serialized to JSON as objects
                 $item['type'] = array_values($item['type']);
                 ApiResult::setIndexedTagName($item['type'], 't');
             }
         }
         if (isset($settings[ApiBase::PARAM_MAX])) {
             $item['max'] = $settings[ApiBase::PARAM_MAX];
         }
         if (isset($settings[ApiBase::PARAM_MAX2])) {
             $item['highmax'] = $settings[ApiBase::PARAM_MAX2];
         }
         if (isset($settings[ApiBase::PARAM_MIN])) {
             $item['min'] = $settings[ApiBase::PARAM_MIN];
         }
         if (!empty($settings[ApiBase::PARAM_RANGE_ENFORCE])) {
             $item['enforcerange'] = true;
         }
         if (!empty($settings[ApiBase::PARAM_HELP_MSG_INFO])) {
             $item['info'] = [];
             foreach ($settings[ApiBase::PARAM_HELP_MSG_INFO] as $i) {
                 $tag = array_shift($i);
                 $info = ['name' => $tag];
                 if (count($i)) {
                     $info['values'] = $i;
                     ApiResult::setIndexedTagName($info['values'], 'v');
                 }
                 $this->formatHelpMessages($info, 'text', [$this->context->msg("apihelp-{$path}-paraminfo-{$tag}")->numParams(count($i))->params($this->context->getLanguage()->commaList($i))->params($module->getModulePrefix())]);
                 ApiResult::setSubelementsList($info, 'text');
                 $item['info'][] = $info;
             }
             ApiResult::setIndexedTagName($item['info'], 'i');
         }
         $ret['parameters'][] = $item;
     }
     ApiResult::setIndexedTagName($ret['parameters'], 'param');
     $dynamicParams = $module->dynamicParameterDocumentation();
     if ($dynamicParams !== null) {
         if ($this->helpFormat === 'none') {
             $ret['dynamicparameters'] = true;
         } else {
             $dynamicParams = ApiBase::makeMessage($dynamicParams, $this->context, [$module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()]);
             $this->formatHelpMessages($ret, 'dynamicparameters', [$dynamicParams]);
         }
     }
     return $ret;
 }
 /**
  * Validate "centralauthtoken", and disable certain modules that make no
  * sense with "centralauthtoken".
  * @param ApiBase $module API module
  * @param User $user User
  * @param array &$message Error message key and params
  * @return bool
  */
 static function onApiCheckCanExecute($module, $user, &$message)
 {
     global $wgCentralAuthCookies;
     if (!$wgCentralAuthCookies) {
         return true;
     }
     if (self::hasApiToken()) {
         $module->getMain()->getVal('centralauthtoken');
         # Mark used
         $apiCentralUser = self::getApiCentralUser(true);
         $centralUser = CentralAuthUser::getInstance($user);
         if (!$apiCentralUser || !$centralUser || $apiCentralUser->getId() !== $centralUser->getId()) {
             // Bad design, API.
             ApiBase::$messageMap['centralauth-api-badtoken'] = array('code' => 'badtoken', 'info' => 'The centralauthtoken is not valid');
             $message = array('centralauth-api-badtoken');
             return false;
         }
         if ($module instanceof ApiLogin || $module instanceof ApiLogout) {
             // Bad design, API.
             ApiBase::$messageMap['centralauth-api-blacklistedmodule'] = array('code' => 'badparams', 'info' => 'The module "$1" may not be used with centralauthtoken');
             $message = array('centralauth-api-blacklistedmodule', $module->getModuleName());
             return false;
         }
     }
     return true;
 }
示例#8
0
 /**
  * @param ApiBase $module
  * @param string $paramName What type of request is this? e.g. action,
  *    query, list, prop, meta, format
  * @return string
  */
 public static function makeHelpMsgHeader($module, $paramName)
 {
     $modulePrefix = $module->getModulePrefix();
     if (strval($modulePrefix) !== '') {
         $modulePrefix = "({$modulePrefix}) ";
     }
     return "* {$paramName}={$module->getModuleName()} {$modulePrefix}*";
 }
 /**
  * @param ApiBase $module
  * @return ApiResult
  */
 private function getModuleInfo($module)
 {
     $result = $this->getResult();
     $ret = array();
     $path = $module->getModulePath();
     $ret['name'] = $module->getModuleName();
     $ret['classname'] = get_class($module);
     $ret['path'] = $path;
     if (!$module->isMain()) {
         $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup($module->getModuleName());
     }
     $ret['prefix'] = $module->getModulePrefix();
     $this->formatHelpMessages($ret, 'description', $module->getFinalDescription());
     foreach ($module->getHelpFlags() as $flag) {
         $ret[$flag] = true;
     }
     $ret['helpurls'] = (array) $module->getHelpUrls();
     if (isset($ret['helpurls'][0]) && $ret['helpurls'][0] === false) {
         $ret['helpurls'] = array();
     }
     ApiResult::setIndexedTagName($ret['helpurls'], 'helpurl');
     if ($this->helpFormat !== 'none') {
         $ret['examples'] = array();
         $examples = $module->getExamplesMessages();
         foreach ($examples as $qs => $msg) {
             $item = array('query' => $qs);
             $msg = ApiBase::makeMessage($msg, $this->context, array($module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()));
             $this->formatHelpMessages($item, 'description', array($msg));
             if (isset($item['description'])) {
                 if (is_array($item['description'])) {
                     $item['description'] = $item['description'][0];
                 } else {
                     ApiResult::setSubelementsList($item, 'description');
                 }
             }
             $ret['examples'][] = $item;
         }
         ApiResult::setIndexedTagName($ret['examples'], 'example');
     }
     $ret['parameters'] = array();
     $params = $module->getFinalParams(ApiBase::GET_VALUES_FOR_HELP);
     $paramDesc = $module->getFinalParamDescription();
     foreach ($params as $name => $settings) {
         if (!is_array($settings)) {
             $settings = array(ApiBase::PARAM_DFLT => $settings);
         }
         $item = array('name' => $name);
         if (isset($paramDesc[$name])) {
             $this->formatHelpMessages($item, 'description', $paramDesc[$name], true);
         }
         $item['required'] = !empty($settings[ApiBase::PARAM_REQUIRED]);
         if (!empty($settings[ApiBase::PARAM_DEPRECATED])) {
             $item['deprecated'] = true;
         }
         if ($name === 'token' && $module->needsToken()) {
             $item['tokentype'] = $module->needsToken();
         }
         if (!isset($settings[ApiBase::PARAM_TYPE])) {
             $dflt = isset($settings[ApiBase::PARAM_DFLT]) ? $settings[ApiBase::PARAM_DFLT] : null;
             if (is_bool($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'boolean';
             } elseif (is_string($dflt) || is_null($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'string';
             } elseif (is_int($dflt)) {
                 $settings[ApiBase::PARAM_TYPE] = 'integer';
             }
         }
         if (isset($settings[ApiBase::PARAM_DFLT])) {
             switch ($settings[ApiBase::PARAM_TYPE]) {
                 case 'boolean':
                     $item['default'] = $settings[ApiBase::PARAM_DFLT] ? 'true' : 'false';
                     break;
                 case 'string':
                     $item['default'] = strval($settings[ApiBase::PARAM_DFLT]);
                     break;
                 case 'integer':
                     $item['default'] = intval($settings[ApiBase::PARAM_DFLT]);
                     break;
                 default:
                     $item['default'] = $settings[ApiBase::PARAM_DFLT];
                     break;
             }
         }
         $item['multi'] = !empty($settings[ApiBase::PARAM_ISMULTI]);
         if ($item['multi']) {
             $item['limit'] = $this->getMain()->canApiHighLimits() ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_SML1;
             $item['lowlimit'] = ApiBase::LIMIT_SML1;
             $item['highlimit'] = ApiBase::LIMIT_SML2;
         }
         if (!empty($settings[ApiBase::PARAM_ALLOW_DUPLICATES])) {
             $item['allowsduplicates'] = true;
         }
         if (isset($settings[ApiBase::PARAM_TYPE])) {
             if ($settings[ApiBase::PARAM_TYPE] === 'submodule') {
                 $item['type'] = $module->getModuleManager()->getNames($name);
                 sort($item['type']);
                 $item['submodules'] = true;
             } else {
                 $item['type'] = $settings[ApiBase::PARAM_TYPE];
             }
             if (is_array($item['type'])) {
                 // To prevent sparse arrays from being serialized to JSON as objects
                 $item['type'] = array_values($item['type']);
                 ApiResult::setIndexedTagName($item['type'], 't');
             }
         }
         if (isset($settings[ApiBase::PARAM_MAX])) {
             $item['max'] = $settings[ApiBase::PARAM_MAX];
         }
         if (isset($settings[ApiBase::PARAM_MAX2])) {
             $item['highmax'] = $settings[ApiBase::PARAM_MAX2];
         }
         if (isset($settings[ApiBase::PARAM_MIN])) {
             $item['min'] = $settings[ApiBase::PARAM_MIN];
         }
         if (!empty($settings[ApiBase::PARAM_HELP_MSG_INFO])) {
             $item['info'] = array();
             foreach ($settings[ApiBase::PARAM_HELP_MSG_INFO] as $i) {
                 $tag = array_shift($i);
                 $info = array('name' => $tag);
                 if (count($i)) {
                     $info['values'] = $i;
                     ApiResult::setIndexedTagName($info['values'], 'v');
                 }
                 $this->formatHelpMessages($info, 'text', array($this->context->msg("apihelp-{$path}-paraminfo-{$tag}")->numParams(count($i))->params($this->context->getLanguage()->commaList($i))->params($module->getModulePrefix())));
                 ApiResult::setSubelementsList($info, 'text');
                 $item['info'][] = $info;
             }
             ApiResult::setIndexedTagName($item['info'], 'i');
         }
         $ret['parameters'][] = $item;
     }
     ApiResult::setIndexedTagName($ret['parameters'], 'param');
     return $ret;
 }