Exemple #1
0
 /**
  * Static function wrapping RSSParser to handle rendering of RSS elements
  * @param $input String: text inside the tags.
  * @param $args Array: value associative list of the element attributes and
  * 						their values.
  * @param $parser Parser
  * @param $frame PPFrame parser context
  */
 static function renderRss($input, $args, $parser, $frame)
 {
     global $wgRSSCacheAge, $wgRSSCacheCompare, $wgRSSNamespaces, $wgRSSAllowedFeeds;
     if (is_array($wgRSSNamespaces) && count($wgRSSNamespaces)) {
         $ns = $parser->getTitle()->getNamespace();
         $checkNS = array_flip($wgRSSNamespaces);
         if (!isset($checkNS[$ns])) {
             return wfMsg('rss-ns-permission');
         }
     }
     if (count($wgRSSAllowedFeeds) && !in_array($input, $wgRSSAllowedFeeds)) {
         return wfMsg('rss-url-permission');
     }
     if (!Http::isValidURI($input)) {
         return wfMsg('rss-invalid-url', htmlspecialchars($input));
     }
     if ($wgRSSCacheCompare) {
         $timeout = $wgRSSCacheCompare;
     } else {
         $timeout = $wgRSSCacheAge;
     }
     $parser->getOutput()->updateCacheExpiry($timeout);
     $rss = new RSSParser($input, $args);
     $status = $rss->fetch();
     # Check for errors.
     if (!$status->isGood()) {
         return wfMsg('rss-error', htmlspecialchars($input), $status->getWikiText());
     }
     if (!is_object($rss->rss) || !is_array($rss->rss->items)) {
         return wfMsg('rss-empty', htmlspecialchars($input));
     }
     return $rss->renderFeed($parser, $frame);
 }
 public function execute($sub)
 {
     global $wgOut, $wgRequest;
     global $wgLandingPageBase, $wgChapterLandingPages, $wgLandingPageDefaultTarget;
     $lang = preg_match('/^[A-Za-z-]+$/', $wgRequest->getVal('lang')) ? $wgRequest->getVal('lang') : 'en';
     $utm_source = $wgRequest->getVal('utm_source');
     $utm_medium = $wgRequest->getVal('utm_medium');
     $utm_campaign = $wgRequest->getVal('utm_campaign');
     $referrer = $wgRequest->getHeader('referer');
     $target = $wgRequest->getVal('target', null);
     if (!$target) {
         $target = $wgLandingPageDefaultTarget;
     }
     $tracking = '?' . wfArrayToCGI(array('utm_source' => "{$utm_source}", 'utm_medium' => "{$utm_medium}", 'utm_campaign' => "{$utm_campaign}", 'referrer' => "{$referrer}", 'target' => "{$target}"));
     $ip = $wgRequest->getVal('ip') ? $wgRequest->getVal('ip') : wfGetIP();
     if (IP::isValid($ip)) {
         $country = geoip_country_code_by_name($ip);
         if (is_string($country) && array_key_exists($country, $wgChapterLandingPages)) {
             $wgOut->redirect($this->getDestination($utm_source) . '/' . $wgChapterLandingPages[$country] . $tracking);
             return;
         }
     }
     // No valid IP or chapter page - let's just go for the passed in url or our fallback
     if (Http::isValidURI($target)) {
         $wgOut->redirect($target . '/' . $lang . $tracking);
         return;
     } else {
         $wgOut->redirect($wgLandingPageBase . $target . '/' . $lang . $tracking);
     }
 }
