/**
  * Check, if the user solved the captcha.
  *
  * Based on reference implementation:
  * https://github.com/google/recaptcha#php
  *
  * @return boolean
  */
 function passCaptcha()
 {
     global $wgRequest, $wgReCaptchaSecretKey, $wgReCaptchaSendRemoteIP;
     $url = 'https://www.google.com/recaptcha/api/siteverify';
     // Build data to append to request
     $data = array('secret' => $wgReCaptchaSecretKey, 'response' => $wgRequest->getVal('g-recaptcha-response'));
     if ($wgReCaptchaSendRemoteIP) {
         $data['remoteip'] = $wgRequest->getIP();
     }
     $url = wfAppendQuery($url, $data);
     $request = MWHttpRequest::factory($url, array('method' => 'GET'));
     $status = $request->execute();
     if (!$status->isOK()) {
         $this->error = 'http';
         $this->logStatusError($status);
         return false;
     }
     $response = FormatJson::decode($request->getContent(), true);
     if (!$response) {
         $this->error = 'json';
         $this->logStatusError($this->error);
         return false;
     }
     if (isset($response['error-codes'])) {
         $this->error = 'recaptcha-api';
         $this->logCheckError($response['error-codes']);
         return false;
     }
     return $response['success'];
 }
Esempio n. 2
0
 protected function fetchScriptList()
 {
     $data = array('action' => 'query', 'format' => 'php', 'list' => 'allpages', 'apnamespace' => '8', 'aplimit' => '500');
     $baseUrl = $this->getArg(0);
     $pages = array();
     do {
         $url = wfAppendQuery($baseUrl, $data);
         $strResult = Http::get($url);
         //$result = FormatJson::decode( $strResult ); // Still broken
         $result = unserialize($strResult);
         if (!empty($result['query']['allpages'])) {
             foreach ($result['query']['allpages'] as $page) {
                 if (substr($page['title'], -3) === '.js') {
                     strtok($page['title'], ':');
                     $pages[] = strtok('');
                 }
             }
         }
         if (!empty($result['query-continue'])) {
             $data['apfrom'] = $result['query-continue']['allpages']['apfrom'];
             $this->output("Fetching new batch from {$data['apfrom']}\n");
         }
     } while (isset($result['query-continue']));
     return $pages;
 }
 public function stage(GatewayType $adapter, $normalized, &$stagedData)
 {
     if ($adapter->isBatchProcessor()) {
         // Only makes sense for real users.
         return;
     }
     if (!empty($normalized['returnto'])) {
         $returnto = $normalized['returnto'];
     } else {
         $returnto = '';
     }
     if (isset($normalized['payment_method']) && $normalized['payment_method'] === 'cc') {
         // Add order ID to the returnto URL, only if it's not already there.
         //TODO: This needs to be more robust (like actually pulling the
         //qstring keys, resetting the values, and putting it all back)
         //but for now it'll keep us alive.
         if ($adapter->getOrderIDMeta('generate') && !empty($returnto) && !strpos($returnto, 'order_id')) {
             $queryArray = array('order_id' => $normalized['order_id']);
             $stagedData['returnto'] = wfAppendQuery($returnto, $queryArray);
         }
     } else {
         // FIXME: An empty returnto should be handled by the result switcher instead.
         $stagedData['returnto'] = ResultPages::getThankYouPage($adapter);
     }
 }
 /**
  * @param bool $rapidFail if true, render a form as a fail page rather than redirect
  * @param string $failPage either a wiki page title, or a URL to an external wiki
  *                         page title.
  * @param array $data information about the current request.
  *                    language, gateway, payment_method, and payment_submethod must be set
  * @param Psr\Log\LoggerInterface $logger
  * @return string full URL of the fail page, or just form name in case of rapidFail
  */
 private static function getFailPageFromParams($rapidFail, $failPage, $data, LoggerInterface $logger)
 {
     if (isset($data['language'])) {
         $language = $data['language'];
     } else {
         $language = WmfFramework::getLanguageCode();
     }
     // Prefer RapidFail.
     if ($rapidFail) {
         // choose which fail page to go for.
         try {
             $fail_ffname = GatewayFormChooser::getBestErrorForm($data['gateway'], $data['payment_method'], $data['payment_submethod']);
             return $fail_ffname;
         } catch (Exception $e) {
             $logger->error('Cannot determine best error form. ' . $e->getMessage());
         }
     }
     if (filter_var($failPage, FILTER_VALIDATE_URL)) {
         return self::appendLanguageAndMakeURL($failPage, $language);
     }
     // FIXME: either add Special:FailPage to avoid depending on wiki content,
     // or update the content on payments to be consistent with the /lang
     // format of ThankYou pages so we can use appendLanguageAndMakeURL here.
     $failTitle = Title::newFromText($failPage);
     $url = wfAppendQuery($failTitle->getFullURL(), array('uselang' => $language));
     return $url;
 }
 /**
  * Target URL for a link provided by a support button/aid.
  *
  * @param $title Title Title object for the translation message.
  * @since 2015.09
  */
 public static function getSupportUrl(Title $title)
 {
     global $wgTranslateSupportUrl, $wgTranslateSupportUrlNamespace;
     $namespace = $title->getNamespace();
     // Fetch the configuration for this namespace if possible, or the default.
     if (isset($wgTranslateSupportUrlNamespace[$namespace])) {
         $config = $wgTranslateSupportUrlNamespace[$namespace];
     } elseif ($wgTranslateSupportUrl) {
         $config = $wgTranslateSupportUrl;
     } else {
         throw new TranslationHelperException("Support page not configured");
     }
     // Preprocess params
     $params = array();
     if (isset($config['params'])) {
         foreach ($config['params'] as $key => $value) {
             $params[$key] = str_replace('%MESSAGE%', $title->getPrefixedText(), $value);
         }
     }
     // Return the URL or make one from the page
     if (isset($config['url'])) {
         return wfAppendQuery($config['url'], $params);
     } elseif (isset($config['page'])) {
         $page = Title::newFromText($config['page']);
         if (!$page) {
             throw new TranslationHelperException("Support page not configured properly");
         }
         return $page->getFullUrl($params);
     } else {
         throw new TranslationHelperException("Support page not configured properly");
     }
 }
Esempio n. 6
0
 protected function fetchScriptList()
 {
     $data = ['action' => 'query', 'format' => 'json', 'list' => 'allpages', 'apnamespace' => '8', 'aplimit' => '500', 'continue' => ''];
     $baseUrl = $this->getArg(0);
     $pages = [];
     while (true) {
         $url = wfAppendQuery($baseUrl, $data);
         $strResult = Http::get($url, [], __METHOD__);
         $result = FormatJson::decode($strResult, true);
         $page = null;
         foreach ($result['query']['allpages'] as $page) {
             if (substr($page['title'], -3) === '.js') {
                 strtok($page['title'], ':');
                 $pages[] = strtok('');
             }
         }
         if ($page !== null) {
             $this->output("Fetched list up to {$page['title']}\n");
         }
         if (isset($result['continue'])) {
             // >= 1.21
             $data = array_replace($data, $result['continue']);
         } elseif (isset($result['query-continue']['allpages'])) {
             // <= 1.20
             $data = array_replace($data, $result['query-continue']['allpages']);
         } else {
             break;
         }
     }
     return $pages;
 }
	public function execute( $par ) {
		global $wgOut, $wgRequest;
		global $wgVariablePagePossibilities;

		$lang = ( preg_match( '/^[A-Za-z-]+$/', $wgRequest->getVal( 'lang' ) ) )
				? $wgRequest->getVal( 'lang' )
				: 'en' ;
		$utm_source = $wgRequest->getVal( 'utm_source' );
		$utm_medium = $wgRequest->getVal( 'utm_medium' );
		$utm_campaign = $wgRequest->getVal( 'utm_campaign' );
		$referrer = ( $wgRequest->getVal( 'referrer' ))
				? $wgRequest->getVal( 'referrer' )
				: $wgRequest->getHeader( 'referer' );
	
		$query = array();
		if ( strlen( $lang ) ) $query[ 'language' ] = $lang;
		if ( strlen( $utm_source ) ) $query[ 'utm_source' ] = $utm_source;
		if ( strlen( $utm_medium ) ) $query[ 'utm_medium' ] = $utm_medium;
		if ( strlen( $utm_campaign ) ) $query[ 'utm_campaign' ] = $utm_campaign;
		if ( strlen( $referrer ) ) $query[ 'referrer' ] = $referrer;

		// determine the URL to which we will redirect the user
		$url = $this->determinePage( $wgVariablePagePossibilities );
		$wgOut->redirect( wfAppendQuery( $url, $query ) );
	}
