Пример #1
0
 /**
  * Check if the given local page title is a spam regex source.
  * @param Title $title
  * @return bool
  */
 function isLocalSource($title)
 {
     global $wgDBname;
     if ($title->getNamespace() == NS_MEDIAWIKI) {
         $sources = array("Spam-blacklist", "Spam-whitelist");
         if (in_array($title->getDBkey(), $sources)) {
             return true;
         }
     }
     $thisHttp = wfExpandUrl($title->getFullUrl('action=raw'), PROTO_HTTP);
     $thisHttpRegex = '/^' . preg_quote($thisHttp, '/') . '(?:&.*)?$/';
     foreach ($this->files as $fileName) {
         $matches = array();
         if (preg_match('/^DB: (\\w*) (.*)$/', $fileName, $matches)) {
             if ($wgDBname == $matches[1]) {
                 if ($matches[2] == $title->getPrefixedDbKey()) {
                     // Local DB fetch of this page...
                     return true;
                 }
             }
         } elseif (preg_match($thisHttpRegex, $fileName)) {
             // Raw view of this page
             return true;
         }
     }
     return false;
 }
Пример #2
0
/**
 * Forks processes to scan the originating IP for an open proxy server
 * MemCached can be used to skip IPs that have already been scanned
 */
function wfProxyCheck()
{
    global $wgBlockOpenProxies, $wgProxyPorts, $wgProxyScriptPath;
    global $wgMemc, $wgProxyMemcExpiry, $wgRequest;
    global $wgProxyKey;
    if (!$wgBlockOpenProxies) {
        return;
    }
    $ip = $wgRequest->getIP();
    # Get MemCached key
    $mcKey = wfMemcKey('proxy', 'ip', $ip);
    $mcValue = $wgMemc->get($mcKey);
    $skip = (bool) $mcValue;
    # Fork the processes
    if (!$skip) {
        $title = SpecialPage::getTitleFor('Blockme');
        $iphash = md5($ip . $wgProxyKey);
        $url = wfExpandUrl($title->getFullURL('ip=' . $iphash), PROTO_HTTP);
        foreach ($wgProxyPorts as $port) {
            $params = implode(' ', array(escapeshellarg($wgProxyScriptPath), escapeshellarg($ip), escapeshellarg($port), escapeshellarg($url)));
            exec("php {$params} >" . wfGetNull() . " 2>&1 &");
        }
        # Set MemCached key
        $wgMemc->set($mcKey, 1, $wgProxyMemcExpiry);
    }
}
Пример #3
0
function streamAppleTouch()
{
    global $wgAppleTouchIcon;
    wfResetOutputBuffers();
    if ($wgAppleTouchIcon === false) {
        # That's not very helpful, that's where we are already
        header('HTTP/1.1 404 Not Found');
        faviconShowError('$wgAppleTouchIcon is configured incorrectly, ' . 'it must be set to something other than false \\n');
        return;
    }
    $req = RequestContext::getMain()->getRequest();
    if ($req->getHeader('X-Favicon-Loop') !== false) {
        header('HTTP/1.1 500 Internal Server Error');
        faviconShowError('Proxy forwarding loop detected');
        return;
    }
    $url = wfExpandUrl($wgAppleTouchIcon, PROTO_CANONICAL);
    $client = MWHttpRequest::factory($url);
    $client->setHeader('X-Favicon-Loop', '1');
    $status = $client->execute();
    if (!$status->isOK()) {
        header('HTTP/1.1 500 Internal Server Error');
        faviconShowError("Failed to fetch URL \"{$url}\"");
        return;
    }
    $content = $client->getContent();
    header('Content-Length: ' . strlen($content));
    header('Content-Type: ' . $client->getResponseHeader('Content-Type'));
    header('Cache-Control: public');
    header('Expires: ' . gmdate('r', time() + 86400));
    echo $content;
}
Пример #4
0
function efOpenGraphMetaPageHook(OutputPage &$out, &$sk)
{
    global $wgLogo, $wgSitename, $wgXhtmlNamespaces, $egFacebookAppId, $egFacebookAdmins;
    $wgXhtmlNamespaces["og"] = "http://opengraphprotocol.org/schema/";
    $title = $out->getTitle();
    $isMainpage = $title->isMainPage();
    $meta = array();
    if ($isMainpage) {
        $meta["og:type"] = "website";
        $meta["og:title"] = $wgSitename;
    } else {
        $meta["og:type"] = "article";
        $meta["og:site_name"] = $wgSitename;
        // Try to chose the most appropriate title for showing in news feeds.
        if (defined('NS_BLOG_ARTICLE') && $title->getNamespace() == NS_BLOG_ARTICLE || defined('NS_BLOG_ARTICLE_TALK') && $title->getNamespace() == NS_BLOG_ARTICLE_TALK) {
            $meta["og:title"] = $title->getSubpageText();
        } else {
            $meta["og:title"] = $title->getText();
        }
    }
    if (isset($out->mMainImage) && $out->mMainImage !== false) {
        if (is_object($out->mMainImage)) {
            $meta["og:image"] = wfExpandUrl($out->mMainImage->createThumb(100 * 3, 100));
        } else {
            // In some edge-cases we won't have defined an object but rather a full URL.
            $meta["og:image"] = $out->mMainImage;
        }
    } elseif ($isMainpage) {
        $meta["og:image"] = wfExpandUrl($wgLogo);
    }
    if (isset($out->mDescription)) {
        // set by Description2 extension, install it if you want proper og:description support
        $meta["og:description"] = $out->mDescription;
    }
    $meta["og:url"] = $title->getFullURL();
    if ($egFacebookAppId) {
        /* begin wikia change */
        // $meta["fb:app_id"] = $egFacebookAppId;
        // fb:app_id needs a prefix property declaring the namespace, so just add it directly
        $out->addHeadItem("meta:property:fb:app_id", "\t" . Html::element('meta', array('property' => 'fb:app_id', 'content' => $egFacebookAppId, 'prefix' => "fb: http://www.facebook.com/2008/fbml")) . "\n");
        /* end wikia change */
    }
    if ($egFacebookAdmins) {
        $meta["fb:admins"] = $egFacebookAdmins;
    }
    /* begin wikia change */
    wfRunHooks('OpenGraphMetaHeaders', array("meta" => &$meta, "title" => $title));
    /* end wikia change */
    foreach ($meta as $property => $value) {
        if ($value) {
            if (isset(OutputPage::$metaAttrPrefixes) && isset(OutputPage::$metaAttrPrefixes['property'])) {
                $out->addMeta("property:{$property}", $value);
            } else {
                $out->addHeadItem("meta:property:{$property}", "\t" . Html::element('meta', array('property' => $property, 'content' => $value)) . "\n");
            }
        }
    }
    return true;
}
 /**
  * Main Constructer
  *
  * @access	public
  * @return	void
  */
 public function __construct()
 {
     global $wgServer, $wgScriptPath, $wgUser;
     $achievementsPage = Title::newFromText('Special:Achievements');
     $this->achievementsURL = $achievementsPage->getFullURL();
     $this->urlPrefix = wfExpandUrl($wgServer . $wgScriptPath);
     $this->wgUser = $wgUser;
 }
 /**
  * If WikiFactory wgEnableNewAuth variable is set to true, then this method sets login url for the New Auth Flow login page.
  * Also new class is set for the login button.
  * Otherwise it sets url to the old Special:Login page.
  */
 private function setupLoginLink()
 {
     if ($this->app->wg->EnableNewAuth) {
         $this->loginUrl = '/join?redirect=' . urlencode(wfExpandUrl($this->app->wg->request->getRequestURL())) . $this->getUselangParam();
         $this->loginButtonClass = 'new-login';
     } else {
         $this->loginUrl = SpecialPage::getTitleFor('UserLogin')->getLocalURL();
         $this->loginButtonClass = '';
     }
 }
 public function performUploadDone($user)
 {
     $this->mUpload->finalizeFile();
     $status = parent::performUpload($this->comment, $this->pageText, $this->watch, $user);
     if ($status['result'] !== 'Success') {
         return $status;
     }
     $file = $this->mUpload->getLocalFile();
     return array('result' => 1, 'done' => 1, 'resultUrl' => wfExpandUrl($file->getDescriptionUrl()));
 }