Exemple #3
0
 public function fetchFile()
 {
     if (!Http::isValidURI($this->mUrl)) {
         return Status::newFatal('http-invalid-url');
     }
     if (!$this->mAsync) {
         return $this->reallyFetchFile();
     }
     return Status::newGood();
 }
 public function __construct(WebRequest $request)
 {
     parent::__construct($request);
     global $IP, $wgUser;
     $ac = new AssetsConfig();
     $assets = $ac->resolve($this->mOid, true, !isset($this->mParams['minify']) || $this->mParams['minify'] == true, $this->mParams);
     $this->mContentType = $ac->getGroupType($this->mOid);
     foreach ($assets as $asset) {
         // reference to a file to be fetched by the browser from external server (BugId:9522)
         if (substr($asset, 0, 10) == '#external_') {
             // do nothing
         } else {
             if (Http::isValidURI($asset)) {
                 $params = array();
                 $url = parse_url($asset);
                 if (isset($url['query'])) {
                     parse_str($url['query'], $params);
                 }
                 // Start checking the url to see if it is something we care about (BugId:30188)
                 if (isset($params['action']) && $params['action'] == 'raw' && isset($params['gen']) && $params['gen'] == 'js') {
                     //$this->mContent .= RequestContext::getMain()->getSkin()->generateUserJs(); // FIXME
                 } else {
                     if (isset($params['action']) && $params['action'] == 'raw' && isset($params['gen']) && $params['gen'] == 'css') {
                         //$this->mContent .= RequestContext::getMain()->getSkin()->generateUserStylesheet(); // FIXME
                     } else {
                         //Debug added on May 4, 2012 to inquire external requests spikes
                         $start = microtime(true);
                         $this->mContent .= HTTP::get($asset);
                         $totalTime = microtime(true) - $start;
                         if ($totalTime >= 1) {
                             Wikia::log(__METHOD__, false, "oid: {$this->mOid}, totalTime: {$totalTime}, asset: {$asset}, referrer: {$_SERVER['HTTP_REFERER']}, entrypoint: {$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", true);
                         }
                     }
                 }
             } else {
                 $this->mContent .= file_get_contents($IP . '/' . $asset);
             }
         }
         if ($this->mContentType == AssetsManager::TYPE_JS) {
             // add semicolon to separate concatenated files (BugId:20272)
             // but only for JS (BugId:20824)
             $this->mContent .= ";\n";
         }
     }
     // For RTE only
     // TODO: add "filters" definitions to config.php
     if ($this->mOid == 'rte' || $this->mOid == 'eplrte' || $this->mOid == 'mini_editor_rte_js') {
         $this->mContent = preg_replace('#^.*@Packager\\.RemoveLine.*$#m', '', $this->mContent);
         $this->mContent = str_replace("", '', $this->mContent);
     }
 }
 /** Build $this->messages array */
 private function initMessagesHref()
 {
     # List of default messages for the sidebar. The sidebar doesn't care at
     # all whether they are full URLs, interwiki links or local titles.
     $URL_messages = array('mainpage', 'portal-url', 'currentevents-url', 'recentchanges-url', 'randompage-url', 'helppage');
     # We're assuming that isValidURI works as advertised: it's also
     # tested separately, in tests/phpunit/includes/HttpTest.php.
     foreach ($URL_messages as $m) {
         $titleName = MessageCache::singleton()->get($m);
         if (Http::isValidURI($titleName)) {
             $this->messages[$m]['href'] = $titleName;
         } else {
             $title = Title::newFromText($titleName);
             $this->messages[$m]['href'] = $title->getLocalURL();
         }
     }
 }
Exemple #6
0
 /**
  * Test Http::isValidURI()
  * @bug 27854 : Http::isValidURI is too lax
  * @dataProvider provideURI
  * @covers Http::isValidURI
  */
 public function testIsValidUri($expect, $URI, $message = '')
 {
     $this->assertEquals($expect, (bool) Http::isValidURI($URI), $message);
 }
Exemple #7
0
 public static function isValidURI($url)
 {
     return Http::isValidURI($url) || UploadFromUrl::isValidBase64($url);
 }