Esempio n. 8
0
 public function execute()
 {
     global $wgUser, $wgArticleFeedbackRatingTypes, $wgArticleFeedbackSMaxage, $wgArticleFeedbackNamespaces;
     $params = $this->extractRequestParams();
     // Anon token check
     if ($wgUser->isAnon()) {
         if (!isset($params['anontoken'])) {
             $this->dieUsageMsg(array('missingparam', 'anontoken'));
         } elseif (strlen($params['anontoken']) != 32) {
             $this->dieUsage('The anontoken is not 32 characters', 'invalidtoken');
         }
         $token = $params['anontoken'];
     } else {
         $token = '';
     }
     // Load check, is this page ArticleFeedback-enabled ?
     // Keep in sync with ext.articleFeedback.startup.js
     $title = Title::newFromID($params['pageid']);
     if (is_null($title) || !in_array($title->getNamespace(), $wgArticleFeedbackNamespaces) || $title->isRedirect()) {
         // ...then error out
         $this->dieUsage('ArticleFeedback is not enabled on this page', 'invalidpage');
     }
     $dbw = wfGetDB(DB_MASTER);
     // Query the latest ratings by this user for this page,
     // possibly for an older revision
     // Select from the master to prevent replag-induced bugs
     $res = $dbw->select('article_feedback', array('aa_rating_id', 'aa_rating_value', 'aa_revision'), array('aa_user_text' => $wgUser->getName(), 'aa_page_id' => $params['pageid'], 'aa_rating_id' => array_keys($wgArticleFeedbackRatingTypes), 'aa_user_anon_token' => $token), __METHOD__, array('ORDER BY' => 'aa_revision DESC', 'LIMIT' => count($wgArticleFeedbackRatingTypes)));
     $lastRatings = array();
     foreach ($res as $row) {
         $lastRatings[$row->aa_rating_id]['value'] = $row->aa_rating_value;
         $lastRatings[$row->aa_rating_id]['revision'] = $row->aa_revision;
     }
     $pageId = $params['pageid'];
     $revisionId = $params['revid'];
     foreach ($wgArticleFeedbackRatingTypes as $ratingID => $unused) {
         $lastPageRating = false;
         $lastRevRating = false;
         if (isset($lastRatings[$ratingID])) {
             $lastPageRating = intval($lastRatings[$ratingID]['value']);
             if (intval($lastRatings[$ratingID]['revision']) == $revisionId) {
                 $lastRevRating = $lastPageRating;
             }
         }
         $thisRating = false;
         if (isset($params["r{$ratingID}"])) {
             $thisRating = intval($params["r{$ratingID}"]);
         }
         $this->insertRevisionRating($pageId, $revisionId, $ratingID, $thisRating - $lastRevRating, $thisRating, $lastRevRating);
         $this->insertPageRating($pageId, $ratingID, $thisRating - $lastPageRating, $thisRating, $lastPageRating);
         $this->insertUserRatings($pageId, $revisionId, $wgUser, $token, $ratingID, $thisRating, $params['bucket']);
     }
     $this->insertProperties($revisionId, $wgUser, $token, $params);
     $squidUpdate = new SquidUpdate(array(wfAppendQuery(wfScript('api'), array('action' => 'query', 'format' => 'json', 'list' => 'articlefeedback', 'afpageid' => $pageId, 'afanontoken' => '', 'afuserrating' => 0, 'maxage' => 0, 'smaxage' => $wgArticleFeedbackSMaxage))));
     $squidUpdate->doUpdate();
     wfRunHooks('ArticleFeedbackChangeRating', array($params));
     $r = array('result' => 'Success');
     $this->getResult()->addValue(null, $this->getModuleName(), $r);
 }
 /**
  * Get the API URL constructed from the domain template of sites
  */
 public static function getApiURL($language, $params = null)
 {
     global $wgContentTranslationSiteTemplates;
     $domain = self::getDomainCode($language);
     // $wgContentTranslationSiteTemplates['api'] is protocol relative path
     $url = 'https:' . str_replace('$1', $domain, $wgContentTranslationSiteTemplates['api']);
     $url = wfAppendQuery($url, $params);
     return $url;
 }
Esempio n. 10
0
 private function doRequest($apiUrl)
 {
     $params = array('action' => 'query', 'list' => 'allpages', 'apnamespace' => 120, 'aplimit' => 300, 'format' => 'json', 'rawcontinue' => 1);
     if (isset($this->continuation) && $this->continuation !== null) {
         $params['apfrom'] = $this->continuation;
     }
     $json = Http::get(wfAppendQuery($apiUrl, $params), array(), __METHOD__);
     return json_decode($json, true);
 }
Esempio n. 11
0
 private function doRequest(array $ids)
 {
     $params = array('action' => 'wbgetentities', 'ids' => implode('|', $ids), 'format' => 'json');
     $json = Http::get(wfAppendQuery($this->apiUrl, $params), array(), __METHOD__);
     $data = json_decode($json, true);
     if ($data) {
         return $data;
     }
     $this->logger->error('Failed to decode json api response');
 }
 /**
 	@brief Fetch the edit form and return the text in #wpTextbox1.
 	@param title The page to be opened for editing.
 */
 public function getPreloadedText($title)
 {
     $url = wfAppendQuery(wfScript('index'), array('title' => $title, 'action' => 'edit'));
     $this->loadFromURL($url);
     $elem = $this->getElementById('wpTextbox1');
     if (!$elem) {
         return null;
     }
     return trim($elem->textContent);
 }