Пример #8
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 '';
}
Пример #9
0
 /**
  * @param integer $size the width of the thumbnail
  * @return string
  */
 private function getPageImageHtml($size = 750)
 {
     if ($this->item->hasImage()) {
         $thumb = models\Image::getThumbnail($this->item->getFile(), $size);
         if ($thumb && $thumb->getUrl()) {
             $data = array('url' => wfExpandUrl($thumb->getUrl(), PROTO_CURRENT), 'wide' => $thumb->getWidth() > $thumb->getHeight());
             return Template::render('CardImage', $data);
         }
     }
     return '';
 }
Пример #10
0
 /** @dataProvider provideExpandableUrls */
 public function testWfExpandUrl($fullUrl, $shortUrl, $defaultProto, $server, $canServer, $httpsMode, $message)
 {
     // Fake $wgServer and $wgCanonicalServer
     $this->setMwGlobals(array('wgServer' => $server, 'wgCanonicalServer' => $canServer));
     // Fake $_SERVER['HTTPS'] if needed
     if ($httpsMode) {
         $_SERVER['HTTPS'] = 'on';
     } else {
         unset($_SERVER['HTTPS']);
     }
     $this->assertEquals($fullUrl, wfExpandUrl($shortUrl, $defaultProto), $message);
 }