Exemple #8
0
 /**
  * @return Status
  */
 public function fetchFile()
 {
     if (!Http::isValidURI($this->mUrl)) {
         return Status::newFatal('http-invalid-url');
     }
     if (!self::isAllowedHost($this->mUrl)) {
         return Status::newFatal('upload-copy-upload-invalid-domain');
     }
     if (!$this->mAsync) {
         return $this->reallyFetchFile();
     }
     return Status::newGood();
 }
	public function execute() {
		wfProfileIn( __METHOD__ );

		parent::execute();

		if ( is_array( $this->postData ) ) {
			$this->postData = wfArrayToCgi( $this->postData );
		}

		if ( $this->parsedUrl['scheme'] != 'http' &&
			 $this->parsedUrl['scheme'] != 'https' ) {
			$this->status->fatal( 'http-invalid-scheme', $this->parsedUrl['scheme'] );
		}

		$this->reqHeaders['Accept'] = "*/*";
		if ( $this->method == 'POST' ) {
			// Required for HTTP 1.0 POSTs
			$this->reqHeaders['Content-Length'] = strlen( $this->postData );
			if ( !isset( $this->reqHeaders['Content-Type'] ) ) {
				$this->reqHeaders['Content-Type'] = "application/x-www-form-urlencoded";
			}
		}

		$options = array();
		if ( $this->proxy ) {
			$options['proxy'] = $this->urlToTCP( $this->proxy );
			$options['request_fulluri'] = true;
		}

		if ( !$this->followRedirects ) {
			$options['max_redirects'] = 0;
		} else {
			$options['max_redirects'] = $this->maxRedirects;
		}

		$options['method'] = $this->method;
		$options['header'] = implode( "\r\n", $this->getHeaderList() );
		// Note that at some future point we may want to support
		// HTTP/1.1, but we'd have to write support for chunking
		// in version of PHP < 5.3.1
		$options['protocol_version'] = "1.0";

		// This is how we tell PHP we want to deal with 404s (for example) ourselves.
		// Only works on 5.2.10+
		$options['ignore_errors'] = true;

		if ( $this->postData ) {
			$options['content'] = $this->postData;
		}

		$options['timeout'] = $this->timeout;

		if ( $this->sslVerifyHost ) {
			$options['CN_match'] = $this->parsedUrl['host'];
		}
		if ( $this->sslVerifyCert ) {
			$options['verify_peer'] = true;
		}

		if ( is_dir( $this->caInfo ) ) {
			$options['capath'] = $this->caInfo;
		} elseif ( is_file( $this->caInfo ) ) {
			$options['cafile'] = $this->caInfo;
		} elseif ( $this->caInfo ) {
			throw new MWException( "Invalid CA info passed: {$this->caInfo}" );
		}

		$scheme = $this->parsedUrl['scheme'];
		$context = stream_context_create( array( "$scheme" => $options ) );

		$this->headerList = array();
		$reqCount = 0;
		$url = $this->url;

		$result = array();

		do {
			$reqCount++;
			wfSuppressWarnings();
			$fh = fopen( $url, "r", false, $context );
			wfRestoreWarnings();

			if ( !$fh ) {
				break;
			}

			$result = stream_get_meta_data( $fh );
			$this->headerList = $result['wrapper_data'];
			$this->parseHeader();

			if ( !$this->followRedirects ) {
				break;
			}

			# Handle manual redirection
			if ( !$this->isRedirect() || $reqCount > $this->maxRedirects ) {
				break;
			}
			# Check security of URL
			$url = $this->getResponseHeader( "Location" );

			if ( !Http::isValidURI( $url ) ) {
				wfDebug( __METHOD__ . ": insecure redirection\n" );
				break;
			}
		} while ( true );

		$this->setStatus();

		if ( $fh === false ) {
			$this->status->fatal( 'http-request-error' );
			wfProfileOut( __METHOD__ );
			return $this->status;
		}

		if ( $result['timed_out'] ) {
			$this->status->fatal( 'http-timed-out', $this->url );
			wfProfileOut( __METHOD__ );
			return $this->status;
		}

		// If everything went OK, or we received some error code
		// get the response body content.
		if ( $this->status->isOK() || (int)$this->respStatus >= 300 ) {
			while ( !feof( $fh ) ) {
				$buf = fread( $fh, 8192 );

				if ( $buf === false ) {
					$this->status->fatal( 'http-read-error' );
					break;
				}

				if ( strlen( $buf ) ) {
					call_user_func( $this->callback, $fh, $buf );
				}
			}
		}
		fclose( $fh );

		wfProfileOut( __METHOD__ );

		return $this->status;
	}
 /**
  * Download the file
  *
  * @param array $httpOptions Array of options for MWHttpRequest.
  *   This could be used to override the timeout on the http request.
  * @return Status
  */
 public function fetchFile($httpOptions = [])
 {
     if (!Http::isValidURI($this->mUrl)) {
         return Status::newFatal('http-invalid-url', $this->mUrl);
     }
     if (!self::isAllowedHost($this->mUrl)) {
         return Status::newFatal('upload-copy-upload-invalid-domain');
     }
     if (!self::isAllowedUrl($this->mUrl)) {
         return Status::newFatal('upload-copy-upload-invalid-url');
     }
     return $this->reallyFetchFile($httpOptions);
 }