Esempio n. 13
0
function wfCSSRender(&$parser, $css)
{
    global $wgCSSPath, $wgStylePath, $wgCSSIdentifier;
    $css = trim($css);
    $title = Title::newFromText($css);
    $rawProtection = "{$wgCSSIdentifier}=1";
    $headItem = '<!-- Begin Extension:CSS -->';
    if (is_object($title) && $title->exists()) {
        # Article actually in the db
        $params = "action=raw&ctype=text/css&{$rawProtection}";
        $url = $title->getLocalURL($params);
        $headItem .= HTML::linkedStyle($url);
    } elseif ($css[0] == '/') {
        # Regular file
        $base = $wgCSSPath === false ? $wgStylePath : $wgCSSPath;
        $url = wfAppendQuery($base . $css, $rawProtection);
        # Verify the expanded URL is still using the base URL
        if (strpos(wfExpandUrl($url), wfExpandUrl($base)) === 0) {
            $headItem .= HTML::linkedStyle($url);
        } else {
            $headItem .= '<!-- Invalid/malicious path  -->';
        }
    } else {
        # Inline CSS; use data URI to prevent injection.  JavaScript
        # will use a canary to verify load and will safely convert to
        # style tag if load fails.
        # Generate random CSS color that isn't black or white.
        $color = dechex(mt_rand(1, hexdec('fffffe')));
        $color = str_pad($color, 6, '0', STR_PAD_LEFT);
        # Prepend canary CSS to sanitized user CSS
        $canaryId = "{$wgCSSIdentifier}-canary-{$color}";
        $canaryCSS = "#{$canaryId}{background:#{$color} !important}";
        $css = $canaryCSS . Sanitizer::checkCss($css);
        # Encode data URI and append link tag
        $dataPrefix = 'data:text/css;charset=UTF-8;base64,';
        $url = $dataPrefix . base64_encode($css);
        $headItem .= HTML::linkedStyle($url);
        # Calculate URI prefix to match link tag
        $hrefPrefix = $dataPrefix . base64_encode('#' . $canaryId);
        $hrefPrefix = substr($url, 0, strlen($hrefPrefix));
        # Add JS to verify the link tag loaded and fallback if needed
        $parser->getOutput()->addModules('ext.CSS');
        $headItem .= HTML::inlineScript(<<<INLINESCRIPT
jQuery( function( \$ ) {
\t\$( 'link[href^="{$hrefPrefix}"]' )
\t\t.cssExtensionDataURIFallback( '{$canaryId}', '{$color}' );
} );
INLINESCRIPT
);
    }
    $headItem .= '<!-- End Extension:CSS -->';
    $parser->getOutput()->addHeadItem($headItem);
    return '';
}
 /**
  * Hook function called with &match=lang
  * Transform $text into a bilingual version
  * @param $out OutputPage
  * @param $text
  */
 function addMatchedText(&$out, &$text)
 {
     global $wgContLang, $wgContLanguageCode, $wgRequest, $wgLang, $wgMemc, $wgDoubleWikiCacheTime;
     $match_request = $wgRequest->getText('match');
     if ($match_request === '') {
         return true;
     }
     $this->addMatchingTags($text, $match_request);
     $langLinks = $out->getLanguageLinks();
     foreach ($langLinks as $l) {
         $nt = Title::newFromText($l);
         $iw = $nt->getInterwiki();
         if ($iw !== $match_request) {
             continue;
         }
         $key = wfMemcKey('doublewiki', $wgLang->getCode(), $nt->getPrefixedDbKey());
         $cachedText = $wgMemc->get($key);
         if ($cachedText) {
             $text = $cachedText;
         } else {
             $url = $nt->getCanonicalURL();
             $myURL = $out->getTitle()->getLocalURL();
             $languageName = $wgContLang->getLanguageName($iw);
             $myLanguage = $wgLang->getLanguageName($wgContLang->getCode());
             $translation = Http::get(wfAppendQuery($url, array('action' => 'render')));
             if ($translation !== null) {
                 break;
             }
             /**
              * first find all links that have no 'class' parameter.
              * these links are local so we add '?match=xx' to their url,
              * unless it already contains a '?'
              */
             $translation = preg_replace("/<a href=\"http:\\/\\/([^\"\\?]*)\"(([\\s]+)(c(?!lass=)|[^c\\>\\s])([^\\>\\s]*))*\\>/i", "<a href=\"http://\\1?match={$wgContLanguageCode}\"\\2>", $translation);
             // now add class='extiw' to these links
             $translation = preg_replace("/<a href=\"http:\\/\\/([^\"]*)\"(([\\s]+)(c(?!lass=)|[^c\\>\\s])([^\\>\\s]*))*\\>/i", "<a href=\"http://\\1\" class=\"extiw\"\\3>", $translation);
             // use class='extiw' for images too
             $translation = preg_replace("/<a href=\"http:\\/\\/([^\"]*)\"([^\\>]*)class=\"image\"([^\\>]*)\\>/i", "<a href=\"http://\\1\"\\2class=\"extiw\"\\3>", $translation);
             // add prefixes to internal links, in order to prevent duplicates
             $translation = preg_replace("/<a href=\"#(.*?)\"/i", "<a href=\"#l_\\1\"", $translation);
             $translation = preg_replace("/<li id=\"(.*?)\"/i", "<li id=\"l_\\1\"", $translation);
             $text = preg_replace("/<a href=\"#(.*?)\"/i", "<a href=\"#r_\\1\"", $text);
             $text = preg_replace("/<li id=\"(.*?)\"/i", "<li id=\"r_\\1\"", $text);
             // add ?match= to local links of the local wiki
             $text = preg_replace("/<a href=\"\\/([^\"\\?]*)\"/i", "<a href=\"/\\1?match={$match_request}\"", $text);
             // do the job
             $text = $this->matchColumns($text, $myLanguage, $myURL, $wgContLanguageCode, $translation, $languageName, $url, $match_request);
             $wgMemc->set($key, $text, $wgDoubleWikiCacheTime);
         }
         break;
     }
     return true;
 }
	/**
	 * Purpose: Add custom tabs
	 *
	 * When editing in read-only data-set, if you have the copy permission, you can
	 * make a copy into the designated community dataset and edit the data there.
	 * This is accessible through an 'edit copy' tab which is added below.
	 *
	 * @param $skin Skin as passed by MW
	 * @param $tabs as passed by MW
	 */
	public static function onSkinTemplateTabs( $skin, $content_actions ) {
		global $wgUser, $wgCommunity_dc, $wdShowEditCopy, $wdHandlerClasses;

		$title = $skin->getTitle();

		if ( !self::isWikidataNs( $title ) ) {
			return true;
		}

		$ns = $title->getNamespace();
		$editChanged = false;
		$dc = wdGetDataSetContext();

		if ( $wdHandlerClasses[ $ns ] == 'DefinedMeaning' ) {

			# Hackishly determine which DMID we're on by looking at the page title component
			$tt = $title->getText();
			$rpos1 = strrpos( $tt, '(' );
			$rpos2 = strrpos( $tt, ')' );
			$dmid = ( $rpos1 && $rpos2 ) ? substr( $tt, $rpos1 + 1, $rpos2 - $rpos1 - 1 ) : 0;
			if ( $dmid ) {
				$copyTitle = SpecialPage::getTitleFor( 'Copy' );
				if ( $dc != $wgCommunity_dc && $wdShowEditCopy ) {
					$editChanged = true;
					$content_actions['edit'] = array(
						'class' => false,
						'text' => wfMsg( 'ow_nstab_edit_copy' ),
						'href' => $copyTitle->getLocalUrl( "action=copy&dmid=$dmid&dc1=$dc&dc2=$wgCommunity_dc" )
					);
				}
				$content_actions['nstab-definedmeaning'] = array(
					 'class' => 'selected',
					 'text' => wfMsg( 'ow_nstab_definedmeaning' ),
					 'href' => $title->getLocalUrl( "dataset=$dc" )
				);
			}
		}

		// Prevent move tab being shown.
		unset( $content_actions['move'] );

		// Add context dataset (old hooks 'GetEditLinkTrail' and 'GetHistoryLinkTrail')
		if ( !$editChanged && $content_actions['edit'] != null ) {
			$content_actions['edit']['href'] = wfAppendQuery( $content_actions['edit']['href'], "dataset=$dc" );
		}

		$content_actions['history']['href'] = wfAppendQuery( $content_actions['history']['href'], "dataset=$dc" );

		return true;
	}
Esempio n. 16
0
 protected function requestParsoid($method, $title, $params)
 {
     global $wgVisualEditorParsoidURL, $wgVisualEditorParsoidTimeout, $wgVisualEditorParsoidForwardCookies;
     $url = $wgVisualEditorParsoidURL . '/' . urlencode($this->getApiSource()) . '/' . urlencode($title->getPrefixedDBkey());
     $data = array_merge($this->getProxyConf(), array('method' => $method, 'timeout' => $wgVisualEditorParsoidTimeout));
     if ($method === 'POST') {
         $data['postData'] = $params;
     } else {
         $url = wfAppendQuery($url, $params);
     }
     $req = MWHttpRequest::factory($url, $data);
     // Forward cookies, but only if configured to do so and if there are read restrictions
     if ($wgVisualEditorParsoidForwardCookies && !User::isEveryoneAllowed('read')) {
         $req->setHeader('Cookie', $this->getRequest()->getHeader('Cookie'));
     }
     $status = $req->execute();
     if ($status->isOK()) {
         // Pass thru performance data from Parsoid to the client, unless the response was
         // served directly from Varnish, in  which case discard the value of the XPP header
         // and use it to declare the cache hit instead.
         $xCache = $req->getResponseHeader('X-Cache');
         if (is_string($xCache) && strpos(strtolower($xCache), 'hit') !== false) {
             $xpp = 'cached-response=true';
             $hit = true;
         } else {
             $xpp = $req->getResponseHeader('X-Parsoid-Performance');
             $hit = false;
         }
         WikiaLogger::instance()->debug('ApiVisualEditor', array('hit' => $hit, 'method' => $method, 'url' => $url));
         if ($xpp !== null) {
             $resp = $this->getRequest()->response();
             $resp->header('X-Parsoid-Performance: ' . $xpp);
         }
     } elseif ($status->isGood()) {
         $this->dieUsage($req->getContent(), 'parsoidserver-http-' . $req->getStatus());
     } elseif ($errors = $status->getErrorsByType('error')) {
         $error = $errors[0];
         $code = $error['message'];
         if (count($error['params'])) {
             $message = $error['params'][0];
         } else {
             $message = 'MWHttpRequest error';
         }
         $this->dieUsage($message, 'parsoidserver-' . $code);
     }
     // TODO pass through X-Parsoid-Performance header, merge with getHTML above
     return $req->getContent();
 }
 /**
  * Main execution point
  *
  * @param string $subpage
  */
 public function execute($subpage)
 {
     // Backwards-compatibility: redirect to new feed URLs
     $feedFormat = $this->getRequest()->getVal('feed');
     if (!$this->including() && $feedFormat) {
         $query = $this->getFeedQuery();
         $query['feedformat'] = $feedFormat === 'atom' ? 'atom' : 'rss';
         $this->getOutput()->redirect(wfAppendQuery(wfScript('api'), $query));
         return;
     }
     // 10 seconds server-side caching max
     $this->getOutput()->setSquidMaxage(10);
     // Check if the client has a cached version
     $lastmod = $this->checkLastModified();
     if ($lastmod === false) {
         return;
     }
     parent::execute($subpage);
 }
 public function execute($par)
 {
     $redirect = $this->getRedirect($par);
     $query = $this->getRedirectQuery();
     // Redirect to a page title with possible query parameters
     if ($redirect instanceof Title) {
         $url = $redirect->getFullURL($query);
         $this->getOutput()->redirect($url);
         return $redirect;
     } elseif ($redirect === true) {
         // Redirect to index.php with query parameters
         $url = wfAppendQuery(wfScript('index'), $query);
         $this->getOutput()->redirect($url);
         return $redirect;
     } else {
         $class = get_class($this);
         throw new MWException("RedirectSpecialPage {$class} doesn't redirect!");
     }
 }