Пример #11
0
 public function execute()
 {
     if ($this->getPageSet()->getGoodTitleCount() == 0) {
         return;
     }
     $params = $this->extractRequestParams();
     $query = $params['query'];
     $protocol = ApiQueryExtLinksUsage::getProtocolPrefix($params['protocol']);
     $this->addFields(array('el_from', 'el_to'));
     $this->addTables('externallinks');
     $this->addWhereFld('el_from', array_keys($this->getPageSet()->getGoodTitles()));
     $whereQuery = $this->prepareUrlQuerySearchString($query, $protocol);
     if ($whereQuery !== null) {
         $this->addWhere($whereQuery);
     }
     // Don't order by el_from if it's constant in the WHERE clause
     if (count($this->getPageSet()->getGoodTitles()) != 1) {
         $this->addOption('ORDER BY', 'el_from');
     }
     // If we're querying all protocols, use DISTINCT to avoid repeating protocol-relative links twice
     if ($protocol === null) {
         $this->addOption('DISTINCT');
     }
     $this->addOption('LIMIT', $params['limit'] + 1);
     $offset = isset($params['offset']) ? $params['offset'] : 0;
     if ($offset) {
         $this->addOption('OFFSET', $params['offset']);
     }
     $res = $this->select(__METHOD__);
     $count = 0;
     foreach ($res as $row) {
         if (++$count > $params['limit']) {
             // We've reached the one extra which shows that
             // there are additional pages to be had. Stop here...
             $this->setContinueEnumParameter('offset', $offset + $params['limit']);
             break;
         }
         $entry = array();
         $to = $row->el_to;
         // expand protocol-relative urls
         if ($params['expandurl']) {
             $to = wfExpandUrl($to, PROTO_CANONICAL);
         }
         ApiResult::setContent($entry, $to);
         $fit = $this->addPageSubItem($row->el_from, $entry);
         if (!$fit) {
             $this->setContinueEnumParameter('offset', $offset + $count - 1);
             break;
         }
     }
 }