Exemple #11
0
 public function execute()
 {
     parent::execute();
     if (is_array($this->postData)) {
         $this->postData = wfArrayToCgi($this->postData);
     }
     if ($this->parsedUrl['scheme'] != 'http' && $this->parsedUrl['scheme'] != 'https') {
         $this->status->fatal('http-invalid-scheme', $this->parsedUrl['scheme']);
     }
     $this->reqHeaders['Accept'] = "*/*";
     $this->reqHeaders['Connection'] = 'Close';
     if ($this->method == 'POST') {
         // Required for HTTP 1.0 POSTs
         $this->reqHeaders['Content-Length'] = strlen($this->postData);
         if (!isset($this->reqHeaders['Content-Type'])) {
             $this->reqHeaders['Content-Type'] = "application/x-www-form-urlencoded";
         }
     }
     // Set up PHP stream context
     $options = ['http' => ['method' => $this->method, 'header' => implode("\r\n", $this->getHeaderList()), 'protocol_version' => '1.1', 'max_redirects' => $this->followRedirects ? $this->maxRedirects : 0, 'ignore_errors' => true, 'timeout' => $this->timeout, 'curl_verify_ssl_host' => $this->sslVerifyHost ? 2 : 0, 'curl_verify_ssl_peer' => $this->sslVerifyCert], 'ssl' => ['verify_peer' => $this->sslVerifyCert, 'SNI_enabled' => true, 'ciphers' => 'HIGH:!SSLv2:!SSLv3:-ADH:-kDH:-kECDH:-DSS', 'disable_compression' => true]];
     if ($this->proxy) {
         $options['http']['proxy'] = $this->urlToTcp($this->proxy);
         $options['http']['request_fulluri'] = true;
     }
     if ($this->postData) {
         $options['http']['content'] = $this->postData;
     }
     if ($this->sslVerifyHost) {
         // PHP 5.6.0 deprecates CN_match, in favour of peer_name which
         // actually checks SubjectAltName properly.
         if (version_compare(PHP_VERSION, '5.6.0', '>=')) {
             $options['ssl']['peer_name'] = $this->parsedUrl['host'];
         } else {
             $options['ssl']['CN_match'] = $this->parsedUrl['host'];
         }
     }
     $options['ssl'] += $this->getCertOptions();
     $context = stream_context_create($options);
     $this->headerList = [];
     $reqCount = 0;
     $url = $this->url;
     $result = [];
     if ($this->profiler) {
         $profileSection = $this->profiler->scopedProfileIn(__METHOD__ . '-' . $this->profileName);
     }
     do {
         $reqCount++;
         $this->fopenErrors = [];
         set_error_handler([$this, 'errorHandler']);
         $fh = fopen($url, "r", false, $context);
         restore_error_handler();
         if (!$fh) {
             // HACK for instant commons.
             // If we are contacting (commons|upload).wikimedia.org
             // try again with CN_match for en.wikipedia.org
             // as php does not handle SubjectAltName properly
             // prior to "peer_name" option in php 5.6
             if (isset($options['ssl']['CN_match']) && ($options['ssl']['CN_match'] === 'commons.wikimedia.org' || $options['ssl']['CN_match'] === 'upload.wikimedia.org')) {
                 $options['ssl']['CN_match'] = 'en.wikipedia.org';
                 $context = stream_context_create($options);
                 continue;
             }
             break;
         }
         $result = stream_get_meta_data($fh);
         $this->headerList = $result['wrapper_data'];
         $this->parseHeader();
         if (!$this->followRedirects) {
             break;
         }
         # Handle manual redirection
         if (!$this->isRedirect() || $reqCount > $this->maxRedirects) {
             break;
         }
         # Check security of URL
         $url = $this->getResponseHeader("Location");
         if (!Http::isValidURI($url)) {
             $this->logger->debug(__METHOD__ . ": insecure redirection\n");
             break;
         }
     } while (true);
     if ($this->profiler) {
         $this->profiler->scopedProfileOut($profileSection);
     }
     $this->setStatus();
     if ($fh === false) {
         if ($this->fopenErrors) {
             $this->logger->warning(__CLASS__ . ': error opening connection: {errstr1}', $this->fopenErrors);
         }
         $this->status->fatal('http-request-error');
         return $this->status;
     }
     if ($result['timed_out']) {
         $this->status->fatal('http-timed-out', $this->url);
         return $this->status;
     }
     // If everything went OK, or we received some error code
     // get the response body content.
     if ($this->status->isOK() || (int) $this->respStatus >= 300) {
         while (!feof($fh)) {
             $buf = fread($fh, 8192);
             if ($buf === false) {
                 $this->status->fatal('http-read-error');
                 break;
             }
             if (strlen($buf)) {
                 call_user_func($this->callback, $fh, $buf);
             }
         }
     }
     fclose($fh);
     return $this->status;
 }
 /**
  * Based on the array of items resolves it into array of assets
  * Parameters $combine, $minify and $params are eventually passed to custom function (look at #function_) which may deliver different set of assets based on them
  *
  * @author Inez Korczyński <*****@*****.**>
  */
 private function resolveItemsToAssets($items, $combine, $minify, $params)
 {
     $assets = array();
     foreach ($items as $item) {
         if (substr($item, 0, 2) == '//') {
             // filepath - most typical case
             $assets[] = substr($item, 2);
         } elseif (substr($item, 0, 7) == '#group_') {
             // reference to another group
             $assets = array_merge($assets, $this->resolve(substr($item, 7), $combine, $minify, $params));
         } elseif (substr($item, 0, 10) == '#function_') {
             // reference to a function that returns array of URIs
             $assets = array_merge($assets, call_user_func(substr($item, 10), $combine, $minify, $params));
         } elseif (substr($item, 0, 10) == '#external_') {
             // reference to a file to be fetched by the browser from external server (BugId:9522)
             $assets[] = $item;
         } elseif (Http::isValidURI($item)) {
             // reference to remote file (http and https)
             $assets[] = $item;
         }
     }
     return $assets;
 }
 /**
  * @author Inez Korczyński <*****@*****.**>
  * @return array Array of one or many URLs
  */
 private function getGroupURL($groupName, $params, $prefix, $combine, $minify)
 {
     wfProfileIn(__METHOD__);
     //lazy loading of AssetsConfig
     $this->loadConfig();
     // pass noexternals mode (BugId:28143)
     global $wgNoExternals;
     if (!empty($wgNoExternals)) {
         $params['noexternals'] = 1;
     }
     $assets = $this->mAssetsConfig->resolve($groupName, $this->mCombine, $this->mMinify, $params);
     $URLs = array();
     if ($combine !== null ? $combine : $this->mCombine) {
         // "minify" is a special parameter that can be set only when initialising object and can not be overwritten per request
         if ($minify !== null ? !$minify : !$this->mMinify) {
             $params['minify'] = false;
         } else {
             unset($params['minify']);
         }
         // check for an #external_ URL being in the package (BugId:9522)
         $isEmpty = true;
         foreach ($assets as $asset) {
             if (substr($asset, 0, 10) == '#external_') {
                 $URLs[] = substr($asset, 10);
             } else {
                 $isEmpty = false;
             }
         }
         // add info about noexternals mode to AssetsManager URL (BugId:28143)
         global $wgNoExternals;
         if (!empty($wgNoExternals)) {
             $params['noexternals'] = 1;
         }
         // When AssetsManager works in "combine" mode return URL to the combined package
         if (!$isEmpty) {
             $url = $prefix . $this->getAMLocalURL('group', $groupName, $params);
             // apply domain sharding
             $url = wfReplaceAssetServer($url);
             $URLs[] = $url;
         }
     } else {
         foreach ($assets as $asset) {
             if (substr($asset, 0, 10) == '#external_') {
                 $url = substr($asset, 10);
             } else {
                 if (Http::isValidURI($asset)) {
                     $url = $asset;
                 } else {
                     // We always need to use common host for static assets since it has
                     // the information about the slot which is otherwise not available
                     // in varnish (BugId: 33905)
                     $url = $this->getOneCommonURL($asset, $minify);
                 }
             }
             // apply domain sharding
             $url = wfReplaceAssetServer($url);
             $URLs[] = $url;
         }
     }
     $this->mGeneratedUrls += array_fill_keys($URLs, $groupName);
     wfProfileOut(__METHOD__);
     return $URLs;
 }