Esempio n. 19
0
 /**
  * Main execution point
  *
  * @param string $subpage
  */
 public function execute($subpage)
 {
     // Backwards-compatibility: redirect to new feed URLs
     $feedFormat = $this->getRequest()->getVal('feed');
     if (!$this->including() && $feedFormat) {
         $query = $this->getFeedQuery();
         $query['feedformat'] = $feedFormat === 'atom' ? 'atom' : 'rss';
         $this->getOutput()->redirect(wfAppendQuery(wfScript('api'), $query));
         return;
     }
     // 10 seconds server-side caching max
     $this->getOutput()->setCdnMaxage(10);
     // Check if the client has a cached version
     $lastmod = $this->checkLastModified();
     if ($lastmod === false) {
         return;
     }
     $this->addHelpLink('//meta.wikimedia.org/wiki/Special:MyLanguage/Help:Recent_changes', true);
     parent::execute($subpage);
 }
 /**
  * Returns the normalized form of the given page title, using the
  * normalization rules of the given site. If the given title is a redirect,
  * the redirect weill be resolved and the redirect target is returned.
  *
  * @note This actually makes an API request to the remote site, so beware
  *   that this function is slow and depends on an external service.
  *
  * @see Site::normalizePageName
  *
  * @since 1.27
  *
  * @param string $pageName
  * @param string $apiUrl
  *
  * @return string
  * @throws \MWException
  */
 public function normalizePageName($pageName, $apiUrl)
 {
     // Check if we have strings as arguments.
     if (!is_string($pageName)) {
         throw new \MWException('$pageName must be a string');
     }
     // Go on call the external site
     // Make sure the string is normalized into NFC (due to T42017)
     // but do nothing to the whitespaces, that should work appropriately.
     // @see https://phabricator.wikimedia.org/T42017
     $pageName = Validator::cleanUp($pageName);
     // Build the args for the specific call
     $args = ['action' => 'query', 'prop' => 'info', 'redirects' => true, 'converttitles' => true, 'format' => 'json', 'titles' => $pageName];
     $url = wfAppendQuery($apiUrl, $args);
     // Go on call the external site
     // @todo we need a good way to specify a timeout here.
     $ret = $this->http->get($url, [], __METHOD__);
     if ($ret === false) {
         wfDebugLog("MediaWikiSite", "call to external site failed: {$url}");
         return false;
     }
     $data = FormatJson::decode($ret, true);
     if (!is_array($data)) {
         wfDebugLog("MediaWikiSite", "call to <{$url}> returned bad json: " . $ret);
         return false;
     }
     $page = static::extractPageRecord($data, $pageName);
     if (isset($page['missing'])) {
         wfDebugLog("MediaWikiSite", "call to <{$url}> returned a marker for a missing page title! " . $ret);
         return false;
     }
     if (isset($page['invalid'])) {
         wfDebugLog("MediaWikiSite", "call to <{$url}> returned a marker for an invalid page title! " . $ret);
         return false;
     }
     if (!isset($page['title'])) {
         wfDebugLog("MediaWikiSite", "call to <{$url}> did not return a page title! " . $ret);
         return false;
     }
     return $page['title'];
 }
 /**
  * Some extra tabs for editing
  * @param &$sktemplate SkinTemplate
  * @param &$links array
  * @return bool
  */
 public static function onSkinTemplateNavigation(&$sktemplate, &$links)
 {
     $title = $sktemplate->getTitle();
     $request = $sktemplate->getRequest();
     if (isset($links['views']['edit'])) {
         if ($title->hasContentModel('CollaborationListContent') || $title->hasContentModel('CollaborationHubContent')) {
             // Edit as JSON
             $active = in_array($request->getVal('action'), ['edit', 'submit']) && $request->getVal('format') === 'application/json';
             $links['actions']['editasjson'] = ['class' => $active ? 'selected' : false, 'href' => wfAppendQuery($links['views']['edit']['href'], ['format' => 'application/json']), 'text' => wfMessage('collaborationkit-editjsontab')->text()];
             if ($active) {
                 // Make it not be selected when editing json.
                 $links['views']['edit']['class'] = false;
             }
         }
         if ($title->hasContentModel('CollaborationHubContent')) {
             // Add feature
             $links['actions']['addnewfeature'] = ['class' => '', 'href' => SpecialPage::getTitleFor('CreateHubFeature')->getFullUrl(['collaborationhub' => $title->getFullText()]), 'text' => wfMessage('collaborationkit-hub-addpage')->text()];
         }
     }
     return true;
 }
 /**
  * <inputbox type=create...> sends requests with action=edit, and 
  * possibly a &prefix=Foo.  So we pick that up here, munge prefix 
  * and title together, and redirect back out to the real page
  * @param $output OutputPage
  * @param $article Article
  * @param $title Title
  * @param $user User
  * @param $request WebRequest 
  * @param $wiki MediaWiki
  * @return bool
  */
 public static function onMediaWikiPerformAction($output, $article, $title, $user, $request, $wiki)
 {
     if ($wiki->getAction($request) !== 'edit') {
         # not our problem
         return true;
     }
     if ($request->getText('prefix', '') === '') {
         # Fine
         return true;
     }
     $params = $request->getValues();
     $title = $params['prefix'];
     if (isset($params['title'])) {
         $title .= $params['title'];
     }
     unset($params['prefix']);
     $params['title'] = $title;
     global $wgScript;
     $output->redirect(wfAppendQuery($wgScript, $params), '301');
     return false;
 }
Esempio n. 23
0
 public function execute($par)
 {
     if (empty($par)) {
         $par = 'main';
     }
     // These come from transclusions
     $request = $this->getRequest();
     $options = ['action' => 'help', 'nolead' => true, 'submodules' => $request->getCheck('submodules'), 'recursivesubmodules' => $request->getCheck('recursivesubmodules'), 'title' => $request->getVal('title', $this->getPageTitle('$1')->getPrefixedText())];
     // These are for linking from wikitext, since url parameters are a pain
     // to do.
     while (true) {
         if (substr($par, 0, 4) === 'sub/') {
             $par = substr($par, 4);
             $options['submodules'] = 1;
             continue;
         }
         if (substr($par, 0, 5) === 'rsub/') {
             $par = substr($par, 5);
             $options['recursivesubmodules'] = 1;
             continue;
         }
         $moduleName = $par;
         break;
     }
     if (!$this->including()) {
         unset($options['nolead'], $options['title']);
         $options['modules'] = $moduleName;
         $link = wfAppendQuery(wfExpandUrl(wfScript('api'), PROTO_CURRENT), $options);
         $this->getOutput()->redirect($link);
         return;
     }
     $main = new ApiMain($this->getContext(), false);
     try {
         $module = $main->getModuleFromPath($moduleName);
     } catch (UsageException $ex) {
         $this->getOutput()->addHTML(Html::rawElement('span', ['class' => 'error'], $this->msg('apihelp-no-such-module', $moduleName)->inContentLanguage()->parse()));
         return;
     }
     ApiHelp::getHelp($this->getContext(), $module, $options);
 }