Пример #12
0
 public function testSubPageRedirect()
 {
     $ctx = new RequestContext();
     SpecialPageFactory::executePath(Title::newFromText('Special:Search/foo_bar'), $ctx);
     $url = $ctx->getOutput()->getRedirect();
     // some older versions of hhvm have a bug that doesn't parse relative
     // urls with a port, so help it out a little bit.
     // https://github.com/facebook/hhvm/issues/7136
     $url = wfExpandUrl($url, PROTO_CURRENT);
     $parts = parse_url($url);
     $this->assertEquals('/w/index.php', $parts['path']);
     parse_str($parts['query'], $query);
     $this->assertEquals('Special:Search', $query['title']);
     $this->assertEquals('foo bar', $query['search']);
 }
Пример #13
0
 /**
  * @param string $url Url to use. If protocol-relative, will be expanded to an http:// URL
  * @param array $options (optional) extra params to pass (see Http::request())
  * @param string $caller The method making this request, for profiling
  * @param Profiler $profiler An instance of the profiler for profiling, or null
  */
 protected function __construct($url, $options = [], $caller = __METHOD__, $profiler = null)
 {
     global $wgHTTPTimeout, $wgHTTPConnectTimeout;
     $this->url = wfExpandUrl($url, PROTO_HTTP);
     $this->parsedUrl = wfParseUrl($this->url);
     if (isset($options['logger'])) {
         $this->logger = $options['logger'];
     } else {
         $this->logger = new NullLogger();
     }
     if (!$this->parsedUrl || !Http::isValidURI($this->url)) {
         $this->status = Status::newFatal('http-invalid-url', $url);
     } else {
         $this->status = Status::newGood(100);
         // continue
     }
     if (isset($options['timeout']) && $options['timeout'] != 'default') {
         $this->timeout = $options['timeout'];
     } else {
         $this->timeout = $wgHTTPTimeout;
     }
     if (isset($options['connectTimeout']) && $options['connectTimeout'] != 'default') {
         $this->connectTimeout = $options['connectTimeout'];
     } else {
         $this->connectTimeout = $wgHTTPConnectTimeout;
     }
     if (isset($options['userAgent'])) {
         $this->setUserAgent($options['userAgent']);
     }
     $members = ["postData", "proxy", "noProxy", "sslVerifyHost", "caInfo", "method", "followRedirects", "maxRedirects", "sslVerifyCert", "callback"];
     foreach ($members as $o) {
         if (isset($options[$o])) {
             // ensure that MWHttpRequest::method is always
             // uppercased. Bug 36137
             if ($o == 'method') {
                 $options[$o] = strtoupper($options[$o]);
             }
             $this->{$o} = $options[$o];
         }
     }
     if ($this->noProxy) {
         $this->proxy = '';
         // noProxy takes precedence
     }
     // Profile based on what's calling us
     $this->profiler = $profiler;
     $this->profileName = $caller;
 }
Пример #14
0
 /**
  * Perform an HTTP request
  *
  * @param $method String: HTTP method. Usually GET/POST
  * @param $url String: full URL to act on
  * @param $options Array: options to pass to MWHttpRequest object.
  *	Possible keys for the array:
  *    - timeout             Timeout length in seconds
  *    - postData            An array of key-value pairs or a url-encoded form data
  *    - proxy               The proxy to use.
  *                          Will use $wgHTTPProxy (if set) otherwise.
  *    - noProxy             Override $wgHTTPProxy (if set) and don't use any proxy at all.
  *    - sslVerifyHost       (curl only) Verify hostname against certificate
  *    - sslVerifyCert       (curl only) Verify SSL certificate
  *    - caInfo              (curl only) Provide CA information
  *    - maxRedirects        Maximum number of redirects to follow (defaults to 5)
  *    - followRedirects     Whether to follow redirects (defaults to false).
  *		                    Note: this should only be used when the target URL is trusted,
  *		                    to avoid attacks on intranet services accessible by HTTP.
  * @return Mixed: (bool)false on failure or a string on success
  */
 public static function request($method, $url, $options = array())
 {
     $url = wfExpandUrl($url);
     wfDebug("HTTP: {$method}: {$url}\n");
     $options['method'] = strtoupper($method);
     if (!isset($options['timeout'])) {
         $options['timeout'] = 'default';
     }
     $req = MWHttpRequest::factory($url, $options);
     $status = $req->execute();
     if ($status->isOK()) {
         return $req->getContent();
     } else {
         return false;
     }
 }