Exemple #14
0
 /**
  * @param $url String: url to use
  * @param $options Array: (optional) extra params to pass (see Http::request())
  */
 function __construct($url, $options = array())
 {
     global $wgHTTPTimeout;
     $this->url = $url;
     $this->parsedUrl = parse_url($url);
     if (!Http::isValidURI($this->url)) {
         $this->status = Status::newFatal('http-invalid-url');
     } else {
         $this->status = Status::newGood(100);
         // continue
     }
     if (isset($options['timeout']) && $options['timeout'] != 'default') {
         $this->timeout = $options['timeout'];
     } else {
         $this->timeout = $wgHTTPTimeout;
     }
     $members = array("postData", "proxy", "noProxy", "sslVerifyHost", "caInfo", "method", "followRedirects", "maxRedirects", "sslVerifyCert");
     foreach ($members as $o) {
         if (isset($options[$o])) {
             $this->{$o} = $options[$o];
         }
     }
 }
Exemple #15
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;
 }
Exemple #16
0
 /**
  * Load quiz data (try to use cache layer)
  */
 private function load($master = false)
 {
     global $wgMemc;
     wfProfileIn(__METHOD__);
     if (!$master) {
         $this->mData = $wgMemc->get($this->mMemcacheKey);
     }
     if (empty($this->mData)) {
         $article = Article::newFromID($this->mQuizId);
         // check quiz existence
         if (empty($article)) {
             wfDebug(__METHOD__ . ": quiz doesn't exist\n");
             wfProfileOut(__METHOD__);
             return;
         }
         // get quiz's author and creation timestamp
         $title = $article->getTitle();
         $firstRev = $title->getFirstRevision();
         $titleText = $title->getText();
         $titleScreenText = '';
         $fbRecommendationText = '';
         $images = array();
         $imageShorts = array();
         $moreInfoHeading = '';
         $moreInfoLinks = array();
         // parse wikitext containing quiz data
         $content = $article->getContent();
         $lines = explode("\n", $content);
         foreach ($lines as $line) {
             if (startsWith($line, self::TITLESCREENTEXT_MARKER)) {
                 $titleScreenText = trim(substr($line, strlen(self::TITLESCREENTEXT_MARKER)));
             } elseif (startsWith($line, self::FBRECOMMENDATIONTEXT_MARKER)) {
                 $fbRecommendationText = trim(substr($line, strlen(self::FBRECOMMENDATIONTEXT_MARKER)));
             } elseif (startsWith($line, self::IMAGE_MARKER)) {
                 $imageShort = trim(substr($line, strlen(self::IMAGE_MARKER)));
                 $images[] = $this->getImageSrc($imageShort);
                 $imageShorts[] = $imageShort;
             } elseif (startsWith($line, self::MOREINFOHEADING_MARKER)) {
                 $moreInfoHeading = trim(substr($line, strlen(self::MOREINFOHEADING_MARKER)));
             } elseif (startsWith($line, self::MOREINFOLINK_MARKER)) {
                 $moreInfo = substr($line, strlen(self::MOREINFOLINK_MARKER));
                 $moreInfoChunks = explode(self::MOREINFOLINK_TEXT_MARKER, $moreInfo);
                 if (Http::isValidURI($moreInfoChunks[0])) {
                     $moreInfoUrl = $moreInfoChunks[0];
                 } else {
                     $title = Title::newFromText($moreInfoChunks[0]);
                     $moreInfoUrl = $title->getFullUrl();
                 }
                 $moreInfoLinks[] = array('article' => $moreInfoChunks[0], 'url' => $moreInfoUrl, 'text' => isset($moreInfoChunks[1]) ? $moreInfoChunks[1] : '');
             } elseif (startsWith($line, self::REQUIRE_EMAIL_MARKER)) {
                 $line = substr($line, strlen(self::REQUIRE_EMAIL_MARKER));
                 $requireEmail = $line == 'true';
             }
         }
         // load quiz's elements
         if (empty($this->mCategory)) {
             $catName = self::QUIZ_CATEGORY_PREFIX . $titleText;
             $cat = Category::newFromName($catName);
             $this->mCategory = $cat;
         }
         $quizElements = array();
         if (empty($this->mCategory) || !$this->mCategory->getID()) {
             wfDebug(__METHOD__ . ": quiz's category doesn't exist\n");
         } else {
             // get quiz elements
             $quizIterator = $this->mCategory->getMembers();
             while ($quizElementTitle = $quizIterator->current()) {
                 $quizElement = WikiaQuizElement::newFromId($quizElementTitle->getArticleId());
                 $quizElements[] = $quizElement->getData();
                 $quizIterator->next();
             }
         }
         $this->mData = array('id' => $this->mQuizId, 'name' => $titleText, 'requireEmail' => !empty($requireEmail), 'elements' => $quizElements, 'titlescreentext' => $titleScreenText, 'fbrecommendationtext' => $fbRecommendationText, 'images' => $images, 'imageShorts' => $imageShorts, 'moreinfoheading' => $moreInfoHeading, 'moreinfo' => $moreInfoLinks);
         wfDebug(__METHOD__ . ": loaded from scratch\n");
         // store it in memcache
         $wgMemc->set($this->mMemcacheKey, $this->mData, self::CACHE_TTL);
     } else {
         wfDebug(__METHOD__ . ": loaded from memcache\n");
     }
     $this->mExists = true;
     wfProfileOut(__METHOD__);
     return;
 }