Esempio n. 24
0
 /**
  * Handle Special:Redirect/logid/xxx
  * (by redirecting to index.php?title=Special:Log)
  *
  * @since 1.27
  * @return string|null Url to redirect to, or null if $mValue is invalid.
  */
 function dispatchLog()
 {
     $logid = $this->mValue;
     if (!ctype_digit($logid)) {
         return null;
     }
     $logid = (int) $logid;
     if ($logid === 0) {
         return null;
     }
     $logparams = ['log_id', 'log_timestamp', 'log_type', 'log_user_text'];
     $dbr = wfGetDB(DB_REPLICA);
     // Gets the nested SQL statement which
     // returns timestamp of the log with the given log ID
     $inner = $dbr->selectSQLText('logging', ['log_timestamp'], ['log_id' => $logid]);
     // Returns all fields mentioned in $logparams of the logs
     // with the same timestamp as the one returned by the statement above
     $logsSameTimestamps = $dbr->select('logging', $logparams, ["log_timestamp = ({$inner})"]);
     if ($logsSameTimestamps->numRows() === 0) {
         return null;
     }
     // Stores the row with the same log ID as the one given
     $rowMain = [];
     foreach ($logsSameTimestamps as $row) {
         if ((int) $row->log_id === $logid) {
             $rowMain = $row;
         }
     }
     array_shift($logparams);
     // Stores all the rows with the same values in each column
     // as $rowMain
     foreach ($logparams as $cond) {
         $matchedRows = [];
         foreach ($logsSameTimestamps as $row) {
             if ($row->{$cond} === $rowMain->{$cond}) {
                 $matchedRows[] = $row;
             }
         }
         if (count($matchedRows) === 1) {
             break;
         }
         $logsSameTimestamps = $matchedRows;
     }
     $query = ['title' => 'Special:Log', 'limit' => count($matchedRows)];
     // A map of database field names from table 'logging' to the values of $logparams
     $keys = ['log_timestamp' => 'offset', 'log_type' => 'type', 'log_user_text' => 'user'];
     foreach ($logparams as $logKey) {
         $query[$keys[$logKey]] = $matchedRows[0]->{$logKey};
     }
     $query['offset'] = $query['offset'] + 1;
     $url = $query;
     return wfAppendQuery(wfScript('index'), $url);
 }
Esempio n. 25
0
 /**
  * @return string
  */
 function getTransformScript()
 {
     if (!isset($this->transformScript)) {
         $this->transformScript = false;
         if ($this->repo) {
             $script = $this->repo->getThumbScriptUrl();
             if ($script) {
                 $this->transformScript = wfAppendQuery($script, array('f' => $this->getName()));
             }
         }
     }
     return $this->transformScript;
 }
Esempio n. 26
0
 /**
  * @return array Array in format "link name or number => 'link html'".
  */
 public function getHeadLinksArray()
 {
     global $wgVersion;
     $tags = array();
     $config = $this->getConfig();
     $canonicalUrl = $this->mCanonicalUrl;
     $tags['meta-generator'] = Html::element('meta', array('name' => 'generator', 'content' => "MediaWiki {$wgVersion}"));
     if ($config->get('ReferrerPolicy') !== false) {
         $tags['meta-referrer'] = Html::element('meta', array('name' => 'referrer', 'content' => $config->get('ReferrerPolicy')));
     }
     $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
     if ($p !== 'index,follow') {
         // http://www.robotstxt.org/wc/meta-user.html
         // Only show if it's different from the default robots policy
         $tags['meta-robots'] = Html::element('meta', array('name' => 'robots', 'content' => $p));
     }
     foreach ($this->mMetatags as $tag) {
         if (0 == strcasecmp('http:', substr($tag[0], 0, 5))) {
             $a = 'http-equiv';
             $tag[0] = substr($tag[0], 5);
         } else {
             $a = 'name';
         }
         $tagName = "meta-{$tag[0]}";
         if (isset($tags[$tagName])) {
             $tagName .= $tag[1];
         }
         $tags[$tagName] = Html::element('meta', array($a => $tag[0], 'content' => $tag[1]));
     }
     foreach ($this->mLinktags as $tag) {
         $tags[] = Html::element('link', $tag);
     }
     # Universal edit button
     if ($config->get('UniversalEditButton') && $this->isArticleRelated()) {
         $user = $this->getUser();
         if ($this->getTitle()->quickUserCan('edit', $user) && ($this->getTitle()->exists() || $this->getTitle()->quickUserCan('create', $user))) {
             // Original UniversalEditButton
             $msg = $this->msg('edit')->text();
             $tags['universal-edit-button'] = Html::element('link', array('rel' => 'alternate', 'type' => 'application/x-wiki', 'title' => $msg, 'href' => $this->getTitle()->getEditURL()));
             // Alternate edit link
             $tags['alternative-edit'] = Html::element('link', array('rel' => 'edit', 'title' => $msg, 'href' => $this->getTitle()->getEditURL()));
         }
     }
     # Generally the order of the favicon and apple-touch-icon links
     # should not matter, but Konqueror (3.5.9 at least) incorrectly
     # uses whichever one appears later in the HTML source. Make sure
     # apple-touch-icon is specified first to avoid this.
     if ($config->get('AppleTouchIcon') !== false) {
         $tags['apple-touch-icon'] = Html::element('link', array('rel' => 'apple-touch-icon', 'href' => $config->get('AppleTouchIcon')));
     }
     if ($config->get('Favicon') !== false) {
         $tags['favicon'] = Html::element('link', array('rel' => 'shortcut icon', 'href' => $config->get('Favicon')));
     }
     # OpenSearch description link
     $tags['opensearch'] = Html::element('link', array('rel' => 'search', 'type' => 'application/opensearchdescription+xml', 'href' => wfScript('opensearch_desc'), 'title' => $this->msg('opensearch-desc')->inContentLanguage()->text()));
     if ($config->get('EnableAPI')) {
         # Real Simple Discovery link, provides auto-discovery information
         # for the MediaWiki API (and potentially additional custom API
         # support such as WordPress or Twitter-compatible APIs for a
         # blogging extension, etc)
         $tags['rsd'] = Html::element('link', array('rel' => 'EditURI', 'type' => 'application/rsd+xml', 'href' => wfExpandUrl(wfAppendQuery(wfScript('api'), array('action' => 'rsd')), PROTO_RELATIVE)));
     }
     # Language variants
     if (!$config->get('DisableLangConversion')) {
         $lang = $this->getTitle()->getPageLanguage();
         if ($lang->hasVariants()) {
             $variants = $lang->getVariants();
             foreach ($variants as $_v) {
                 $tags["variant-{$_v}"] = Html::element('link', array('rel' => 'alternate', 'hreflang' => wfBCP47($_v), 'href' => $this->getTitle()->getLocalURL(array('variant' => $_v))));
             }
         }
         # x-default link per https://support.google.com/webmasters/answer/189077?hl=en
         $tags["variant-x-default"] = Html::element('link', array('rel' => 'alternate', 'hreflang' => 'x-default', 'href' => $this->getTitle()->getLocalURL()));
     }
     # Copyright
     if ($this->copyrightUrl !== null) {
         $copyright = $this->copyrightUrl;
     } else {
         $copyright = '';
         if ($config->get('RightsPage')) {
             $copy = Title::newFromText($config->get('RightsPage'));
             if ($copy) {
                 $copyright = $copy->getLocalURL();
             }
         }
         if (!$copyright && $config->get('RightsUrl')) {
             $copyright = $config->get('RightsUrl');
         }
     }
     if ($copyright) {
         $tags['copyright'] = Html::element('link', array('rel' => 'copyright', 'href' => $copyright));
     }
     # Feeds
     if ($config->get('Feed')) {
         foreach ($this->getSyndicationLinks() as $format => $link) {
             # Use the page name for the title.  In principle, this could
             # lead to issues with having the same name for different feeds
             # corresponding to the same page, but we can't avoid that at
             # this low a level.
             $tags[] = $this->feedLink($format, $link, $this->msg("page-{$format}-feed", $this->getTitle()->getPrefixedText())->text());
         }
         # Recent changes feed should appear on every page (except recentchanges,
         # that would be redundant). Put it after the per-page feed to avoid
         # changing existing behavior. It's still available, probably via a
         # menu in your browser. Some sites might have a different feed they'd
         # like to promote instead of the RC feed (maybe like a "Recent New Articles"
         # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
         # If so, use it instead.
         $sitename = $config->get('Sitename');
         if ($config->get('OverrideSiteFeed')) {
             foreach ($config->get('OverrideSiteFeed') as $type => $feedUrl) {
                 // Note, this->feedLink escapes the url.
                 $tags[] = $this->feedLink($type, $feedUrl, $this->msg("site-{$type}-feed", $sitename)->text());
             }
         } elseif (!$this->getTitle()->isSpecial('Recentchanges')) {
             $rctitle = SpecialPage::getTitleFor('Recentchanges');
             foreach ($config->get('AdvertisedFeedTypes') as $format) {
                 $tags[] = $this->feedLink($format, $rctitle->getLocalURL(array('feed' => $format)), $this->msg("site-{$format}-feed", $sitename)->text());
             }
         }
     }
     # Canonical URL
     if ($config->get('EnableCanonicalServerLink')) {
         if ($canonicalUrl !== false) {
             $canonicalUrl = wfExpandUrl($canonicalUrl, PROTO_CANONICAL);
         } else {
             if ($this->isArticleRelated()) {
                 // This affects all requests where "setArticleRelated" is true. This is
                 // typically all requests that show content (query title, curid, oldid, diff),
                 // and all wikipage actions (edit, delete, purge, info, history etc.).
                 // It does not apply to File pages and Special pages.
                 // 'history' and 'info' actions address page metadata rather than the page
                 // content itself, so they may not be canonicalized to the view page url.
                 // TODO: this ought to be better encapsulated in the Action class.
                 $action = Action::getActionName($this->getContext());
                 if (in_array($action, array('history', 'info'))) {
                     $query = "action={$action}";
                 } else {
                     $query = '';
                 }
                 $canonicalUrl = $this->getTitle()->getCanonicalURL($query);
             } else {
                 $reqUrl = $this->getRequest()->getRequestURL();
                 $canonicalUrl = wfExpandUrl($reqUrl, PROTO_CANONICAL);
             }
         }
     }
     if ($canonicalUrl !== false) {
         $tags[] = Html::element('link', array('rel' => 'canonical', 'href' => $canonicalUrl));
     }
     return $tags;
 }
    /**
     * Prepares links used in the mobile footer
     * @param QuickTemplate $tpl
     */
    protected function prepareMobileFooterLinks($tpl)
    {
        $req = $this->getRequest();
        $url = $this->getOutput()->getProperty('desktopUrl');
        if ($url) {
            $url = wfAppendQuery($url, 'mobileaction=toggle_view_desktop');
        } else {
            $url = $this->getTitle()->getLocalUrl($req->appendQueryValue('mobileaction', 'toggle_view_desktop', true));
        }
        $url = htmlspecialchars($this->mobileContext->getDesktopUrl(wfExpandUrl($url, PROTO_RELATIVE)));
        $desktop = wfMessage('mobile-frontend-view-desktop')->escaped();
        $mobile = wfMessage('mobile-frontend-view-mobile')->escaped();
        $switcherHtml = <<<HTML
<h2>{$this->getSitename(true)}</h2>
<ul>
\t<li>{$mobile}</li><li><a id="mw-mf-display-toggle" href="{$url}">{$desktop}</a></li>
</ul>
HTML;
        // Generate the licensing text displayed in the footer of each page.
        // See Skin::getCopyright for desktop equivalent.
        $license = self::getLicense('footer');
        if (isset($license['link']) && $license['link']) {
            $licenseText = $this->msg('mobile-frontend-copyright')->rawParams($license['link'])->text();
        } else {
            $licenseText = '';
        }
        // Enable extensions to add links to footer in Mobile view, too - bug 66350
        Hooks::run('SkinMinervaOutputPageBeforeExec', array(&$this, &$tpl));
        $tpl->set('mobile-switcher', $switcherHtml);
        $tpl->set('mobile-license', $licenseText);
        $tpl->set('privacy', $this->footerLink('mobile-frontend-privacy-link-text', 'privacypage'));
        $tpl->set('terms-use', $this->getTermsLink());
    }