Пример #15
0
 public function load($parser)
 {
     if ($this->loaded) {
         return;
     }
     if (!$parser->getTitle()->mUrlform) {
         return;
     }
     $file = $parser->getTitle()->mUrlform;
     $path = __DIR__ . '/css/' . $file . '.css';
     if (!file_exists($path)) {
         return;
     }
     global $wgScriptPath;
     $url = wfExpandUrl("{$wgScriptPath}/extensions/CSSLoader/css/{$file}.css");
     $this->url = $url;
     $this->loaded = true;
 }
Пример #16
0
 /** @dataProvider provideExpandableUrls */
 public function testWfExpandUrl($fullUrl, $shortUrl, $defaultProto, $server, $canServer, $httpsMode, $message)
 {
     // Fake $wgServer and $wgCanonicalServer
     global $wgServer, $wgCanonicalServer;
     $oldServer = $wgServer;
     $oldCanServer = $wgCanonicalServer;
     $wgServer = $server;
     $wgCanonicalServer = $canServer;
     // Fake $_SERVER['HTTPS'] if needed
     if ($httpsMode) {
         $_SERVER['HTTPS'] = 'on';
     } else {
         unset($_SERVER['HTTPS']);
     }
     $this->assertEquals($fullUrl, wfExpandUrl($shortUrl, $defaultProto), $message);
     // Restore $wgServer and $wgCanonicalServer
     $wgServer = $oldServer;
     $wgCanonicalServer = $oldCanServer;
 }
 /**
  * @param string $url
  * @param array $cookies
  * @return MobileContext
  */
 private function makeContext($url = '/', $cookies = array())
 {
     $query = array();
     if ($url) {
         $params = wfParseUrl(wfExpandUrl($url));
         if (isset($params['query'])) {
             $query = wfCgiToArray($params['query']);
         }
     }
     $request = new FauxRequest($query);
     $request->setRequestURL($url);
     $request->setCookies($cookies, '');
     $context = new DerivativeContext(RequestContext::getMain());
     $context->setRequest($request);
     $context->setOutput(new OutputPage($context));
     $instance = unserialize('O:13:"MobileContext":0:{}');
     $instance->setContext($context);
     return $instance;
 }
Пример #18
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);
 }
Пример #19
0
 public function execute()
 {
     wfProfileIn(__METHOD__);
     $params = $this->extractRequestParams();
     global $wgFeedClasses;
     if (!isset($wgFeedClasses[$params['feedformat']])) {
         wfProfileOut(__METHOD__);
         $this->dieUsage('Invalid subscription feed type', 'feed-invalid');
     }
     $language = isset($params['language']) ? $params['language'] : false;
     if ($language !== false && !Language::isValidCode($language)) {
         $language = false;
     }
     $feeds = FeaturedFeeds::getFeeds($language);
     $ourFeed = $feeds[$params['feed']];
     $feedClass = new $wgFeedClasses[$params['feedformat']]($ourFeed->title, $ourFeed->description, wfExpandUrl(Title::newMainPage()->getFullURL()));
     ApiFormatFeedWrapper::setResult($this->getResult(), $feedClass, $ourFeed->getFeedItems());
     // Cache stuff in squids
     $this->getMain()->setCacheMode('public');
     $this->getMain()->setCacheMaxAge(FeaturedFeeds::getMaxAge());
     wfProfileOut(__METHOD__);
 }