Exemple #17
0
 public function execute()
 {
     wfProfileIn(__METHOD__);
     parent::execute();
     if (is_array($this->postData)) {
         $this->postData = wfArrayToCgi($this->postData);
     }
     if ($this->parsedUrl['scheme'] != 'http' && $this->parsedUrl['scheme'] != 'https') {
         $this->status->fatal('http-invalid-scheme', $this->parsedUrl['scheme']);
     }
     $this->reqHeaders['Accept'] = "*/*";
     $this->reqHeaders['Connection'] = 'Close';
     if ($this->method == 'POST') {
         // Required for HTTP 1.0 POSTs
         $this->reqHeaders['Content-Length'] = strlen($this->postData);
         if (!isset($this->reqHeaders['Content-Type'])) {
             $this->reqHeaders['Content-Type'] = "application/x-www-form-urlencoded";
         }
     }
     // Set up PHP stream context
     $options = array('http' => array('method' => $this->method, 'header' => implode("\r\n", $this->getHeaderList()), 'protocol_version' => '1.1', 'max_redirects' => $this->followRedirects ? $this->maxRedirects : 0, 'ignore_errors' => true, 'timeout' => $this->timeout, 'curl_verify_ssl_host' => $this->sslVerifyHost ? 2 : 0, 'curl_verify_ssl_peer' => $this->sslVerifyCert), 'ssl' => array('verify_peer' => $this->sslVerifyCert, 'SNI_enabled' => true));
     if ($this->proxy) {
         $options['http']['proxy'] = $this->urlToTCP($this->proxy);
         $options['http']['request_fulluri'] = true;
     }
     if ($this->postData) {
         $options['http']['content'] = $this->postData;
     }
     if ($this->sslVerifyHost) {
         $options['ssl']['CN_match'] = $this->parsedUrl['host'];
     }
     if (is_dir($this->caInfo)) {
         $options['ssl']['capath'] = $this->caInfo;
     } elseif (is_file($this->caInfo)) {
         $options['ssl']['cafile'] = $this->caInfo;
     } elseif ($this->caInfo) {
         throw new MWException("Invalid CA info passed: {$this->caInfo}");
     }
     $context = stream_context_create($options);
     $this->headerList = array();
     $reqCount = 0;
     $url = $this->url;
     $result = array();
     do {
         $reqCount++;
         wfSuppressWarnings();
         $fh = fopen($url, "r", false, $context);
         wfRestoreWarnings();
         if (!$fh) {
             break;
         }
         $result = stream_get_meta_data($fh);
         $this->headerList = $result['wrapper_data'];
         $this->parseHeader();
         if (!$this->followRedirects) {
             break;
         }
         # Handle manual redirection
         if (!$this->isRedirect() || $reqCount > $this->maxRedirects) {
             break;
         }
         # Check security of URL
         $url = $this->getResponseHeader("Location");
         if (!Http::isValidURI($url)) {
             wfDebug(__METHOD__ . ": insecure redirection\n");
             break;
         }
     } while (true);
     $this->setStatus();
     if ($fh === false) {
         $this->status->fatal('http-request-error');
         wfProfileOut(__METHOD__);
         return $this->status;
     }
     if ($result['timed_out']) {
         $this->status->fatal('http-timed-out', $this->url);
         wfProfileOut(__METHOD__);
         return $this->status;
     }
     // If everything went OK, or we received some error code
     // get the response body content.
     if ($this->status->isOK() || (int) $this->respStatus >= 300) {
         while (!feof($fh)) {
             $buf = fread($fh, 8192);
             if ($buf === false) {
                 $this->status->fatal('http-read-error');
                 break;
             }
             if (strlen($buf)) {
                 call_user_func($this->callback, $fh, $buf);
             }
         }
     }
     fclose($fh);
     wfProfileOut(__METHOD__);
     return $this->status;
 }
 private static function parseCreateEditQuizRequest(WebRequest $request, $quiz, &$error)
 {
     $wgUser = F::app()->getGlobal('wgUser');
     $wgLang = F::app()->getGlobal('wgContLang');
     // parse quiz fields
     $quizContent = '';
     // title
     if (!empty($quiz)) {
         $title = $quiz->getTitle();
     } else {
         $title = trim($request->getVal('title'));
     }
     // title screen text
     $titleScreenText = trim($request->getVal('titlescreentext'));
     if ($titleScreenText) {
         $quizContent .= WikiaQuiz::TITLESCREENTEXT_MARKER . $titleScreenText . "\n";
     }
     // facebook recommendation description
     $fbRecommendationText = trim($request->getVal('fbrecommendationtext'));
     if ($fbRecommendationText) {
         $quizContent .= WikiaQuiz::FBRECOMMENDATIONTEXT_MARKER . $fbRecommendationText . "\n";
     }
     // title screen images
     $titleScreenImages = $request->getArray('titlescreenimage');
     foreach ($titleScreenImages as $image) {
         if ($image) {
             if (!self::isValidImage($image)) {
                 $error = wfMsg('wikiaquiz-error-invalid-image', $image);
                 return;
             }
             $quizContent .= WikiaQuiz::IMAGE_MARKER . $image . "\n";
         }
     }
     // More Info heading
     $moreInfoHeading = trim($request->getVal('moreinfoheading'));
     if ($moreInfoHeading) {
         $quizContent .= WikiaQuiz::MOREINFOHEADING_MARKER . $moreInfoHeading . "\n";
     }
     // Are emails required?
     if ($request->getCheck('requireemail')) {
         $quizContent .= WikiaQuiz::REQUIRE_EMAIL_MARKER . "true\n";
     }
     // More Info links
     $moreInfoArticles = $request->getArray('moreinfoarticle');
     $moreInfoLinkTexts = $request->getArray('moreinfolinktext');
     foreach ($moreInfoArticles as $index => $articleName) {
         if ($articleName) {
             $moreInfoLinkText = isset($moreInfoLinkTexts[$index]) ? $moreInfoLinkTexts[$index] : '';
             if (Http::isValidURI($articleName)) {
                 $quizContent .= WikiaQuiz::MOREINFOLINK_MARKER . $articleName . WikiaQuiz::MOREINFOLINK_TEXT_MARKER . $moreInfoLinkText . "\n";
             } else {
                 $title_object = F::build('Title', array($articleName), 'newFromText');
                 if (is_object($title_object) && $title_object->exists()) {
                     $quizContent .= WikiaQuiz::MOREINFOLINK_MARKER . $articleName . WikiaQuiz::MOREINFOLINK_TEXT_MARKER . $moreInfoLinkText . "\n";
                 } else {
                     $error = wfMsg('wikiaquiz-error-invalid-article-with-details', $articleName);
                     return;
                 }
             }
         }
     }
     $patternCategory = "/\\[\\[" . $wgLang->getNsText(NS_CATEGORY) . "\\:" . WikiaQuiz::QUIZ_CATEGORY_PREFIX . $title . "(\\|(.+))*\\]\\]/";
     //process questions (quizelements)
     $questions = $request->getArray('question');
     foreach ($questions as $index => $question) {
         $question = trim($question);
         if (!$question) {
             continue;
         }
         $title_object = F::build('Title', array($question, NS_WIKIA_QUIZARTICLE), 'newFromText');
         if (is_object($title_object) && $title_object->exists()) {
             // update category tag
             $article = F::build('Article', array($title_object));
             $content = $article->getContent();
             $newContent = null;
             $matches = null;
             preg_match($patternCategory, $content, $matches);
             if (isset($matches[2])) {
                 if ($matches[2] != $index) {
                     $replace = "[[" . $wgLang->getNsText(NS_CATEGORY) . ":" . WikiaQuiz::QUIZ_CATEGORY_PREFIX . $title . "|" . $index . "]]";
                     $newContent = preg_replace($patternCategory, $replace, $content);
                 }
             } else {
                 // this category is new for this article. append to contents.
                 $newContent .= self::getCategoryText($title, $index);
             }
             if ($newContent) {
                 $status = $article->doEdit($newContent, 'Quiz Question and Answers Updated', EDIT_UPDATE, false, $wgUser);
             }
         } else {
             if ($title_object == null) {
                 $error = wfMsg('wikiaquiz-error-invalid-question');
                 return;
             } else {
                 // create question
                 $content = self::getCategoryText($title, $index);
                 $article = F::build('Article', array($title_object));
                 $status = $article->doEdit($content, 'Quiz Article Created', EDIT_NEW, false, $wgUser);
                 //@todo check status
             }
         }
     }
     if (!empty($quiz)) {
         // remove old questions from quiz
         $questionKeys = array_flip($questions);
         $elements = $quiz->getElements();
         if (is_array($elements)) {
             foreach ($elements as $element) {
                 $question = trim($element['title']);
                 if ($question) {
                     if (!array_key_exists($question, $questionKeys)) {
                         $title_object = F::build('Title', array($question, NS_WIKIA_QUIZARTICLE), 'newFromText');
                         $article = F::build('Article', array($title_object));
                         $content = $article->getContent();
                         $content = preg_replace($patternCategory, '', $content);
                         $status = $article->doEdit($content, 'Quiz Question and Answers Updated', EDIT_UPDATE, false, $wgUser);
                     }
                 }
             }
         }
     }
     return $quizContent;
 }