public function execute() { if (!$this->getUser()->isLoggedIn()) { $this->dieUsage('Must be logged in to link accounts', 'notloggedin'); } $params = $this->extractRequestParams(); $this->requireAtLeastOneParameter($params, 'continue', 'returnurl'); if ($params['returnurl'] !== null) { $bits = wfParseUrl($params['returnurl']); if (!$bits || $bits['scheme'] === '') { $encParamName = $this->encodeParamName('returnurl'); $this->dieUsage("Invalid value '{$params['returnurl']}' for url parameter {$encParamName}", "badurl_{$encParamName}"); } } $helper = new ApiAuthManagerHelper($this); $manager = AuthManager::singleton(); // Check security-sensitive operation status $helper->securitySensitiveOperation('LinkAccounts'); // Make sure it's possible to link accounts if (!$manager->canLinkAccounts()) { $this->getResult()->addValue(null, 'linkaccount', $helper->formatAuthenticationResponse(AuthenticationResponse::newFail($this->msg('userlogin-cannot-' . AuthManager::ACTION_LINK)))); return; } // Perform the link step if ($params['continue']) { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LINK_CONTINUE); $res = $manager->continueAccountLink($reqs); } else { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LINK); $res = $manager->beginAccountLink($this->getUser(), $reqs, $params['returnurl']); } $this->getResult()->addValue(null, 'linkaccount', $helper->formatAuthenticationResponse($res)); }
protected function checkContactLink($name, $url, &$countOk) { global $wgVersion; $ok = false; if (Sanitizer::validateEmail($url)) { $ok = true; // assume OK } else { $bits = wfParseUrl($url); if ($bits && isset($bits['scheme'])) { if ($bits['scheme'] == 'mailto') { $ok = true; // assume OK } elseif (in_array($bits['scheme'], array('http', 'https'))) { $req = MWHttpRequest::factory($url, array('method' => 'GET', 'timeout' => 8, 'sslVerifyHost' => false, 'sslVerifyCert' => false)); $req->setUserAgent("MediaWiki {$wgVersion}, CheckCongressLinks Checker"); $ok = $req->execute()->isOK(); } } } if ($ok) { ++$countOk; } else { $this->output("Broken: [{$name}] [{$url}]\n"); } }
/** * @see RCFeedEngine::send */ public function send(array $feed, $line) { $parsed = wfParseUrl($feed['uri']); $server = $parsed['host']; $options = ['serializer' => 'none']; $channel = 'rc'; if (isset($parsed['port'])) { $server .= ":{$parsed['port']}"; } if (isset($parsed['query'])) { parse_str($parsed['query'], $options); } if (isset($parsed['pass'])) { $options['password'] = $parsed['pass']; } if (isset($parsed['path'])) { $channel = str_replace('/', '.', ltrim($parsed['path'], '/')); } $pool = RedisConnectionPool::singleton($options); $conn = $pool->getConnection($server); if ($conn !== false) { $conn->publish($channel, $line); return true; } else { return false; } }
/** * Determine whether this server is configured as the priority or normal server * * If this is neither the priority nor normal server, assumes 'local' - meaning * this server should be handling the request. */ public function determineLocalServerType() { global $wgServer, $wgLandingCheckPriorityURLBase, $wgLandingCheckNormalURLBase; $localServerDetails = wfParseUrl($wgServer); // The following checks are necessary due to a bug in wfParseUrl that was fixed in r94352. if ($wgLandingCheckPriorityURLBase) { $priorityServerDetails = wfParseUrl($wgLandingCheckPriorityURLBase); } else { $priorityServerDetails = false; } if ($wgLandingCheckNormalURLBase) { $normalServerDetails = wfParseUrl($wgLandingCheckNormalURLBase); } else { $normalServerDetails = false; } //$priorityServerDetails = wfParseUrl( $wgLandingCheckPriorityURLBase ); //$normalServerDetails = wfParseUrl( $wgLandingCheckNormalURLBase ); if ($localServerDetails['host'] == $priorityServerDetails['host']) { return 'priority'; } elseif ($localServerDetails['host'] == $normalServerDetails['host']) { return 'normal'; } else { return 'local'; } }
/** * Provider of URL parts for testing wfAssembleUrl() * * @return array */ public static function provideURLParts() { $schemes = array('' => array(), '//' => array('delimiter' => '//'), 'http://' => array('scheme' => 'http', 'delimiter' => '://')); $hosts = array('' => array(), 'example.com' => array('host' => 'example.com'), 'example.com:123' => array('host' => 'example.com', 'port' => 123), '*****@*****.**' => array('user' => 'id', 'host' => 'example.com'), 'id@example.com:123' => array('user' => 'id', 'host' => 'example.com', 'port' => 123), 'id:key@example.com' => array('user' => 'id', 'pass' => 'key', 'host' => 'example.com'), 'id:key@example.com:123' => array('user' => 'id', 'pass' => 'key', 'host' => 'example.com', 'port' => 123)); $cases = array(); foreach ($schemes as $scheme => $schemeParts) { foreach ($hosts as $host => $hostParts) { foreach (array('', '/path') as $path) { foreach (array('', 'query') as $query) { foreach (array('', 'fragment') as $fragment) { $parts = array_merge($schemeParts, $hostParts); $url = $scheme . $host . $path; if ($path) { $parts['path'] = $path; } if ($query) { $parts['query'] = $query; $url .= '?' . $query; } if ($fragment) { $parts['fragment'] = $fragment; $url .= '#' . $fragment; } $cases[] = array($parts, $url); } } } } } $complexURL = 'http://*****:*****@example.org:321' . '/over/there?name=ferret&foo=bar#nose'; $cases[] = array(wfParseUrl($complexURL), $complexURL); return $cases; }
public function execute() { $params = $this->extractRequestParams(); $this->requireAtLeastOneParameter($params, 'continue', 'returnurl'); if ($params['returnurl'] !== null) { $bits = wfParseUrl($params['returnurl']); if (!$bits || $bits['scheme'] === '') { $encParamName = $this->encodeParamName('returnurl'); $this->dieUsage("Invalid value '{$params['returnurl']}' for url parameter {$encParamName}", "badurl_{$encParamName}"); } } $helper = new ApiAuthManagerHelper($this); $manager = AuthManager::singleton(); // Make sure it's possible to log in if (!$manager->canAuthenticateNow()) { $this->getResult()->addValue(null, 'clientlogin', $helper->formatAuthenticationResponse(AuthenticationResponse::newFail($this->msg('userlogin-cannot-' . AuthManager::ACTION_LOGIN)))); return; } // Perform the login step if ($params['continue']) { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LOGIN_CONTINUE); $res = $manager->continueAuthentication($reqs); } else { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LOGIN); if ($params['preservestate']) { $req = $helper->getPreservedRequest(); if ($req) { $reqs[] = $req; } } $res = $manager->beginAuthentication($reqs, $params['returnurl']); } $this->getResult()->addValue(null, 'clientlogin', $helper->formatAuthenticationResponse($res)); }
/** * @param UUID $srcWorkflow ID of the source Workflow * @param Title $srcTitle Title of the page that the Workflow exists on * @param String $objectType Output of getRevisionType for the AbstractRevision that this reference comes from. * @param UUID $objectId Unique identifier for the revisioned object containing the reference. * @param string $type Type of reference * @param string $url URL of the reference's target. * @throws InvalidReferenceException */ public function __construct(UUID $srcWorkflow, Title $srcTitle, $objectType, UUID $objectId, $type, $url) { $this->url = $url; if (!is_array(wfParseUrl($url))) { throw new InvalidReferenceException("Invalid URL {$url} specified for reference " . get_class($this)); } parent::__construct($srcWorkflow, $srcTitle, $objectType, $objectId, $type); }
/** * Returns the basic hostname and port using wfParseUrl * @param string $url URL to parse * @return string */ public static function getBaseUrl($url) { $parse = wfParseUrl($url); $site = $parse['host']; if (isset($parse['port'])) { $site .= ':' . $parse['port']; } return $site; }
/** * @dataProvider provideDataWatchTopicLink */ public function testUnwatchTopicLink(Title $title, $workflowId) { $anchor = $this->urlGenerator->unwatchTopicLink($title, $workflowId); $this->assertInstanceOf('\\Flow\\Model\\Anchor', $anchor); $link = $anchor->getFullURL(); $option = wfParseUrl($link); $this->assertArrayHasKey('query', $option); parse_str($option['query'], $query); $this->assertEquals('unwatch', $query['action']); }
public function execute($par) { $this->setHeaders(); $this->outputHeader(); $out = $this->getOutput(); $out->allowClickjacking(); $request = $this->getRequest(); $target = $request->getVal('target', $par); $namespace = $request->getIntOrNull('namespace'); $protocols_list = []; foreach ($this->getConfig()->get('UrlProtocols') as $prot) { if ($prot !== '//') { $protocols_list[] = $prot; } } $target2 = $target; // Get protocol, default is http:// $protocol = 'http://'; $bits = wfParseUrl($target); if (isset($bits['scheme']) && isset($bits['delimiter'])) { $protocol = $bits['scheme'] . $bits['delimiter']; // Make sure wfParseUrl() didn't make some well-intended correction in the // protocol if (strcasecmp($protocol, substr($target, 0, strlen($protocol))) === 0) { $target2 = substr($target, strlen($protocol)); } else { // If it did, let LinkFilter::makeLikeArray() handle this $protocol = ''; } } $out->addWikiMsg('linksearch-text', '<nowiki>' . $this->getLanguage()->commaList($protocols_list) . '</nowiki>', count($protocols_list)); $fields = ['target' => ['type' => 'text', 'name' => 'target', 'id' => 'target', 'size' => 50, 'label-message' => 'linksearch-pat', 'default' => $target, 'dir' => 'ltr']]; if (!$this->getConfig()->get('MiserMode')) { $fields += ['namespace' => ['type' => 'namespaceselect', 'name' => 'namespace', 'label-message' => 'linksearch-ns', 'default' => $namespace, 'id' => 'namespace', 'all' => '', 'cssclass' => 'namespaceselector']]; } $hiddenFields = ['title' => $this->getPageTitle()->getPrefixedDBkey()]; $htmlForm = HTMLForm::factory('ooui', $fields, $this->getContext()); $htmlForm->addHiddenFields($hiddenFields); $htmlForm->setSubmitTextMsg('linksearch-ok'); $htmlForm->setWrapperLegendMsg('linksearch'); $htmlForm->setAction(wfScript()); $htmlForm->setMethod('get'); $htmlForm->prepareForm()->displayForm(false); $this->addHelpLink('Help:Linksearch'); if ($target != '') { $this->setParams(['query' => Parser::normalizeLinkUrl($target2), 'namespace' => $namespace, 'protocol' => $protocol]); parent::execute($par); if ($this->mungedQuery === false) { $out->addWikiMsg('linksearch-error'); } } }
/** * @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; }
function execute($par) { global $wgUrlProtocols, $wgMiserMode, $wgScript; $this->setHeaders(); $this->outputHeader(); $out = $this->getOutput(); $out->allowClickjacking(); $request = $this->getRequest(); $target = $request->getVal('target', $par); $namespace = $request->getIntorNull('namespace', null); $protocols_list = array(); foreach ($wgUrlProtocols as $prot) { if ($prot !== '//') { $protocols_list[] = $prot; } } $target2 = $target; // Get protocol, default is http:// $protocol = 'http://'; $bits = wfParseUrl($target); if (isset($bits['scheme']) && isset($bits['delimiter'])) { $protocol = $bits['scheme'] . $bits['delimiter']; // Make sure wfParseUrl() didn't make some well-intended correction in the // protocol if (strcasecmp($protocol, substr($target, 0, strlen($protocol))) === 0) { $target2 = substr($target, strlen($protocol)); } else { // If it did, let LinkFilter::makeLikeArray() handle this $protocol = ''; } } $out->addWikiMsg('linksearch-text', '<nowiki>' . $this->getLanguage()->commaList($protocols_list) . '</nowiki>', count($protocols_list)); $s = Html::openElement('form', array('id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $wgScript)) . "\n" . Html::hidden('title', $this->getPageTitle()->getPrefixedDBkey()) . "\n" . Html::openElement('fieldset') . "\n" . Html::element('legend', array(), $this->msg('linksearch')->text()) . "\n" . Xml::inputLabel($this->msg('linksearch-pat')->text(), 'target', 'target', 50, $target) . "\n"; if (!$wgMiserMode) { $s .= Html::namespaceSelector(array('selected' => $namespace, 'all' => '', 'label' => $this->msg('linksearch-ns')->text()), array('name' => 'namespace', 'id' => 'namespace', 'class' => 'namespaceselector')); } $s .= Xml::submitButton($this->msg('linksearch-ok')->text()) . "\n" . Html::closeElement('fieldset') . "\n" . Html::closeElement('form') . "\n"; $out->addHTML($s); if ($target != '') { $this->setParams(array('query' => $target2, 'namespace' => $namespace, 'protocol' => $protocol)); parent::execute($par); if ($this->mMungedQuery === false) { $out->addWikiMsg('linksearch-error'); } } }
/** * Checks whether the URL is for an allowed host * * @param $url string * @return bool */ public static function isAllowedHost($url) { global $wgCopyUploadsDomains; if (!count($wgCopyUploadsDomains)) { return true; } $parsedUrl = wfParseUrl($url); if (!$parsedUrl) { return false; } $valid = false; foreach ($wgCopyUploadsDomains as $domain) { if ($parsedUrl['host'] === $domain) { $valid = true; break; } } return $valid; }
protected function hitThumbUrl($file, $transformParams) { global $wgUploadThumbnailRenderHttpCustomHost, $wgUploadThumbnailRenderHttpCustomDomain; $thumbName = $file->thumbName($transformParams); $thumbUrl = $file->getThumbUrl($thumbName); if ($wgUploadThumbnailRenderHttpCustomDomain) { $parsedUrl = wfParseUrl($thumbUrl); if (!$parsedUrl || !isset($parsedUrl['path']) || !strlen($parsedUrl['path'])) { return false; } $thumbUrl = '//' . $wgUploadThumbnailRenderHttpCustomDomain . $parsedUrl['path']; } wfDebug(__METHOD__ . ": hitting url {$thumbUrl}\n"); $request = MWHttpRequest::factory($thumbUrl, array('method' => 'HEAD', 'followRedirects' => true), __METHOD__); if ($wgUploadThumbnailRenderHttpCustomHost) { $request->setHeader('Host', $wgUploadThumbnailRenderHttpCustomHost); } $status = $request->execute(); return $request->getStatus(); }
public function execute() { $params = $this->extractRequestParams(); $this->requireAtLeastOneParameter($params, 'continue', 'returnurl'); if ($params['returnurl'] !== null) { $bits = wfParseUrl($params['returnurl']); if (!$bits || $bits['scheme'] === '') { $encParamName = $this->encodeParamName('returnurl'); $this->dieUsage("Invalid value '{$params['returnurl']}' for url parameter {$encParamName}", "badurl_{$encParamName}"); } } $helper = new ApiAuthManagerHelper($this); $manager = AuthManager::singleton(); // Make sure it's possible to log in if (!$manager->canAuthenticateNow()) { $this->getResult()->addValue(null, 'clientlogin', $helper->formatAuthenticationResponse(AuthenticationResponse::newFail($this->msg('userlogin-cannot-' . AuthManager::ACTION_LOGIN)))); $helper->logAuthenticationResult('login', 'userlogin-cannot-' . AuthManager::ACTION_LOGIN); return; } // Perform the login step if ($params['continue']) { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LOGIN_CONTINUE); $res = $manager->continueAuthentication($reqs); } else { $reqs = $helper->loadAuthenticationRequests(AuthManager::ACTION_LOGIN); if ($params['preservestate']) { $req = $helper->getPreservedRequest(); if ($req) { $reqs[] = $req; } } $res = $manager->beginAuthentication($reqs, $params['returnurl']); } // Remove CreateFromLoginAuthenticationRequest from $res->neededRequests. // It's there so a RESTART treated as UI will work right, but showing // it to the API client is just confusing. $res->neededRequests = ApiAuthManagerHelper::blacklistAuthenticationRequests($res->neededRequests, [CreateFromLoginAuthenticationRequest::class]); $this->getResult()->addValue(null, 'clientlogin', $helper->formatAuthenticationResponse($res)); $helper->logAuthenticationResult('login', $res); }
/** * Checks whether the URL is for an allowed host * The domains in the whitelist can include wildcard characters (*) in place * of any of the domain levels, e.g. '*.flickr.com' or 'upload.*.gov.uk'. * * @param string $url * @return bool */ public static function isAllowedHost($url) { global $wgCopyUploadsDomains; if (!count($wgCopyUploadsDomains)) { return true; } $parsedUrl = wfParseUrl($url); if (!$parsedUrl) { return false; } $valid = false; foreach ($wgCopyUploadsDomains as $domain) { // See if the domain for the upload matches this whitelisted domain $whitelistedDomainPieces = explode('.', $domain); $uploadDomainPieces = explode('.', $parsedUrl['host']); if (count($whitelistedDomainPieces) === count($uploadDomainPieces)) { $valid = true; // See if all the pieces match or not (excluding wildcards) foreach ($whitelistedDomainPieces as $index => $piece) { if ($piece !== '*' && $piece !== $uploadDomainPieces[$index]) { $valid = false; } } if ($valid) { // We found a match, so quit comparing against the list break; } } /* Non-wildcard test if ( $parsedUrl['host'] === $domain ) { $valid = true; break; } */ } return $valid; }
/** * Create a value suitable for the MessageId Header * * @return string */ static function makeMsgId() { global $wgSMTP, $wgServer; $msgid = uniqid(wfWikiID() . ".", true); /* true required for cygwin */ if (is_array($wgSMTP) && isset($wgSMTP['IDHost']) && $wgSMTP['IDHost']) { $domain = $wgSMTP['IDHost']; } else { $url = wfParseUrl($wgServer); $domain = $url['host']; } return "<{$msgid}@{$domain}>"; }
/** * Get an associative array of additional HTML attributes appropriate for a * particular external link. This currently may include rel => nofollow * (depending on configuration, namespace, and the URL's domain) and/or a * target attribute (depending on configuration). * * @param string $url Optional URL, to extract the domain from for rel => * nofollow if appropriate * @return array Associative array of HTML attributes */ function getExternalLinkAttribs($url = false) { $attribs = array(); global $wgNoFollowLinks, $wgNoFollowNsExceptions; $ns = $this->mTitle->getNamespace(); if ($wgNoFollowLinks && !in_array($ns, $wgNoFollowNsExceptions)) { $attribs['rel'] = 'nofollow'; global $wgNoFollowDomainExceptions; if ($wgNoFollowDomainExceptions) { $bits = wfParseUrl($url); if (is_array($bits) && isset($bits['host'])) { foreach ($wgNoFollowDomainExceptions as $domain) { if (substr($bits['host'], -strlen($domain)) == $domain) { unset($attribs['rel']); break; } } } } } if ($this->mOptions->getExternalLinkTarget()) { $attribs['target'] = $this->mOptions->getExternalLinkTarget(); } return $attribs; }
/** * Show single interwiki link * * @param $result SearchResult * @param $lastInterwiki String * @param $terms Array * @param $query String * @param array $customCaptions iw prefix -> caption * * @return string */ protected function showInterwikiHit( $result, $lastInterwiki, $terms, $query, $customCaptions ) { wfProfileIn( __METHOD__ ); if ( $result->isBrokenTitle() ) { wfProfileOut( __METHOD__ ); return "<!-- Broken link in search result -->\n"; } $t = $result->getTitle(); $titleSnippet = $result->getTitleSnippet( $terms ); if ( $titleSnippet == '' ) { $titleSnippet = null; } $link = Linker::linkKnown( $t, $titleSnippet ); // format redirect if any $redirectTitle = $result->getRedirectTitle(); $redirectText = $result->getRedirectSnippet( $terms ); $redirect = ''; if ( !is_null( $redirectTitle ) ) { if ( $redirectText == '' ) { $redirectText = null; } $redirect = "<span class='searchalttitle'>" . $this->msg( 'search-redirect' )->rawParams( Linker::linkKnown( $redirectTitle, $redirectText ) )->text() . "</span>"; } $out = ""; // display project name if ( is_null( $lastInterwiki ) || $lastInterwiki != $t->getInterwiki() ) { if ( array_key_exists( $t->getInterwiki(), $customCaptions ) ) { // captions from 'search-interwiki-custom' $caption = $customCaptions[$t->getInterwiki()]; } else { // default is to show the hostname of the other wiki which might suck // if there are many wikis on one hostname $parsed = wfParseUrl( $t->getFullURL() ); $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text(); } // "more results" link (special page stuff could be localized, but we might not know target lang) $searchTitle = Title::newFromText( $t->getInterwiki() . ":Special:Search" ); $searchLink = Linker::linkKnown( $searchTitle, $this->msg( 'search-interwiki-more' )->text(), array(), array( 'search' => $query, 'fulltext' => 'Search' ) ); $out .= "</ul><div class='mw-search-interwiki-project'><span class='mw-search-interwiki-more'> {$searchLink}</span>{$caption}</div>\n<ul>"; } $out .= "<li>{$link} {$redirect}</li>\n"; wfProfileOut( __METHOD__ ); return $out; }
/** * Queue a purge operation * * @param string $url */ public function queuePurge($url) { global $wgSquidPurgeUseHostHeader; $url = SquidUpdate::expand(str_replace("\n", '', $url)); $request = array(); if ($wgSquidPurgeUseHostHeader) { $url = wfParseUrl($url); $host = $url['host']; if (isset($url['port']) && strlen($url['port']) > 0) { $host .= ":" . $url['port']; } $path = $url['path']; if (isset($url['query']) && is_string($url['query'])) { $path = wfAppendQuery($path, $url['query']); } $request[] = "PURGE {$path} HTTP/1.1"; $request[] = "Host: {$host}"; } else { $request[] = "PURGE {$url} HTTP/1.0"; } $request[] = "Connection: Keep-Alive"; $request[] = "Proxy-Connection: Keep-Alive"; $request[] = "User-Agent: " . Http::userAgent() . ' ' . __CLASS__; // Two ''s to create \r\n\r\n $request[] = ''; $request[] = ''; $this->requests[] = implode("\r\n", $request); if ($this->currentRequestIndex === null) { $this->nextRequest(); } }
/** * Return value of a magic variable (like PAGENAME) * * @private * * @param $index integer * @param $frame PPFrame */ function getVariableValue($index, $frame = false) { global $wgContLang, $wgSitename, $wgServer; global $wgArticlePath, $wgScriptPath, $wgStylePath; /** * Some of these require message or data lookups and can be * expensive to check many times. */ if (wfRunHooks('ParserGetVariableValueVarCache', array(&$this, &$this->mVarCache))) { if (isset($this->mVarCache[$index])) { return $this->mVarCache[$index]; } } $ts = wfTimestamp(TS_UNIX, $this->mOptions->getTimestamp()); wfRunHooks('ParserGetVariableValueTs', array(&$this, &$ts)); # Use the time zone global $wgLocaltimezone; if (isset($wgLocaltimezone)) { $oldtz = date_default_timezone_get(); date_default_timezone_set($wgLocaltimezone); } $localTimestamp = date('YmdHis', $ts); $localMonth = date('m', $ts); $localMonth1 = date('n', $ts); $localMonthName = date('n', $ts); $localDay = date('j', $ts); $localDay2 = date('d', $ts); $localDayOfWeek = date('w', $ts); $localWeek = date('W', $ts); $localYear = date('Y', $ts); $localHour = date('H', $ts); if (isset($wgLocaltimezone)) { date_default_timezone_set($oldtz); } switch ($index) { case 'currentmonth': $value = $wgContLang->formatNum(gmdate('m', $ts)); break; case 'currentmonth1': $value = $wgContLang->formatNum(gmdate('n', $ts)); break; case 'currentmonthname': $value = $wgContLang->getMonthName(gmdate('n', $ts)); break; case 'currentmonthnamegen': $value = $wgContLang->getMonthNameGen(gmdate('n', $ts)); break; case 'currentmonthabbrev': $value = $wgContLang->getMonthAbbreviation(gmdate('n', $ts)); break; case 'currentday': $value = $wgContLang->formatNum(gmdate('j', $ts)); break; case 'currentday2': $value = $wgContLang->formatNum(gmdate('d', $ts)); break; case 'localmonth': $value = $wgContLang->formatNum($localMonth); break; case 'localmonth1': $value = $wgContLang->formatNum($localMonth1); break; case 'localmonthname': $value = $wgContLang->getMonthName($localMonthName); break; case 'localmonthnamegen': $value = $wgContLang->getMonthNameGen($localMonthName); break; case 'localmonthabbrev': $value = $wgContLang->getMonthAbbreviation($localMonthName); break; case 'localday': $value = $wgContLang->formatNum($localDay); break; case 'localday2': $value = $wgContLang->formatNum($localDay2); break; case 'pagename': $value = wfEscapeWikiText($this->mTitle->getText()); break; case 'pagenamee': $value = wfEscapeWikiText($this->mTitle->getPartialURL()); break; case 'fullpagename': $value = wfEscapeWikiText($this->mTitle->getPrefixedText()); break; case 'fullpagenamee': $value = wfEscapeWikiText($this->mTitle->getPrefixedURL()); break; case 'subpagename': $value = wfEscapeWikiText($this->mTitle->getSubpageText()); break; case 'subpagenamee': $value = wfEscapeWikiText($this->mTitle->getSubpageUrlForm()); break; case 'basepagename': $value = wfEscapeWikiText($this->mTitle->getBaseText()); break; case 'basepagenamee': $value = wfEscapeWikiText(wfUrlEncode(str_replace(' ', '_', $this->mTitle->getBaseText()))); break; case 'talkpagename': if ($this->mTitle->canTalk()) { $talkPage = $this->mTitle->getTalkPage(); $value = wfEscapeWikiText($talkPage->getPrefixedText()); } else { $value = ''; } break; case 'talkpagenamee': if ($this->mTitle->canTalk()) { $talkPage = $this->mTitle->getTalkPage(); $value = wfEscapeWikiText($talkPage->getPrefixedUrl()); } else { $value = ''; } break; case 'subjectpagename': $subjPage = $this->mTitle->getSubjectPage(); $value = wfEscapeWikiText($subjPage->getPrefixedText()); break; case 'subjectpagenamee': $subjPage = $this->mTitle->getSubjectPage(); $value = wfEscapeWikiText($subjPage->getPrefixedUrl()); break; case 'revisionid': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONID}} used, setting vary-revision...\n"); $value = $this->mRevisionId; break; case 'revisionday': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONDAY}} used, setting vary-revision...\n"); $value = intval(substr($this->getRevisionTimestamp(), 6, 2)); break; case 'revisionday2': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONDAY2}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 6, 2); break; case 'revisionmonth': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONMONTH}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 4, 2); break; case 'revisionmonth1': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONMONTH1}} used, setting vary-revision...\n"); $value = intval(substr($this->getRevisionTimestamp(), 4, 2)); break; case 'revisionyear': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONYEAR}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 0, 4); break; case 'revisiontimestamp': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONTIMESTAMP}} used, setting vary-revision...\n"); $value = $this->getRevisionTimestamp(); break; case 'revisionuser': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONUSER}} used, setting vary-revision...\n"); $value = $this->getRevisionUser(); break; case 'namespace': $value = str_replace('_', ' ', $wgContLang->getNsText($this->mTitle->getNamespace())); break; case 'namespacee': $value = wfUrlencode($wgContLang->getNsText($this->mTitle->getNamespace())); break; case 'talkspace': $value = $this->mTitle->canTalk() ? str_replace('_', ' ', $this->mTitle->getTalkNsText()) : ''; break; case 'talkspacee': $value = $this->mTitle->canTalk() ? wfUrlencode($this->mTitle->getTalkNsText()) : ''; break; case 'subjectspace': $value = $this->mTitle->getSubjectNsText(); break; case 'subjectspacee': $value = wfUrlencode($this->mTitle->getSubjectNsText()); break; case 'currentdayname': $value = $wgContLang->getWeekdayName(gmdate('w', $ts) + 1); break; case 'currentyear': $value = $wgContLang->formatNum(gmdate('Y', $ts), true); break; case 'currenttime': $value = $wgContLang->time(wfTimestamp(TS_MW, $ts), false, false); break; case 'currenthour': $value = $wgContLang->formatNum(gmdate('H', $ts), true); break; case 'currentweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding $value = $wgContLang->formatNum((int) gmdate('W', $ts)); break; case 'currentdow': $value = $wgContLang->formatNum(gmdate('w', $ts)); break; case 'localdayname': $value = $wgContLang->getWeekdayName($localDayOfWeek + 1); break; case 'localyear': $value = $wgContLang->formatNum($localYear, true); break; case 'localtime': $value = $wgContLang->time($localTimestamp, false, false); break; case 'localhour': $value = $wgContLang->formatNum($localHour, true); break; case 'localweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding $value = $wgContLang->formatNum((int) $localWeek); break; case 'localdow': $value = $wgContLang->formatNum($localDayOfWeek); break; case 'numberofarticles': $value = $wgContLang->formatNum(SiteStats::articles()); break; case 'numberoffiles': $value = $wgContLang->formatNum(SiteStats::images()); break; case 'numberofusers': $value = $wgContLang->formatNum(SiteStats::users()); break; case 'numberofactiveusers': $value = $wgContLang->formatNum(SiteStats::activeUsers()); break; case 'numberofpages': $value = $wgContLang->formatNum(SiteStats::pages()); break; case 'numberofadmins': $value = $wgContLang->formatNum(SiteStats::numberingroup('sysop')); break; case 'numberofedits': $value = $wgContLang->formatNum(SiteStats::edits()); break; case 'numberofviews': $value = $wgContLang->formatNum(SiteStats::views()); break; case 'currenttimestamp': $value = wfTimestamp(TS_MW, $ts); break; case 'localtimestamp': $value = $localTimestamp; break; case 'currentversion': $value = SpecialVersion::getVersion(); break; case 'articlepath': return $wgArticlePath; case 'sitename': return $wgSitename; case 'server': return $wgServer; case 'servername': $serverParts = wfParseUrl($wgServer); return $serverParts && isset($serverParts['host']) ? $serverParts['host'] : $wgServer; case 'scriptpath': return $wgScriptPath; case 'stylepath': return $wgStylePath; case 'directionmark': return $wgContLang->getDirMark(); case 'contentlanguage': global $wgLanguageCode; return $wgLanguageCode; default: $ret = null; if (wfRunHooks('ParserGetVariableValueSwitch', array(&$this, &$this->mVarCache, &$index, &$ret, &$frame))) { return $ret; } else { return null; } } if ($index) { $this->mVarCache[$index] = $value; } return $value; }
function doSubmit() { global $wgContLang; $request = $this->getRequest(); $prefix = $request->getVal('wpInterwikiPrefix'); $do = $request->getVal('wpInterwikiAction'); // Show an error if the prefix is invalid (only when adding one). // Invalid characters for a title should also be invalid for a prefix. // Whitespace, ':', '&' and '=' are invalid, too. // (Bug 30599). global $wgLegalTitleChars; $validPrefixChars = preg_replace('/[ :&=]/', '', $wgLegalTitleChars); if (preg_match("/\\s|[^{$validPrefixChars}]/", $prefix) && $do === 'add') { $this->error('interwiki-badprefix', htmlspecialchars($prefix)); $this->showForm($do); return; } $reason = $request->getText('wpInterwikiReason'); $selfTitle = $this->getPageTitle(); $dbw = wfGetDB(DB_MASTER); switch ($do) { case 'delete': $dbw->delete('interwiki', array('iw_prefix' => $prefix), __METHOD__); if ($dbw->affectedRows() === 0) { $this->error('interwiki_delfailed', $prefix); $this->showForm($do); } else { $this->getOutput()->addWikiMsg('interwiki_deleted', $prefix); $log = new LogPage('interwiki'); $log->addEntry('iw_delete', $selfTitle, $reason, array($prefix)); Interwiki::invalidateCache($prefix); } break; case 'add': $prefix = $wgContLang->lc($prefix); // N.B.: no break! // N.B.: no break! case 'edit': $theurl = $request->getVal('wpInterwikiURL'); $local = $request->getCheck('wpInterwikiLocal') ? 1 : 0; $trans = $request->getCheck('wpInterwikiTrans') ? 1 : 0; $data = array('iw_prefix' => $prefix, 'iw_url' => $theurl, 'iw_local' => $local, 'iw_trans' => $trans); if ($prefix === '' || $theurl === '') { $this->error('interwiki-submit-empty'); $this->showForm($do); return; } // Simple URL validation: check that the protocol is one of // the supported protocols for this wiki. // (bug 30600) if (!wfParseUrl($theurl)) { $this->error('interwiki-submit-invalidurl'); $this->showForm($do); return; } if ($do === 'add') { $dbw->insert('interwiki', $data, __METHOD__, 'IGNORE'); } else { // $do === 'edit' $dbw->update('interwiki', $data, array('iw_prefix' => $prefix), __METHOD__, 'IGNORE'); } // used here: interwiki_addfailed, interwiki_added, interwiki_edited if ($dbw->affectedRows() === 0) { $this->error("interwiki_{$do}failed", $prefix); $this->showForm($do); } else { $this->getOutput()->addWikiMsg("interwiki_{$do}ed", $prefix); $log = new LogPage('interwiki'); $log->addEntry('iw_' . $do, $selfTitle, $reason, array($prefix, $theurl, $trans, $local)); Interwiki::invalidateCache($prefix); } break; } }
/** * Potentially open a socket and sent an HTTP request back to the server * to run a specified number of jobs. This registers a callback to cleanup * the socket once it's done. */ protected function triggerJobs() { global $wgJobRunRate, $wgServer, $wgRunJobsAsync; if ($wgJobRunRate <= 0 || wfReadOnly()) { return; } elseif ($this->getTitle()->isSpecial('RunJobs')) { return; // recursion guard } $section = new ProfileSection(__METHOD__); if ($wgJobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $wgJobRunRate) { return; // the higher $wgJobRunRate, the less likely we return here } $n = 1; } else { $n = intval($wgJobRunRate); } if (!$wgRunJobsAsync) { // If running jobs asynchronously has been disabled, run the job here // while the user waits SpecialRunJobs::executeJobs($n); return; } if (!JobQueueGroup::singleton()->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) { return; // do not send request if there are probably no jobs } $query = array('title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5); $query['signature'] = SpecialRunJobs::getQuerySignature($query); $errno = $errstr = null; $info = wfParseUrl($wgServer); wfSuppressWarnings(); $sock = fsockopen($info['host'], isset($info['port']) ? $info['port'] : 80, $errno, $errstr, 0.1); wfRestoreWarnings(); if (!$sock) { wfDebugLog('runJobs', "Failed to start cron API (socket error {$errno}): {$errstr}\n"); // Fall back to running the job here while the user waits SpecialRunJobs::executeJobs($n); return; } $url = wfAppendQuery(wfScript('index'), $query); $req = "POST {$url} HTTP/1.1\r\nHost: {$info['host']}\r\nConnection: Close\r\nContent-Length: 0\r\n\r\n"; wfDebugLog('runJobs', "Running {$n} job(s) via '{$url}'\n"); // Send a cron API request to be performed in the background. // Give up if this takes too long to send (which should be rare). stream_set_timeout($sock, 1); $bytes = fwrite($sock, $req); if ($bytes !== strlen($req)) { wfDebugLog('runJobs', "Failed to start cron API (socket write error)\n"); } else { // Do not wait for the response (the script should handle client aborts). // Make sure that we don't close before that script reaches ignore_user_abort(). $status = fgets($sock); if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) { wfDebugLog('runJobs', "Failed to start cron API: received '{$status}'\n"); } } fclose($sock); }
/** * Return value of a magic variable (like PAGENAME) * * @private * * @param $index integer * @param bool|\PPFrame $frame * * @throws MWException * @return string */ function getVariableValue($index, $frame = false) { global $wgContLang, $wgSitename, $wgServer; global $wgArticlePath, $wgScriptPath, $wgStylePath; if (is_null($this->mTitle)) { // If no title set, bad things are going to happen // later. Title should always be set since this // should only be called in the middle of a parse // operation (but the unit-tests do funky stuff) throw new MWException(__METHOD__ . ' Should only be ' . ' called while parsing (no title set)'); } /** * Some of these require message or data lookups and can be * expensive to check many times. */ if (wfRunHooks('ParserGetVariableValueVarCache', array(&$this, &$this->mVarCache))) { if (isset($this->mVarCache[$index])) { return $this->mVarCache[$index]; } } $ts = wfTimestamp(TS_UNIX, $this->mOptions->getTimestamp()); wfRunHooks('ParserGetVariableValueTs', array(&$this, &$ts)); $pageLang = $this->getFunctionLang(); switch ($index) { case 'currentmonth': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('m')); break; case 'currentmonth1': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('n')); break; case 'currentmonthname': $value = $pageLang->getMonthName(MWTimestamp::getInstance($ts)->format('n')); break; case 'currentmonthnamegen': $value = $pageLang->getMonthNameGen(MWTimestamp::getInstance($ts)->format('n')); break; case 'currentmonthabbrev': $value = $pageLang->getMonthAbbreviation(MWTimestamp::getInstance($ts)->format('n')); break; case 'currentday': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('j')); break; case 'currentday2': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('d')); break; case 'localmonth': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('m')); break; case 'localmonth1': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('n')); break; case 'localmonthname': $value = $pageLang->getMonthName(MWTimestamp::getLocalInstance($ts)->format('n')); break; case 'localmonthnamegen': $value = $pageLang->getMonthNameGen(MWTimestamp::getLocalInstance($ts)->format('n')); break; case 'localmonthabbrev': $value = $pageLang->getMonthAbbreviation(MWTimestamp::getLocalInstance($ts)->format('n')); break; case 'localday': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('j')); break; case 'localday2': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('d')); break; case 'pagename': $value = wfEscapeWikiText($this->mTitle->getText()); break; case 'pagenamee': $value = wfEscapeWikiText($this->mTitle->getPartialURL()); break; case 'fullpagename': $value = wfEscapeWikiText($this->mTitle->getPrefixedText()); break; case 'fullpagenamee': $value = wfEscapeWikiText($this->mTitle->getPrefixedURL()); break; case 'subpagename': $value = wfEscapeWikiText($this->mTitle->getSubpageText()); break; case 'subpagenamee': $value = wfEscapeWikiText($this->mTitle->getSubpageUrlForm()); break; case 'rootpagename': $value = wfEscapeWikiText($this->mTitle->getRootText()); break; case 'rootpagenamee': $value = wfEscapeWikiText(wfUrlEncode(str_replace(' ', '_', $this->mTitle->getRootText()))); break; case 'basepagename': $value = wfEscapeWikiText($this->mTitle->getBaseText()); break; case 'basepagenamee': $value = wfEscapeWikiText(wfUrlEncode(str_replace(' ', '_', $this->mTitle->getBaseText()))); break; case 'talkpagename': if ($this->mTitle->canTalk()) { $talkPage = $this->mTitle->getTalkPage(); $value = wfEscapeWikiText($talkPage->getPrefixedText()); } else { $value = ''; } break; case 'talkpagenamee': if ($this->mTitle->canTalk()) { $talkPage = $this->mTitle->getTalkPage(); $value = wfEscapeWikiText($talkPage->getPrefixedURL()); } else { $value = ''; } break; case 'subjectpagename': $subjPage = $this->mTitle->getSubjectPage(); $value = wfEscapeWikiText($subjPage->getPrefixedText()); break; case 'subjectpagenamee': $subjPage = $this->mTitle->getSubjectPage(); $value = wfEscapeWikiText($subjPage->getPrefixedURL()); break; case 'pageid': // requested in bug 23427 $pageid = $this->getTitle()->getArticleID(); if ($pageid == 0) { # 0 means the page doesn't exist in the database, # which means the user is previewing a new page. # The vary-revision flag must be set, because the magic word # will have a different value once the page is saved. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{PAGEID}} used in a new page, setting vary-revision...\n"); } $value = $pageid ? $pageid : null; break; case 'revisionid': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONID}} used, setting vary-revision...\n"); $value = $this->mRevisionId; break; case 'revisionday': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONDAY}} used, setting vary-revision...\n"); $value = intval(substr($this->getRevisionTimestamp(), 6, 2)); break; case 'revisionday2': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONDAY2}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 6, 2); break; case 'revisionmonth': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONMONTH}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 4, 2); break; case 'revisionmonth1': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONMONTH1}} used, setting vary-revision...\n"); $value = intval(substr($this->getRevisionTimestamp(), 4, 2)); break; case 'revisionyear': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONYEAR}} used, setting vary-revision...\n"); $value = substr($this->getRevisionTimestamp(), 0, 4); break; case 'revisiontimestamp': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONTIMESTAMP}} used, setting vary-revision...\n"); $value = $this->getRevisionTimestamp(); break; case 'revisionuser': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONUSER}} used, setting vary-revision...\n"); $value = $this->getRevisionUser(); break; case 'revisionsize': # Let the edit saving system know we should parse the page # *after* a revision ID has been assigned. This is for null edits. $this->mOutput->setFlag('vary-revision'); wfDebug(__METHOD__ . ": {{REVISIONSIZE}} used, setting vary-revision...\n"); $value = $this->getRevisionSize(); break; case 'namespace': $value = str_replace('_', ' ', $wgContLang->getNsText($this->mTitle->getNamespace())); break; case 'namespacee': $value = wfUrlencode($wgContLang->getNsText($this->mTitle->getNamespace())); break; case 'namespacenumber': $value = $this->mTitle->getNamespace(); break; case 'talkspace': $value = $this->mTitle->canTalk() ? str_replace('_', ' ', $this->mTitle->getTalkNsText()) : ''; break; case 'talkspacee': $value = $this->mTitle->canTalk() ? wfUrlencode($this->mTitle->getTalkNsText()) : ''; break; case 'subjectspace': $value = str_replace('_', ' ', $this->mTitle->getSubjectNsText()); break; case 'subjectspacee': $value = wfUrlencode($this->mTitle->getSubjectNsText()); break; case 'currentdayname': $value = $pageLang->getWeekdayName((int) MWTimestamp::getInstance($ts)->format('w') + 1); break; case 'currentyear': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('Y'), true); break; case 'currenttime': $value = $pageLang->time(wfTimestamp(TS_MW, $ts), false, false); break; case 'currenthour': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('H'), true); break; case 'currentweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding $value = $pageLang->formatNum((int) MWTimestamp::getInstance($ts)->format('W')); break; case 'currentdow': $value = $pageLang->formatNum(MWTimestamp::getInstance($ts)->format('w')); break; case 'localdayname': $value = $pageLang->getWeekdayName((int) MWTimestamp::getLocalInstance($ts)->format('w') + 1); break; case 'localyear': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('Y'), true); break; case 'localtime': $value = $pageLang->time(MWTimestamp::getLocalInstance($ts)->format('YmdHis'), false, false); break; case 'localhour': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('H'), true); break; case 'localweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding $value = $pageLang->formatNum((int) MWTimestamp::getLocalInstance($ts)->format('W')); break; case 'localdow': $value = $pageLang->formatNum(MWTimestamp::getLocalInstance($ts)->format('w')); break; case 'numberofarticles': $value = $pageLang->formatNum(SiteStats::articles()); break; case 'numberoffiles': $value = $pageLang->formatNum(SiteStats::images()); break; case 'numberofusers': $value = $pageLang->formatNum(SiteStats::users()); break; case 'numberofactiveusers': $value = $pageLang->formatNum(SiteStats::activeUsers()); break; case 'numberofpages': $value = $pageLang->formatNum(SiteStats::pages()); break; case 'numberofadmins': $value = $pageLang->formatNum(SiteStats::numberingroup('sysop')); break; case 'numberofedits': $value = $pageLang->formatNum(SiteStats::edits()); break; case 'numberofviews': global $wgDisableCounters; $value = !$wgDisableCounters ? $pageLang->formatNum(SiteStats::views()) : ''; break; case 'currenttimestamp': $value = wfTimestamp(TS_MW, $ts); break; case 'localtimestamp': $value = MWTimestamp::getLocalInstance($ts)->format('YmdHis'); break; case 'currentversion': $value = SpecialVersion::getVersion(); break; case 'articlepath': return $wgArticlePath; case 'sitename': return $wgSitename; case 'server': return $wgServer; case 'servername': $serverParts = wfParseUrl($wgServer); return $serverParts && isset($serverParts['host']) ? $serverParts['host'] : $wgServer; case 'scriptpath': return $wgScriptPath; case 'stylepath': return $wgStylePath; case 'directionmark': return $pageLang->getDirMark(); case 'contentlanguage': global $wgLanguageCode; return $wgLanguageCode; case 'cascadingsources': $value = CoreParserFunctions::cascadingsources($this); break; default: $ret = null; wfRunHooks('ParserGetVariableValueSwitch', array(&$this, &$this->mVarCache, &$index, &$ret, &$frame)); return $ret; } if ($index) { $this->mVarCache[$index] = $value; } return $value; }
/** * Make an array to be used for calls to Database::buildLike(), which * will match the specified string. There are several kinds of filter entry: * *.domain.com - Produces http://com.domain.%, matches domain.com * and www.domain.com * domain.com - Produces http://com.domain./%, matches domain.com * or domain.com/ but not www.domain.com * *.domain.com/x - Produces http://com.domain.%/x%, matches * www.domain.com/xy * domain.com/x - Produces http://com.domain./x%, matches * domain.com/xy but not www.domain.com/xy * * Asterisks in any other location are considered invalid. * * This function does the same as wfMakeUrlIndexes(), except it also takes care * of adding wildcards * * @param string $filterEntry Domainparts * @param string $protocol Protocol (default http://) * @return array|bool Array to be passed to Database::buildLike() or false on error */ public static function makeLikeArray($filterEntry, $protocol = 'http://') { $db = wfGetDB(DB_REPLICA); $target = $protocol . $filterEntry; $bits = wfParseUrl($target); if ($bits == false) { // Unknown protocol? return false; } if (substr($bits['host'], 0, 2) == '*.') { $subdomains = true; $bits['host'] = substr($bits['host'], 2); if ($bits['host'] == '') { // We don't want to make a clause that will match everything, // that could be dangerous return false; } } else { $subdomains = false; } // Reverse the labels in the hostname, convert to lower case // For emails reverse domainpart only if ($bits['scheme'] === 'mailto' && strpos($bits['host'], '@')) { // complete email address $mailparts = explode('@', $bits['host']); $domainpart = strtolower(implode('.', array_reverse(explode('.', $mailparts[1])))); $bits['host'] = $domainpart . '@' . $mailparts[0]; } elseif ($bits['scheme'] === 'mailto') { // domainpart of email address only, do not add '.' $bits['host'] = strtolower(implode('.', array_reverse(explode('.', $bits['host'])))); } else { $bits['host'] = strtolower(implode('.', array_reverse(explode('.', $bits['host'])))); if (substr($bits['host'], -1, 1) !== '.') { $bits['host'] .= '.'; } } $like[] = $bits['scheme'] . $bits['delimiter'] . $bits['host']; if ($subdomains) { $like[] = $db->anyString(); } if (isset($bits['port'])) { $like[] = ':' . $bits['port']; } if (isset($bits['path'])) { $like[] = $bits['path']; } elseif (!$subdomains) { $like[] = '/'; } if (isset($bits['query'])) { $like[] = '?' . $bits['query']; } if (isset($bits['fragment'])) { $like[] = '#' . $bits['fragment']; } // Check for stray asterisks: asterisk only allowed at the start of the domain foreach ($like as $likepart) { if (!$likepart instanceof LikeMatch && strpos($likepart, '*') !== false) { return false; } } if (!$like[count($like) - 1] instanceof LikeMatch) { // Add wildcard at the end if there isn't one already $like[] = $db->anyString(); } return $like; }
MWExceptionHandler::installHandler(); require_once "{$IP}/includes/compat/normal/UtfNormalUtil.php"; $ps_validation = Profiler::instance()->scopedProfileIn($fname . '-validation'); // T48998: Bail out early if $wgArticlePath is non-absolute foreach (['wgArticlePath', 'wgVariantArticlePath'] as $varName) { if (${$varName} && !preg_match('/^(https?:\\/\\/|\\/)/', ${$varName})) { throw new FatalError("If you use a relative URL for \${$varName}, it must start " . 'with a slash (<code>/</code>).<br><br>See ' . "<a href=\"https://www.mediawiki.org/wiki/Manual:\${$varName}\">" . "https://www.mediawiki.org/wiki/Manual:\${$varName}</a>."); } } Profiler::instance()->scopedProfileOut($ps_validation); $ps_default2 = Profiler::instance()->scopedProfileIn($fname . '-defaults2'); if ($wgCanonicalServer === false) { $wgCanonicalServer = wfExpandUrl($wgServer, PROTO_HTTP); } // Set server name $serverParts = wfParseUrl($wgCanonicalServer); if ($wgServerName !== false) { wfWarn('$wgServerName should be derived from $wgCanonicalServer, ' . 'not customized. Overwriting $wgServerName.'); } $wgServerName = $serverParts['host']; unset($serverParts); // Set defaults for configuration variables // that are derived from the server name by default // Note: $wgEmergencyContact and $wgPasswordSender may be false or empty string (T104142) if (!$wgEmergencyContact) { $wgEmergencyContact = 'wikiadmin@' . $wgServerName; } if (!$wgPasswordSender) { $wgPasswordSender = 'apache@' . $wgServerName; } if (!$wgNoReplyAddress) {
/** * Check whether a given URL has a domain that occurs in a given set of domains * @param string $url URL * @param array $domains Array of domains (strings) * @return bool True if the host part of $url ends in one of the strings in $domains */ function wfMatchesDomainList($url, $domains) { $bits = wfParseUrl($url); if (is_array($bits) && isset($bits['host'])) { $host = '.' . $bits['host']; foreach ((array) $domains as $domain) { $domain = '.' . $domain; if (substr($host, -strlen($domain)) === $domain) { return true; } } } return false; }
/** * Potentially open a socket and sent an HTTP request back to the server * to run a specified number of jobs. This registers a callback to cleanup * the socket once it's done. */ public function triggerJobs() { $jobRunRate = $this->config->get('JobRunRate'); if ($this->getTitle()->isSpecial('RunJobs')) { return; // recursion guard } elseif ($jobRunRate <= 0 || wfReadOnly()) { return; } if ($jobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $jobRunRate) { return; // the higher the job run rate, the less likely we return here } $n = 1; } else { $n = intval($jobRunRate); } $runJobsLogger = LoggerFactory::getInstance('runJobs'); // Fall back to running the job(s) while the user waits if needed if (!$this->config->get('RunJobsAsync')) { $runner = new JobRunner($runJobsLogger); $runner->run(['maxJobs' => $n]); return; } // Do not send request if there are probably no jobs try { $group = JobQueueGroup::singleton(); if (!$group->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) { return; } } catch (JobQueueError $e) { MWExceptionHandler::logException($e); return; // do not make the site unavailable } $query = ['title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5]; $query['signature'] = SpecialRunJobs::getQuerySignature($query, $this->config->get('SecretKey')); $errno = $errstr = null; $info = wfParseUrl($this->config->get('CanonicalServer')); $host = $info ? $info['host'] : null; $port = 80; if (isset($info['scheme']) && $info['scheme'] == 'https') { $host = "tls://" . $host; $port = 443; } if (isset($info['port'])) { $port = $info['port']; } MediaWiki\suppressWarnings(); $sock = $host ? fsockopen($host, $port, $errno, $errstr, 0.1) : false; MediaWiki\restoreWarnings(); $invokedWithSuccess = true; if ($sock) { $special = SpecialPageFactory::getPage('RunJobs'); $url = $special->getPageTitle()->getCanonicalURL($query); $req = "POST {$url} HTTP/1.1\r\n" . "Host: {$info['host']}\r\n" . "Connection: Close\r\n" . "Content-Length: 0\r\n\r\n"; $runJobsLogger->info("Running {$n} job(s) via '{$url}'"); // Send a cron API request to be performed in the background. // Give up if this takes too long to send (which should be rare). stream_set_timeout($sock, 2); $bytes = fwrite($sock, $req); if ($bytes !== strlen($req)) { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API (socket write error)"); } else { // Do not wait for the response (the script should handle client aborts). // Make sure that we don't close before that script reaches ignore_user_abort(). $start = microtime(true); $status = fgets($sock); $sec = microtime(true) - $start; if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API: received '{$status}' ({$sec})"); } } fclose($sock); } else { $invokedWithSuccess = false; $runJobsLogger->error("Failed to start cron API (socket error {$errno}): {$errstr}"); } // Fall back to running the job(s) while the user waits if needed if (!$invokedWithSuccess) { $runJobsLogger->warning("Jobs switched to blocking; Special:RunJobs disabled"); $runner = new JobRunner($runJobsLogger); $runner->run(['maxJobs' => $n]); } }
/** * CentralAuthSilentLoginRedirect hook handler * Points redirects from CentralAuth wiki to mobile domain if user has logged in from it * @see SpecialCentralLogin in CentralAuth extension * @param CentralAuthUser $centralUser * @param string $url to redirect to * @param array $info token information * * @return bool */ public static function onCentralAuthSilentLoginRedirect($centralUser, &$url, $info) { if (isset($info['mobileServer'])) { $mobileUrlParsed = wfParseUrl($info['mobileServer']); $urlParsed = wfParseUrl($url); $urlParsed['host'] = $mobileUrlParsed['host']; $url = wfAssembleUrl($urlParsed); } return true; }
/** * Potentially open a socket and sent an HTTP request back to the server * to run a specified number of jobs. This registers a callback to cleanup * the socket once it's done. */ public function triggerJobs() { $jobRunRate = $this->config->get('JobRunRate'); if ($jobRunRate <= 0 || wfReadOnly()) { return; } elseif ($this->getTitle()->isSpecial('RunJobs')) { return; // recursion guard } if ($jobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $jobRunRate) { return; // the higher the job run rate, the less likely we return here } $n = 1; } else { $n = intval($jobRunRate); } $runJobsLogger = LoggerFactory::getInstance('runJobs'); if (!$this->config->get('RunJobsAsync')) { // Fall back to running the job here while the user waits $runner = new JobRunner($runJobsLogger); $runner->run(array('maxJobs' => $n)); return; } try { if (!JobQueueGroup::singleton()->queuesHaveJobs(JobQueueGroup::TYPE_DEFAULT)) { return; // do not send request if there are probably no jobs } } catch (JobQueueError $e) { MWExceptionHandler::logException($e); return; // do not make the site unavailable } $query = array('title' => 'Special:RunJobs', 'tasks' => 'jobs', 'maxjobs' => $n, 'sigexpiry' => time() + 5); $query['signature'] = SpecialRunJobs::getQuerySignature($query, $this->config->get('SecretKey')); $errno = $errstr = null; $info = wfParseUrl($this->config->get('Server')); MediaWiki\suppressWarnings(); $sock = fsockopen($info['host'], isset($info['port']) ? $info['port'] : 80, $errno, $errstr, 0.1); MediaWiki\restoreWarnings(); if (!$sock) { $runJobsLogger->error("Failed to start cron API (socket error {$errno}): {$errstr}"); // Fall back to running the job here while the user waits $runner = new JobRunner($runJobsLogger); $runner->run(array('maxJobs' => $n)); return; } $url = wfAppendQuery(wfScript('index'), $query); $req = "POST {$url} HTTP/1.1\r\n" . "Host: {$info['host']}\r\n" . "Connection: Close\r\n" . "Content-Length: 0\r\n\r\n"; $runJobsLogger->info("Running {$n} job(s) via '{$url}'"); // Send a cron API request to be performed in the background. // Give up if this takes too long to send (which should be rare). stream_set_timeout($sock, 1); $bytes = fwrite($sock, $req); if ($bytes !== strlen($req)) { $runJobsLogger->error("Failed to start cron API (socket write error)"); } else { // Do not wait for the response (the script should handle client aborts). // Make sure that we don't close before that script reaches ignore_user_abort(). $status = fgets($sock); if (!preg_match('#^HTTP/\\d\\.\\d 202 #', $status)) { $runJobsLogger->error("Failed to start cron API: received '{$status}'"); } } fclose($sock); }