Пример #20
0
 /**
  * Transform a media file
  *
  * @param array $params an associative array of handler-specific parameters.
  *                Typical keys are width, height and page.
  * @param $flags Integer: a bitfield, may contain self::RENDER_NOW to force rendering
  * @return MediaTransformOutput|bool False on failure
  */
 function transform($params, $flags = 0)
 {
     global $wgUseSquid, $wgIgnoreImageErrors, $wgThumbnailEpoch;
     wfProfileIn(__METHOD__);
     do {
         if (!$this->canRender()) {
             $thumb = $this->iconThumb();
             break;
             // not a bitmap or renderable image, don't try
         }
         // Get the descriptionUrl to embed it as comment into the thumbnail. Bug 19791.
         $descriptionUrl = $this->getDescriptionUrl();
         if ($descriptionUrl) {
             $params['descriptionUrl'] = wfExpandUrl($descriptionUrl, PROTO_CANONICAL);
         }
         $handler = $this->getHandler();
         $script = $this->getTransformScript();
         if ($script && !($flags & self::RENDER_NOW)) {
             // Use a script to transform on client request, if possible
             $thumb = $handler->getScriptedTransform($this, $script, $params);
             if ($thumb) {
                 break;
             }
         }
         $normalisedParams = $params;
         $handler->normaliseParams($this, $normalisedParams);
         $thumbName = $this->thumbName($normalisedParams);
         $thumbUrl = $this->getThumbUrl($thumbName);
         $thumbPath = $this->getThumbPath($thumbName);
         // final thumb path
         if ($this->repo) {
             // Defer rendering if a 404 handler is set up...
             if ($this->repo->canTransformVia404() && !($flags & self::RENDER_NOW)) {
                 wfDebug(__METHOD__ . " transformation deferred.");
                 // XXX: Pass in the storage path even though we are not rendering anything
                 // and the path is supposed to be an FS path. This is due to getScalerType()
                 // getting called on the path and clobbering $thumb->getUrl() if it's false.
                 $thumb = $handler->getTransform($this, $thumbPath, $thumbUrl, $params);
                 break;
             }
             // Clean up broken thumbnails as needed
             $this->migrateThumbFile($thumbName);
             // Check if an up-to-date thumbnail already exists...
             wfDebug(__METHOD__ . ": Doing stat for {$thumbPath}\n");
             if (!($flags & self::RENDER_FORCE) && $this->repo->fileExists($thumbPath)) {
                 $timestamp = $this->repo->getFileTimestamp($thumbPath);
                 if ($timestamp !== false && $timestamp >= $wgThumbnailEpoch) {
                     // XXX: Pass in the storage path even though we are not rendering anything
                     // and the path is supposed to be an FS path. This is due to getScalerType()
                     // getting called on the path and clobbering $thumb->getUrl() if it's false.
                     $thumb = $handler->getTransform($this, $thumbPath, $thumbUrl, $params);
                     $thumb->setStoragePath($thumbPath);
                     break;
                 }
             } elseif ($flags & self::RENDER_FORCE) {
                 wfDebug(__METHOD__ . " forcing rendering per flag File::RENDER_FORCE\n");
             }
         }
         // If the backend is ready-only, don't keep generating thumbnails
         // only to return transformation errors, just return the error now.
         if ($this->repo->getReadOnlyReason() !== false) {
             $thumb = $this->transformErrorOutput($thumbPath, $thumbUrl, $params, $flags);
             break;
         }
         // Create a temp FS file with the same extension and the thumbnail
         $thumbExt = FileBackend::extensionFromPath($thumbPath);
         $tmpFile = TempFSFile::factory('transform_', $thumbExt);
         if (!$tmpFile) {
             $thumb = $this->transformErrorOutput($thumbPath, $thumbUrl, $params, $flags);
             break;
         }
         $tmpThumbPath = $tmpFile->getPath();
         // path of 0-byte temp file
         // Actually render the thumbnail...
         wfProfileIn(__METHOD__ . '-doTransform');
         $thumb = $handler->doTransform($this, $tmpThumbPath, $thumbUrl, $params);
         wfProfileOut(__METHOD__ . '-doTransform');
         $tmpFile->bind($thumb);
         // keep alive with $thumb
         if (!$thumb) {
             // bad params?
             $thumb = null;
         } elseif ($thumb->isError()) {
             // transform error
             $this->lastError = $thumb->toText();
             // Ignore errors if requested
             if ($wgIgnoreImageErrors && !($flags & self::RENDER_NOW)) {
                 $thumb = $handler->getTransform($this, $tmpThumbPath, $thumbUrl, $params);
             }
         } elseif ($this->repo && $thumb->hasFile() && !$thumb->fileIsSource()) {
             // Copy the thumbnail from the file system into storage...
             $disposition = $this->getThumbDisposition($thumbName);
             $status = $this->repo->quickImport($tmpThumbPath, $thumbPath, $disposition);
             if ($status->isOK()) {
                 $thumb->setStoragePath($thumbPath);
             } else {
                 $thumb = $this->transformErrorOutput($thumbPath, $thumbUrl, $params, $flags);
             }
             // Give extensions a chance to do something with this thumbnail...
             wfRunHooks('FileTransformed', array($this, $thumb, $tmpThumbPath, $thumbPath));
         }
         // Purge. Useful in the event of Core -> Squid connection failure or squid
         // purge collisions from elsewhere during failure. Don't keep triggering for
         // "thumbs" which have the main image URL though (bug 13776)
         if ($wgUseSquid) {
             if (!$thumb || $thumb->isError() || $thumb->getUrl() != $this->getURL()) {
                 SquidUpdate::purge(array($thumbUrl));
             }
         }
     } while (false);
     wfProfileOut(__METHOD__);
     return is_object($thumb) ? $thumb : false;
 }