Esempio n. 28
0
 /**
  * Recursively-called function to actually construct the help
  *
  * @param IContextSource $context
  * @param ApiBase[] $modules
  * @param array $options
  * @param array &$haveModules
  * @return string
  */
 private static function getHelpInternal(IContextSource $context, array $modules, array $options, &$haveModules)
 {
     $out = '';
     $level = empty($options['headerlevel']) ? 2 : $options['headerlevel'];
     if (empty($options['tocnumber'])) {
         $tocnumber = array(2 => 0);
     } else {
         $tocnumber =& $options['tocnumber'];
     }
     foreach ($modules as $module) {
         $tocnumber[$level]++;
         $path = $module->getModulePath();
         $module->setContext($context);
         $help = array('header' => '', 'flags' => '', 'description' => '', 'help-urls' => '', 'parameters' => '', 'examples' => '', 'submodules' => '');
         if (empty($options['noheader']) || !empty($options['toc'])) {
             $anchor = $path;
             $i = 1;
             while (isset($haveModules[$anchor])) {
                 $anchor = $path . '|' . ++$i;
             }
             if ($module->isMain()) {
                 $header = $context->msg('api-help-main-header')->parse();
             } else {
                 $name = $module->getModuleName();
                 $header = $module->getParent()->getModuleManager()->getModuleGroup($name) . "={$name}";
                 if ($module->getModulePrefix() !== '') {
                     $header .= ' ' . $context->msg('parentheses', $module->getModulePrefix())->parse();
                 }
             }
             $haveModules[$anchor] = array('toclevel' => count($tocnumber), 'level' => $level, 'anchor' => $anchor, 'line' => $header, 'number' => join('.', $tocnumber), 'index' => false);
             if (empty($options['noheader'])) {
                 $help['header'] .= Html::element('h' . min(6, $level), array('id' => $anchor, 'class' => 'apihelp-header'), $header);
             }
         } else {
             $haveModules[$path] = true;
         }
         $links = array();
         $any = false;
         for ($m = $module; $m !== null; $m = $m->getParent()) {
             $name = $m->getModuleName();
             if ($name === 'main_int') {
                 $name = 'main';
             }
             if (count($modules) === 1 && $m === $modules[0] && !(!empty($options['submodules']) && $m->getModuleManager())) {
                 $link = Html::element('b', null, $name);
             } else {
                 $link = SpecialPage::getTitleFor('ApiHelp', $m->getModulePath())->getLocalURL();
                 $link = Html::element('a', array('href' => $link, 'class' => 'apihelp-linktrail'), $name);
                 $any = true;
             }
             array_unshift($links, $link);
         }
         if ($any) {
             $help['header'] .= self::wrap($context->msg('parentheses')->rawParams($context->getLanguage()->pipeList($links)), 'apihelp-linktrail', 'div');
         }
         $flags = $module->getHelpFlags();
         $help['flags'] .= Html::openElement('div', array('class' => 'apihelp-block apihelp-flags'));
         $msg = $context->msg('api-help-flags');
         if (!$msg->isDisabled()) {
             $help['flags'] .= self::wrap($msg->numParams(count($flags)), 'apihelp-block-head', 'div');
         }
         $help['flags'] .= Html::openElement('ul');
         foreach ($flags as $flag) {
             $help['flags'] .= Html::rawElement('li', null, self::wrap($context->msg("api-help-flag-{$flag}"), "apihelp-flag-{$flag}"));
         }
         $sourceInfo = $module->getModuleSourceInfo();
         if ($sourceInfo) {
             if (isset($sourceInfo['namemsg'])) {
                 $extname = $context->msg($sourceInfo['namemsg'])->text();
             } else {
                 $extname = $sourceInfo['name'];
             }
             $help['flags'] .= Html::rawElement('li', null, self::wrap($context->msg('api-help-source', $extname, $sourceInfo['name']), 'apihelp-source'));
             $link = SpecialPage::getTitleFor('Version', 'License/' . $sourceInfo['name']);
             if (isset($sourceInfo['license-name'])) {
                 $msg = $context->msg('api-help-license', $link, $sourceInfo['license-name']);
             } elseif (SpecialVersion::getExtLicenseFileName(dirname($sourceInfo['path']))) {
                 $msg = $context->msg('api-help-license-noname', $link);
             } else {
                 $msg = $context->msg('api-help-license-unknown');
             }
             $help['flags'] .= Html::rawElement('li', null, self::wrap($msg, 'apihelp-license'));
         } else {
             $help['flags'] .= Html::rawElement('li', null, self::wrap($context->msg('api-help-source-unknown'), 'apihelp-source'));
             $help['flags'] .= Html::rawElement('li', null, self::wrap($context->msg('api-help-license-unknown'), 'apihelp-license'));
         }
         $help['flags'] .= Html::closeElement('ul');
         $help['flags'] .= Html::closeElement('div');
         foreach ($module->getFinalDescription() as $msg) {
             $msg->setContext($context);
             $help['description'] .= $msg->parseAsBlock();
         }
         $urls = $module->getHelpUrls();
         if ($urls) {
             $help['help-urls'] .= Html::openElement('div', array('class' => 'apihelp-block apihelp-help-urls'));
             $msg = $context->msg('api-help-help-urls');
             if (!$msg->isDisabled()) {
                 $help['help-urls'] .= self::wrap($msg->numParams(count($urls)), 'apihelp-block-head', 'div');
             }
             if (!is_array($urls)) {
                 $urls = array($urls);
             }
             $help['help-urls'] .= Html::openElement('ul');
             foreach ($urls as $url) {
                 $help['help-urls'] .= Html::rawElement('li', null, Html::element('a', array('href' => $url), $url));
             }
             $help['help-urls'] .= Html::closeElement('ul');
             $help['help-urls'] .= Html::closeElement('div');
         }
         $params = $module->getFinalParams(ApiBase::GET_VALUES_FOR_HELP);
         $dynamicParams = $module->dynamicParameterDocumentation();
         $groups = array();
         if ($params || $dynamicParams !== null) {
             $help['parameters'] .= Html::openElement('div', array('class' => 'apihelp-block apihelp-parameters'));
             $msg = $context->msg('api-help-parameters');
             if (!$msg->isDisabled()) {
                 $help['parameters'] .= self::wrap($msg->numParams(count($params)), 'apihelp-block-head', 'div');
             }
             $help['parameters'] .= Html::openElement('dl');
             $descriptions = $module->getFinalParamDescription();
             foreach ($params as $name => $settings) {
                 if (!is_array($settings)) {
                     $settings = array(ApiBase::PARAM_DFLT => $settings);
                 }
                 $help['parameters'] .= Html::element('dt', null, $module->encodeParamName($name));
                 // Add description
                 $description = array();
                 if (isset($descriptions[$name])) {
                     foreach ($descriptions[$name] as $msg) {
                         $msg->setContext($context);
                         $description[] = $msg->parseAsBlock();
                     }
                 }
                 // Add usage info
                 $info = array();
                 // Required?
                 if (!empty($settings[ApiBase::PARAM_REQUIRED])) {
                     $info[] = $context->msg('api-help-param-required')->parse();
                 }
                 // Custom info?
                 if (!empty($settings[ApiBase::PARAM_HELP_MSG_INFO])) {
                     foreach ($settings[ApiBase::PARAM_HELP_MSG_INFO] as $i) {
                         $tag = array_shift($i);
                         $info[] = $context->msg("apihelp-{$path}-paraminfo-{$tag}")->numParams(count($i))->params($context->getLanguage()->commaList($i))->params($module->getModulePrefix())->parse();
                     }
                 }
                 // Type documentation
                 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_TYPE])) {
                     $type = $settings[ApiBase::PARAM_TYPE];
                     $multi = !empty($settings[ApiBase::PARAM_ISMULTI]);
                     $hintPipeSeparated = true;
                     $count = ApiBase::LIMIT_SML2 + 1;
                     if (is_array($type)) {
                         $count = count($type);
                         $links = isset($settings[ApiBase::PARAM_VALUE_LINKS]) ? $settings[ApiBase::PARAM_VALUE_LINKS] : array();
                         $type = array_map(function ($v) use($links) {
                             $ret = wfEscapeWikiText($v);
                             if (isset($links[$v])) {
                                 $ret = "[[{$links[$v]}|{$ret}]]";
                             }
                             return $ret;
                         }, $type);
                         $i = array_search('', $type, true);
                         if ($i === false) {
                             $type = $context->getLanguage()->commaList($type);
                         } else {
                             unset($type[$i]);
                             $type = $context->msg('api-help-param-list-can-be-empty')->numParams(count($type))->params($context->getLanguage()->commaList($type))->parse();
                         }
                         $info[] = $context->msg('api-help-param-list')->params($multi ? 2 : 1)->params($type)->parse();
                         $hintPipeSeparated = false;
                     } else {
                         switch ($type) {
                             case 'submodule':
                                 $groups[] = $name;
                                 if (isset($settings[ApiBase::PARAM_SUBMODULE_MAP])) {
                                     $map = $settings[ApiBase::PARAM_SUBMODULE_MAP];
                                     ksort($map);
                                     $submodules = array();
                                     foreach ($map as $v => $m) {
                                         $submodules[] = "[[Special:ApiHelp/{$m}|{$v}]]";
                                     }
                                 } else {
                                     $submodules = $module->getModuleManager()->getNames($name);
                                     sort($submodules);
                                     $prefix = $module->isMain() ? '' : $module->getModulePath() . '+';
                                     $submodules = array_map(function ($name) use($prefix) {
                                         return "[[Special:ApiHelp/{$prefix}{$name}|{$name}]]";
                                     }, $submodules);
                                 }
                                 $count = count($submodules);
                                 $info[] = $context->msg('api-help-param-list')->params($multi ? 2 : 1)->params($context->getLanguage()->commaList($submodules))->parse();
                                 $hintPipeSeparated = false;
                                 // No type message necessary, we have a list of values.
                                 $type = null;
                                 break;
                             case 'namespace':
                                 $namespaces = MWNamespace::getValidNamespaces();
                                 $count = count($namespaces);
                                 $info[] = $context->msg('api-help-param-list')->params($multi ? 2 : 1)->params($context->getLanguage()->commaList($namespaces))->parse();
                                 $hintPipeSeparated = false;
                                 // No type message necessary, we have a list of values.
                                 $type = null;
                                 break;
                             case 'limit':
                                 if (isset($settings[ApiBase::PARAM_MAX2])) {
                                     $info[] = $context->msg('api-help-param-limit2')->numParams($settings[ApiBase::PARAM_MAX])->numParams($settings[ApiBase::PARAM_MAX2])->parse();
                                 } else {
                                     $info[] = $context->msg('api-help-param-limit')->numParams($settings[ApiBase::PARAM_MAX])->parse();
                                 }
                                 break;
                             case 'integer':
                                 // Possible messages:
                                 // api-help-param-integer-min,
                                 // api-help-param-integer-max,
                                 // api-help-param-integer-minmax
                                 $suffix = '';
                                 $min = $max = 0;
                                 if (isset($settings[ApiBase::PARAM_MIN])) {
                                     $suffix .= 'min';
                                     $min = $settings[ApiBase::PARAM_MIN];
                                 }
                                 if (isset($settings[ApiBase::PARAM_MAX])) {
                                     $suffix .= 'max';
                                     $max = $settings[ApiBase::PARAM_MAX];
                                 }
                                 if ($suffix !== '') {
                                     $info[] = $context->msg("api-help-param-integer-{$suffix}")->params($multi ? 2 : 1)->numParams($min, $max)->parse();
                                 }
                                 break;
                             case 'upload':
                                 $info[] = $context->msg('api-help-param-upload')->parse();
                                 // No type message necessary, api-help-param-upload should handle it.
                                 $type = null;
                                 break;
                             case 'string':
                             case 'text':
                                 // Displaying a type message here would be useless.
                                 $type = null;
                                 break;
                         }
                     }
                     // Add type. Messages for grep: api-help-param-type-limit
                     // api-help-param-type-integer api-help-param-type-boolean
                     // api-help-param-type-timestamp api-help-param-type-user
                     // api-help-param-type-password
                     if (is_string($type)) {
                         $msg = $context->msg("api-help-param-type-{$type}");
                         if (!$msg->isDisabled()) {
                             $info[] = $msg->params($multi ? 2 : 1)->parse();
                         }
                     }
                     if ($multi) {
                         $extra = array();
                         if ($hintPipeSeparated) {
                             $extra[] = $context->msg('api-help-param-multi-separate')->parse();
                         }
                         if ($count > ApiBase::LIMIT_SML1) {
                             $extra[] = $context->msg('api-help-param-multi-max')->numParams(ApiBase::LIMIT_SML1, ApiBase::LIMIT_SML2)->parse();
                         }
                         if ($extra) {
                             $info[] = join(' ', $extra);
                         }
                     }
                 }
                 // Add default
                 $default = isset($settings[ApiBase::PARAM_DFLT]) ? $settings[ApiBase::PARAM_DFLT] : null;
                 if ($default === '') {
                     $info[] = $context->msg('api-help-param-default-empty')->parse();
                 } elseif ($default !== null && $default !== false) {
                     $info[] = $context->msg('api-help-param-default')->params(wfEscapeWikiText($default))->parse();
                 }
                 if (!array_filter($description)) {
                     $description = array(self::wrap($context->msg('api-help-param-no-description'), 'apihelp-empty'));
                 }
                 // Add "deprecated" flag
                 if (!empty($settings[ApiBase::PARAM_DEPRECATED])) {
                     $help['parameters'] .= Html::openElement('dd', array('class' => 'info'));
                     $help['parameters'] .= self::wrap($context->msg('api-help-param-deprecated'), 'apihelp-deprecated', 'strong');
                     $help['parameters'] .= Html::closeElement('dd');
                 }
                 if ($description) {
                     $description = join('', $description);
                     $description = preg_replace('!\\s*</([oud]l)>\\s*<\\1>\\s*!', "\n", $description);
                     $help['parameters'] .= Html::rawElement('dd', array('class' => 'description'), $description);
                 }
                 foreach ($info as $i) {
                     $help['parameters'] .= Html::rawElement('dd', array('class' => 'info'), $i);
                 }
             }
             if ($dynamicParams !== null) {
                 $dynamicParams = ApiBase::makeMessage($dynamicParams, $context, array($module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()));
                 $help['parameters'] .= Html::element('dt', null, '*');
                 $help['parameters'] .= Html::rawElement('dd', array('class' => 'description'), $dynamicParams->parse());
             }
             $help['parameters'] .= Html::closeElement('dl');
             $help['parameters'] .= Html::closeElement('div');
         }
         $examples = $module->getExamplesMessages();
         if ($examples) {
             $help['examples'] .= Html::openElement('div', array('class' => 'apihelp-block apihelp-examples'));
             $msg = $context->msg('api-help-examples');
             if (!$msg->isDisabled()) {
                 $help['examples'] .= self::wrap($msg->numParams(count($examples)), 'apihelp-block-head', 'div');
             }
             $help['examples'] .= Html::openElement('dl');
             foreach ($examples as $qs => $msg) {
                 $msg = ApiBase::makeMessage($msg, $context, array($module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()));
                 $link = wfAppendQuery(wfScript('api'), $qs);
                 $help['examples'] .= Html::rawElement('dt', null, $msg->parse());
                 $help['examples'] .= Html::rawElement('dd', null, Html::element('a', array('href' => $link), "api.php?{$qs}"));
             }
             $help['examples'] .= Html::closeElement('dl');
             $help['examples'] .= Html::closeElement('div');
         }
         $subtocnumber = $tocnumber;
         $subtocnumber[$level + 1] = 0;
         $suboptions = array('submodules' => $options['recursivesubmodules'], 'headerlevel' => $level + 1, 'tocnumber' => &$subtocnumber, 'noheader' => false) + $options;
         if ($options['submodules'] && $module->getModuleManager()) {
             $manager = $module->getModuleManager();
             $submodules = array();
             foreach ($groups as $group) {
                 $names = $manager->getNames($group);
                 sort($names);
                 foreach ($names as $name) {
                     $submodules[] = $manager->getModule($name);
                 }
             }
             $help['submodules'] .= self::getHelpInternal($context, $submodules, $suboptions, $haveModules);
         }
         $module->modifyHelp($help, $suboptions, $haveModules);
         Hooks::run('APIHelpModifyOutput', array($module, &$help, $suboptions, &$haveModules));
         $out .= join("\n", $help);
     }
     return $out;
 }