Пример #21
0
 private function formatIWLinks($iw)
 {
     $result = array();
     foreach ($iw as $prefix => $titles) {
         foreach (array_keys($titles) as $title) {
             $entry = array();
             $entry['prefix'] = $prefix;
             $title = Title::newFromText("{$prefix}:{$title}");
             if ($title) {
                 $entry['url'] = wfExpandUrl($title->getFullURL(), PROTO_CURRENT);
             }
             $this->getResult()->setContent($entry, $title->getFullText());
             $result[] = $entry;
         }
     }
     return $result;
 }
    /**
     * 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());
    }
Пример #23
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;
 }
Пример #24
0
 /**
  * Like a Http:get request, but with custom User-Agent.
  * @see Http:get
  */
 public static function httpGet($url, $timeout = 'default', $options = array())
 {
     $options['timeout'] = $timeout;
     /* Http::get */
     $url = wfExpandUrl($url, PROTO_HTTP);
     wfDebug("ForeignAPIRepo: HTTP GET: {$url}\n");
     $options['method'] = "GET";
     if (!isset($options['timeout'])) {
         $options['timeout'] = 'default';
     }
     $req = MWHttpRequest::factory($url, $options);
     $req->setUserAgent(ForeignAPIRepo::getUserAgent());
     $status = $req->execute();
     if ($status->isOK()) {
         return $req->getContent();
     } else {
         return false;
     }
 }
Пример #25
0
 /**
  * Return information about the repository.
  *
  * @return array
  * @since 1.22
  */
 function getInfo()
 {
     global $wgFavicon;
     return array_merge(parent::getInfo(), array('favicon' => wfExpandUrl($wgFavicon)));
 }
Пример #26
0
 /**
  * Get the URL for a canonical link, for use in things like IRC and
  * e-mail notifications. Uses $wgCanonicalServer and the
  * GetCanonicalURL hook.
  *
  * NOTE: Unlike getInternalURL(), the canonical URL includes the fragment
  *
  * @see self::getLocalURL for the arguments.
  * @return string The URL
  * @since 1.18
  */
 public function getCanonicalURL($query = '', $query2 = false)
 {
     $query = self::fixUrlQueryArgs($query, $query2);
     $url = wfExpandUrl($this->getLocalURL($query) . $this->getFragmentForURL(), PROTO_CANONICAL);
     Hooks::run('GetCanonicalURL', array(&$this, &$url, $query));
     return $url;
 }