Esempio n. 29
0
 function fetchImageQuery($query)
 {
     global $wgMemc;
     $query = array_merge($query, array('format' => 'json', 'action' => 'query', 'redirects' => 'true'));
     if ($this->mApiBase) {
         $url = wfAppendQuery($this->mApiBase, $query);
     } else {
         $url = $this->makeUrl($query, 'api');
     }
     if (!isset($this->mQueryCache[$url])) {
         $key = $this->getLocalCacheKey('ForeignAPIRepo', 'Metadata', md5($url));
         $data = $wgMemc->get($key);
         if (!$data) {
             $data = self::httpGet($url);
             if (!$data) {
                 return null;
             }
             $wgMemc->set($key, $data, 3600);
         }
         if (count($this->mQueryCache) > 100) {
             // Keep the cache from growing infinitely
             $this->mQueryCache = array();
         }
         $this->mQueryCache[$url] = $data;
     }
     return FormatJson::decode($this->mQueryCache[$url], true);
 }
Esempio n. 30
0
 /**
  * Get a URL with no fragment or server name (relative URL) from a Title object.
  * If this page is generated with action=render, however,
  * $wgServer is prepended to make an absolute URL.
  *
  * @see self::getFullURL to always get an absolute URL.
  * @see self::getLinkURL to always get a URL that's the simplest URL that will be
  *  valid to link, locally, to the current Title.
  * @see self::newFromText to produce a Title object.
  *
  * @param string|array $query An optional query string,
  *   not used for interwiki links. Can be specified as an associative array as well,
  *   e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped).
  *   Some query patterns will trigger various shorturl path replacements.
  * @param array $query2 An optional secondary query array. This one MUST
  *   be an array. If a string is passed it will be interpreted as a deprecated
  *   variant argument and urlencoded into a variant= argument.
  *   This second query argument will be added to the $query
  *   The second parameter is deprecated since 1.19. Pass it as a key,value
  *   pair in the first parameter array instead.
  *
  * @return string String of the URL.
  */
 public function getLocalURL($query = '', $query2 = false)
 {
     global $wgArticlePath, $wgScript, $wgServer, $wgRequest;
     $query = self::fixUrlQueryArgs($query, $query2);
     $interwiki = Interwiki::fetch($this->mInterwiki);
     if ($interwiki) {
         $namespace = $this->getNsText();
         if ($namespace != '') {
             # Can this actually happen? Interwikis shouldn't be parsed.
             # Yes! It can in interwiki transclusion. But... it probably shouldn't.
             $namespace .= ':';
         }
         $url = $interwiki->getURL($namespace . $this->getDBkey());
         $url = wfAppendQuery($url, $query);
     } else {
         $dbkey = wfUrlencode($this->getPrefixedDBkey());
         if ($query == '') {
             $url = str_replace('$1', $dbkey, $wgArticlePath);
             Hooks::run('GetLocalURL::Article', array(&$this, &$url));
         } else {
             global $wgVariantArticlePath, $wgActionPaths, $wgContLang;
             $url = false;
             $matches = array();
             if (!empty($wgActionPaths) && preg_match('/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches)) {
                 $action = urldecode($matches[2]);
                 if (isset($wgActionPaths[$action])) {
                     $query = $matches[1];
                     if (isset($matches[4])) {
                         $query .= $matches[4];
                     }
                     $url = str_replace('$1', $dbkey, $wgActionPaths[$action]);
                     if ($query != '') {
                         $url = wfAppendQuery($url, $query);
                     }
                 }
             }
             if ($url === false && $wgVariantArticlePath && $wgContLang->getCode() === $this->getPageLanguage()->getCode() && $this->getPageLanguage()->hasVariants() && preg_match('/^variant=([^&]*)$/', $query, $matches)) {
                 $variant = urldecode($matches[1]);
                 if ($this->getPageLanguage()->hasVariant($variant)) {
                     // Only do the variant replacement if the given variant is a valid
                     // variant for the page's language.
                     $url = str_replace('$2', urlencode($variant), $wgVariantArticlePath);
                     $url = str_replace('$1', $dbkey, $url);
                 }
             }
             if ($url === false) {
                 if ($query == '-') {
                     $query = '';
                 }
                 $url = "{$wgScript}?title={$dbkey}&{$query}";
             }
         }
         Hooks::run('GetLocalURL::Internal', array(&$this, &$url, $query));
         // @todo FIXME: This causes breakage in various places when we
         // actually expected a local URL and end up with dupe prefixes.
         if ($wgRequest->getVal('action') == 'render') {
             $url = $wgServer . $url;
         }
     }
     Hooks::run('GetLocalURL', array(&$this, &$url, $query));
     return $url;
 }