Пример #27
0
 static function diffPermalinkURL($thread, $revision)
 {
     $query = self::diffQuery($thread, $revision);
     return wfExpandUrl(self::permalinkUrl($thread, null, null, $query), PROTO_RELATIVE);
 }
Пример #28
0
 /**
  * Return the request URI with the canonical service and hostname, path,
  * and query string. This will be suitable for use as an absolute link
  * in HTML or other output.
  *
  * If $wgServer is protocol-relative, this will return a fully
  * qualified URL with the protocol that was used for this request.
  *
  * @return String
  */
 public function getFullRequestURL()
 {
     return wfExpandUrl($this->getRequestURL(), PROTO_CURRENT);
 }
Пример #29
0
 /**
  * Replace the result data with the information about an exception.
  * Returns the error code
  * @param Exception $e
  * @return string
  */
 protected function substituteResultWithError($e)
 {
     $result = $this->getResult();
     $config = $this->getConfig();
     if ($e instanceof UsageException) {
         // User entered incorrect parameters - generate error response
         $errMessage = $e->getMessageArray();
         $link = wfExpandUrl(wfScript('api'));
         ApiResult::setContentValue($errMessage, 'docref', "See {$link} for API usage");
     } else {
         // Something is seriously wrong
         if ($e instanceof DBQueryError && !$config->get('ShowSQLErrors')) {
             $info = 'Database query error';
         } else {
             $info = "Exception Caught: {$e->getMessage()}";
         }
         $errMessage = array('code' => 'internal_api_error_' . get_class($e), 'info' => '[' . MWExceptionHandler::getLogId($e) . '] ' . $info);
         if ($config->get('ShowExceptionDetails')) {
             ApiResult::setContentValue($errMessage, 'trace', MWExceptionHandler::getRedactedTraceAsString($e));
         }
     }
     // Remember all the warnings to re-add them later
     $warnings = $result->getResultData(array('warnings'));
     $result->reset();
     // Re-add the id
     $requestid = $this->getParameter('requestid');
     if (!is_null($requestid)) {
         $result->addValue(null, 'requestid', $requestid, ApiResult::NO_SIZE_CHECK);
     }
     if ($config->get('ShowHostnames')) {
         // servedby is especially useful when debugging errors
         $result->addValue(null, 'servedby', wfHostName(), ApiResult::NO_SIZE_CHECK);
     }
     if ($warnings !== null) {
         $result->addValue(null, 'warnings', $warnings, ApiResult::NO_SIZE_CHECK);
     }
     $result->addValue(null, 'error', $errMessage, ApiResult::NO_SIZE_CHECK);
     return $errMessage['code'];
 }
Пример #30
0
 /**
  * Builds an internal list of APIs to expose information about.
  * Normally this only lists the MediaWiki API, with its base URL,
  * link to documentation, and a marker as to available authentication
  * (to aid in OAuth client apps switching to support in the future).
  *
  * Extensions can expose other APIs, such as WordPress or Twitter-
  * compatible APIs, by hooking 'ApiRsdServiceApis' and adding more
  * elements to the array.
  *
  * See http://cyber.law.harvard.edu/blogs/gems/tech/rsd.html for
  * the base RSD spec, and check WordPress and StatusNet sites for
  * in-production examples listing several blogging and micrblogging
  * APIs.
  *
  * @return array
  */
 protected function getRsdApiList()
 {
     $apis = array('MediaWiki' => array('apiLink' => wfExpandUrl(wfScript('api'), PROTO_CURRENT), 'docs' => 'https://www.mediawiki.org/wiki/API', 'blogID' => '', 'settings' => array('OAuth' => false)));
     Hooks::run('ApiRsdServiceApis', array(&$apis));
     return $apis;
 }