function __construct($key, $archive = 0)
 {
     $this->app = F::app();
     switch ($key) {
         case 'edit':
             $this->mKey = self::EDIT_CATEGORY;
             $this->mEventType = self::EDIT_CATEGORY_INT;
             break;
         case 'create':
             $this->mKey = self::CREATEPAGE_CATEGORY;
             $this->mEventType = self::CREATEPAGE_CATEGORY_INT;
             break;
         case 'delete':
             $this->mKey = self::DELETE_CATEGORY;
             $this->mEventType = self::DELETE_CATEGORY_INT;
             break;
         case 'undelete':
             $this->mKey = self::UNDELETE_CATEGORY;
             $this->mEventType = self::UNDELETE_CATEGORY_INT;
             break;
     }
     $this->setCityId($this->app->wg->CityId);
     $this->setServerName($this->app->wg->Server);
     $this->setIp($this->app->wg->Request->getIP());
     $this->setHostname(wfHostname());
     $this->setBeaconId(wfGetBeaconId());
     $this->setArchive($archive);
     $this->setLanguage();
     $this->setCategory();
 }
 public function log(array $stats)
 {
     $pfhost = $this->perHost ? wfHostname() : '';
     try {
         $dbw = wfGetDB(DB_MASTER);
         $useTrx = $dbw->getType() === 'sqlite';
         // much faster
         if ($useTrx) {
             $dbw->startAtomic(__METHOD__);
         }
         foreach ($stats as $data) {
             $name = $data['name'];
             $eventCount = $data['calls'];
             $timeSum = (double) $data['real'];
             $memorySum = (double) $data['memory'];
             $name = substr($name, 0, 255);
             // Kludge
             $timeSum = $timeSum >= 0 ? $timeSum : 0;
             $memorySum = $memorySum >= 0 ? $memorySum : 0;
             $dbw->upsert('profiling', array('pf_name' => $name, 'pf_count' => $eventCount, 'pf_time' => $timeSum, 'pf_memory' => $memorySum, 'pf_server' => $pfhost), array(array('pf_name', 'pf_server')), array("pf_count=pf_count+{$eventCount}", "pf_time=pf_time+{$timeSum}", "pf_memory=pf_memory+{$memorySum}"), __METHOD__);
         }
         if ($useTrx) {
             $dbw->endAtomic(__METHOD__);
         }
     } catch (DBError $e) {
     }
 }
Esempio n. 3
0
 function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0)
 {
     global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath;
     if (!$this->normaliseParams($image, $params)) {
         return new TransformParameterError($params);
     }
     $clientWidth = $params['width'];
     $clientHeight = $params['height'];
     $physicalWidth = $params['physicalWidth'];
     $physicalHeight = $params['physicalHeight'];
     $srcPath = $image->getPath();
     if ($flags & self::TRANSFORM_LATER) {
         return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath);
     }
     if (!wfMkdirParents(dirname($dstPath))) {
         return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, wfMsg('thumbnail_dest_directory'));
     }
     $err = false;
     if (isset($wgSVGConverters[$wgSVGConverter])) {
         $cmd = str_replace(array('$path/', '$width', '$height', '$input', '$output'), array($wgSVGConverterPath ? wfEscapeShellArg("{$wgSVGConverterPath}/") : "", intval($physicalWidth), intval($physicalHeight), wfEscapeShellArg($srcPath), wfEscapeShellArg($dstPath)), $wgSVGConverters[$wgSVGConverter]) . " 2>&1";
         wfProfileIn('rsvg');
         wfDebug(__METHOD__ . ": {$cmd}\n");
         $err = wfShellExec($cmd, $retval);
         wfProfileOut('rsvg');
     }
     $removed = $this->removeBadFile($dstPath, $retval);
     if ($retval != 0 || $removed) {
         wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd));
         return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err);
     } else {
         return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath);
     }
 }
Esempio n. 4
0
 function logToFile($msg, $file)
 {
     $header = '[' . date('d\\TH:i:s') . '] ' . wfHostname() . ' ' . posix_getpid();
     if ($this->slaveId !== false) {
         $header .= "({$this->slaveId})";
     }
     $header .= ' ' . wfWikiID();
     wfErrorLog(sprintf("%-50s %s\n", $header, $msg), $file);
 }
Esempio n. 5
0
 /**
  * @param array $lbConf Config for LBFactory::__construct()
  * @param Config $mainConfig Main config object from MediaWikiServices
  * @return array
  */
 public static function applyDefaultConfig(array $lbConf, Config $mainConfig)
 {
     global $wgCommandLineMode;
     $lbConf += ['localDomain' => new DatabaseDomain($mainConfig->get('DBname'), null, $mainConfig->get('DBprefix')), 'profiler' => Profiler::instance(), 'trxProfiler' => Profiler::instance()->getTransactionProfiler(), 'replLogger' => LoggerFactory::getInstance('DBReplication'), 'queryLogger' => LoggerFactory::getInstance('DBQuery'), 'connLogger' => LoggerFactory::getInstance('DBConnection'), 'perfLogger' => LoggerFactory::getInstance('DBPerformance'), 'errorLogger' => [MWExceptionHandler::class, 'logException'], 'cliMode' => $wgCommandLineMode, 'hostname' => wfHostname(), 'readOnlyReason' => wfConfiguredReadOnlyReason()];
     if ($lbConf['class'] === 'LBFactorySimple') {
         if (isset($lbConf['servers'])) {
             // Server array is already explicitly configured; leave alone
         } elseif (is_array($mainConfig->get('DBservers'))) {
             foreach ($mainConfig->get('DBservers') as $i => $server) {
                 if ($server['type'] === 'sqlite') {
                     $server += ['dbDirectory' => $mainConfig->get('SQLiteDataDir')];
                 } elseif ($server['type'] === 'postgres') {
                     $server += ['port' => $mainConfig->get('DBport')];
                 }
                 $lbConf['servers'][$i] = $server + ['schema' => $mainConfig->get('DBmwschema'), 'tablePrefix' => $mainConfig->get('DBprefix'), 'flags' => DBO_DEFAULT, 'sqlMode' => $mainConfig->get('SQLMode'), 'utf8Mode' => $mainConfig->get('DBmysql5')];
             }
         } else {
             $flags = DBO_DEFAULT;
             $flags |= $mainConfig->get('DebugDumpSql') ? DBO_DEBUG : 0;
             $flags |= $mainConfig->get('DBssl') ? DBO_SSL : 0;
             $flags |= $mainConfig->get('DBcompress') ? DBO_COMPRESS : 0;
             $server = ['host' => $mainConfig->get('DBserver'), 'user' => $mainConfig->get('DBuser'), 'password' => $mainConfig->get('DBpassword'), 'dbname' => $mainConfig->get('DBname'), 'schema' => $mainConfig->get('DBmwschema'), 'tablePrefix' => $mainConfig->get('DBprefix'), 'type' => $mainConfig->get('DBtype'), 'load' => 1, 'flags' => $flags, 'sqlMode' => $mainConfig->get('SQLMode'), 'utf8Mode' => $mainConfig->get('DBmysql5')];
             if ($server['type'] === 'sqlite') {
                 $server['dbDirectory'] = $mainConfig->get('SQLiteDataDir');
             } elseif ($server['type'] === 'postgres') {
                 $server['port'] = $mainConfig->get('DBport');
             }
             $lbConf['servers'] = [$server];
         }
         if (!isset($lbConf['externalClusters'])) {
             $lbConf['externalClusters'] = $mainConfig->get('ExternalServers');
         }
     } elseif ($lbConf['class'] === 'LBFactoryMulti') {
         if (isset($lbConf['serverTemplate'])) {
             $lbConf['serverTemplate']['schema'] = $mainConfig->get('DBmwschema');
             $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get('SQLMode');
             $lbConf['serverTemplate']['utf8Mode'] = $mainConfig->get('DBmysql5');
         }
     }
     // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804)
     $sCache = MediaWikiServices::getInstance()->getLocalServerObjectCache();
     if ($sCache->getQoS($sCache::ATTR_EMULATION) > $sCache::QOS_EMULATION_SQL) {
         $lbConf['srvCache'] = $sCache;
     }
     $cCache = ObjectCache::getLocalClusterInstance();
     if ($cCache->getQoS($cCache::ATTR_EMULATION) > $cCache::QOS_EMULATION_SQL) {
         $lbConf['memCache'] = $cCache;
     }
     $wCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
     if ($wCache->getQoS($wCache::ATTR_EMULATION) > $wCache::QOS_EMULATION_SQL) {
         $lbConf['wanCache'] = $wCache;
     }
     return $lbConf;
 }
Esempio n. 6
0
 /**
  * storeData -- push data frame to Stomp
  *
  * @param String $type
  * @author Piotr Molski (MoLi)
  * @access private
  *
  */
 private function send_log()
 {
     wfProfileIn(__METHOD__);
     try {
         $data = json_encode(array('cityId' => $this->mCityId, 'pageId' => $this->mPageId, 'revId' => $this->mRevId, 'logId' => $this->mLogId, 'serverName' => $this->mServerName, 'archive' => $this->mArchive, 'hostname' => wfHostname(), 'beaconId' => wfGetBeaconId()));
         WScribeClient::singleton($this->mKey)->send($data);
     } catch (TException $e) {
         Wikia::log(__METHOD__, 'scribeClient exception', $e->getMessage());
     }
     wfProfileOut(__METHOD__);
 }
Esempio n. 7
0
 /**
  * Returns TransactionTrace singleton instance
  *
  * @return TransactionTrace
  */
 public static function getInstance()
 {
     static $instance;
     if ($instance === null) {
         global $wgWikiaEnvironment;
         $instance = new TransactionTrace(array(new TransactionTraceNewrelic(), new TransactionTraceScribe()));
         $instance->set(self::PARAM_ENVIRONMENT, $wgWikiaEnvironment);
         $instance->set(self::PARAM_HOSTNAME, wfHostname());
         $instance->set(self::PARAM_PHP_VERSION, explode('-', phpversion())[0]);
         // report "5.4.17-1~precise+1" as "5.4.17"
     }
     return $instance;
 }
 /**
  * Log the whole profiling data into the database.
  */
 public function logData()
 {
     global $wgProfilePerHost;
     # Do not log anything if database is readonly (bug 5375)
     if (wfReadOnly()) {
         return;
     }
     if ($wgProfilePerHost) {
         $pfhost = wfHostname();
     } else {
         $pfhost = '';
     }
     try {
         $this->collateData();
         $dbw = wfGetDB(DB_MASTER);
         $useTrx = $dbw->getType() === 'sqlite';
         // much faster
         if ($useTrx) {
             $dbw->begin();
         }
         foreach ($this->mCollated as $name => $data) {
             $eventCount = $data['count'];
             $timeSum = (double) ($data['real'] * 1000);
             $memorySum = (double) $data['memory'];
             $name = substr($name, 0, 255);
             // Kludge
             $timeSum = $timeSum >= 0 ? $timeSum : 0;
             $memorySum = $memorySum >= 0 ? $memorySum : 0;
             $dbw->update('profiling', array("pf_count=pf_count+{$eventCount}", "pf_time=pf_time+{$timeSum}", "pf_memory=pf_memory+{$memorySum}"), array('pf_name' => $name, 'pf_server' => $pfhost), __METHOD__);
             $rc = $dbw->affectedRows();
             if ($rc == 0) {
                 $dbw->insert('profiling', array('pf_name' => $name, 'pf_count' => $eventCount, 'pf_time' => $timeSum, 'pf_memory' => $memorySum, 'pf_server' => $pfhost), __METHOD__, array('IGNORE'));
             }
             // When we upgrade to mysql 4.1, the insert+update
             // can be merged into just a insert with this construct added:
             //     "ON DUPLICATE KEY UPDATE ".
             //     "pf_count=pf_count + VALUES(pf_count), ".
             //     "pf_time=pf_time + VALUES(pf_time)";
         }
         if ($useTrx) {
             $dbw->commit();
         }
     } catch (DBError $e) {
     }
 }
Esempio n. 9
0
function wfCheckPAD($url, $pad)
{
    global $wgServer, $wgTitle, $wgCookieDomain;
    if ($wgServer == "http://testers.wikihow.com") {
        return true;
    }
    if (($wgServer == "http://www.wikihow.com" || strpos(wfHostname(), "wikihow.com") !== false) && strpos($pad, "whstatic") === false) {
        $alerts = new MailAddress("*****@*****.**");
        // format of date to correspond to varnish file 04/Dec/2010:07:19:06 -0800
        $now = date("d/M/Y:h:i:s O");
        $subject = "Not using PAD for thumbnail on " . wfHostname() . " - " . $now;
        $body = "article {$wgTitle->getFullURL()}\n\n\nUrl: {$url} \n\n \npad {$pad} \n\n\nserver variables " . print_r($_SERVER, true) . "\n\n allheaders: " . print_r(getallheaders(), true) . "\n\n wgserver {$wgServer}\n\ncookie domain {$wgCookieDomain}\n\n Title " . print_r($wgTitle, true) . "\n\nbacktrace: " . strip_tags(wfBacktrace());
        UserMailer::send($alerts, $alerts, $subject, $body, $alerts);
        error_log($body);
        wfDebug($body);
    }
    return true;
}
Esempio n. 10
0
/** */
function wfStreamFile($fname, $headers = array())
{
    $stat = @stat($fname);
    if (!$stat) {
        header('HTTP/1.0 404 Not Found');
        header('Cache-Control: no-cache');
        header('Content-Type: text/html; charset=utf-8');
        $encFile = htmlspecialchars($fname);
        $encScript = htmlspecialchars($_SERVER['SCRIPT_NAME']);
        echo "<html><body>\n<h1>File not found</h1>\n<p>Although this PHP script ({$encScript}) exists, the file requested for output \n({$encFile}) does not.</p>\n</body></html>\n";
        return;
    }
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stat['mtime']) . ' GMT');
    // Cancel output buffering and gzipping if set
    wfResetOutputBuffers();
    $type = wfGetType($fname);
    if ($type and $type != "unknown/unknown") {
        header("Content-type: {$type}");
    } else {
        header('Content-type: application/x-wiki');
    }
    global $wgContLanguageCode;
    header("Content-Disposition: inline;filename*=utf-8'{$wgContLanguageCode}'" . urlencode(basename($fname)));
    foreach ($headers as $header) {
        header($header);
    }
    if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        $modsince = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
        $sinceTime = strtotime($modsince);
        if ($stat['mtime'] <= $sinceTime) {
            header("HTTP/1.0 304 Not Modified");
            return;
        }
    }
    $h = "";
    foreach ($stat as $k => $v) {
        $h .= "{$k}={$v},";
    }
    header('Content-Length: ' . $stat['size']);
    header('X-stat-results: ' . $h);
    header('X-Serving-host: ' . wfHostname());
    header('Content-Length-true: ' . $stat['size']);
    readfile($fname);
}
Esempio n. 11
0
 /**
  * Convert wikitext to HTML
  * Do not call this function recursively.
  *
  * @param string $text text we want to parse
  * @param $title Title object
  * @param $options ParserOptions
  * @param $linestart boolean
  * @param $clearState boolean
  * @param int $revid number to pass in {{REVISIONID}}
  * @return ParserOutput a ParserOutput
  */
 public function parse($text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null)
 {
     /**
      * First pass--just handle <nowiki> sections, pass the rest off
      * to internalParse() which does all the real work.
      */
     global $wgUseTidy, $wgAlwaysUseTidy, $wgShowHostnames;
     $fname = __METHOD__ . '-' . wfGetCaller();
     wfProfileIn(__METHOD__);
     wfProfileIn($fname);
     $this->startParse($title, $options, self::OT_HTML, $clearState);
     $this->mInputSize = strlen($text);
     if ($this->mOptions->getEnableLimitReport()) {
         $this->mOutput->resetParseStartTime();
     }
     # Remove the strip marker tag prefix from the input, if present.
     if ($clearState) {
         $text = str_replace($this->mUniqPrefix, '', $text);
     }
     $oldRevisionId = $this->mRevisionId;
     $oldRevisionObject = $this->mRevisionObject;
     $oldRevisionTimestamp = $this->mRevisionTimestamp;
     $oldRevisionUser = $this->mRevisionUser;
     $oldRevisionSize = $this->mRevisionSize;
     if ($revid !== null) {
         $this->mRevisionId = $revid;
         $this->mRevisionObject = null;
         $this->mRevisionTimestamp = null;
         $this->mRevisionUser = null;
         $this->mRevisionSize = null;
     }
     wfRunHooks('ParserBeforeStrip', array(&$this, &$text, &$this->mStripState));
     # No more strip!
     wfRunHooks('ParserAfterStrip', array(&$this, &$text, &$this->mStripState));
     $text = $this->internalParse($text);
     wfRunHooks('ParserAfterParse', array(&$this, &$text, &$this->mStripState));
     $text = $this->mStripState->unstripGeneral($text);
     # Clean up special characters, only run once, next-to-last before doBlockLevels
     $fixtags = array('/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1&#160;', '/(\\302\\253) /' => '\\1&#160;', '/&#160;(!\\s*important)/' => ' \\1');
     $text = preg_replace(array_keys($fixtags), array_values($fixtags), $text);
     $text = $this->doBlockLevels($text, $linestart);
     $this->replaceLinkHolders($text);
     /**
      * The input doesn't get language converted if
      * a) It's disabled
      * b) Content isn't converted
      * c) It's a conversion table
      * d) it is an interface message (which is in the user language)
      */
     if (!($options->getDisableContentConversion() || isset($this->mDoubleUnderscores['nocontentconvert']))) {
         if (!$this->mOptions->getInterfaceMessage()) {
             # The position of the convert() call should not be changed. it
             # assumes that the links are all replaced and the only thing left
             # is the <nowiki> mark.
             $text = $this->getConverterLanguage()->convert($text);
         }
     }
     /**
      * A converted title will be provided in the output object if title and
      * content conversion are enabled, the article text does not contain
      * a conversion-suppressing double-underscore tag, and no
      * {{DISPLAYTITLE:...}} is present. DISPLAYTITLE takes precedence over
      * automatic link conversion.
      */
     if (!($options->getDisableTitleConversion() || isset($this->mDoubleUnderscores['nocontentconvert']) || isset($this->mDoubleUnderscores['notitleconvert']) || $this->mOutput->getDisplayTitle() !== false)) {
         $convruletitle = $this->getConverterLanguage()->getConvRuleTitle();
         if ($convruletitle) {
             $this->mOutput->setTitleText($convruletitle);
         } else {
             $titleText = $this->getConverterLanguage()->convertTitle($title);
             $this->mOutput->setTitleText($titleText);
         }
     }
     $text = $this->mStripState->unstripNoWiki($text);
     wfRunHooks('ParserBeforeTidy', array(&$this, &$text));
     $text = $this->replaceTransparentTags($text);
     $text = $this->mStripState->unstripGeneral($text);
     $text = Sanitizer::normalizeCharReferences($text);
     if ($wgUseTidy && $this->mOptions->getTidy() || $wgAlwaysUseTidy) {
         $text = MWTidy::tidy($text);
     } else {
         # attempt to sanitize at least some nesting problems
         # (bug #2702 and quite a few others)
         $tidyregs = array('/(<([bi])>)(<([bi])>)?([^<]*)(<\\/?a[^<]*>)([^<]*)(<\\/\\4>)?(<\\/\\2>)/' => '\\1\\3\\5\\8\\9\\6\\1\\3\\7\\8\\9', '/(<a[^>]+>)([^<]*)(<a[^>]+>[^<]*)<\\/a>(.*)<\\/a>/' => '\\1\\2</a>\\3</a>\\1\\4</a>', '/(<([aib]) [^>]+>)([^<]*)(<div([^>]*)>)(.*)(<\\/div>)([^<]*)(<\\/\\2>)/' => '\\1\\3&lt;div\\5&gt;\\6&lt;/div&gt;\\8\\9', '/<([bi])><\\/\\1>/' => '');
         $text = preg_replace(array_keys($tidyregs), array_values($tidyregs), $text);
     }
     if ($this->mExpensiveFunctionCount > $this->mOptions->getExpensiveParserFunctionLimit()) {
         $this->limitationWarn('expensive-parserfunction', $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit());
     }
     wfRunHooks('ParserAfterTidy', array(&$this, &$text));
     # Information on include size limits, for the benefit of users who try to skirt them
     if ($this->mOptions->getEnableLimitReport()) {
         $max = $this->mOptions->getMaxIncludeSize();
         $cpuTime = $this->mOutput->getTimeSinceStart('cpu');
         if ($cpuTime !== null) {
             $this->mOutput->setLimitReportData('limitreport-cputime', sprintf("%.3f", $cpuTime));
         }
         $wallTime = $this->mOutput->getTimeSinceStart('wall');
         $this->mOutput->setLimitReportData('limitreport-walltime', sprintf("%.3f", $wallTime));
         $this->mOutput->setLimitReportData('limitreport-ppvisitednodes', array($this->mPPNodeCount, $this->mOptions->getMaxPPNodeCount()));
         $this->mOutput->setLimitReportData('limitreport-ppgeneratednodes', array($this->mGeneratedPPNodeCount, $this->mOptions->getMaxGeneratedPPNodeCount()));
         $this->mOutput->setLimitReportData('limitreport-postexpandincludesize', array($this->mIncludeSizes['post-expand'], $max));
         $this->mOutput->setLimitReportData('limitreport-templateargumentsize', array($this->mIncludeSizes['arg'], $max));
         $this->mOutput->setLimitReportData('limitreport-expansiondepth', array($this->mHighestExpansionDepth, $this->mOptions->getMaxPPExpandDepth()));
         $this->mOutput->setLimitReportData('limitreport-expensivefunctioncount', array($this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit()));
         wfRunHooks('ParserLimitReportPrepare', array($this, $this->mOutput));
         $limitReport = "NewPP limit report\n";
         if ($wgShowHostnames) {
             $limitReport .= 'Parsed by ' . wfHostname() . "\n";
         }
         foreach ($this->mOutput->getLimitReportData() as $key => $value) {
             if (wfRunHooks('ParserLimitReportFormat', array($key, &$value, &$limitReport, false, false))) {
                 $keyMsg = wfMessage($key)->inLanguage('en')->useDatabase(false);
                 $valueMsg = wfMessage(array("{$key}-value-text", "{$key}-value"))->inLanguage('en')->useDatabase(false);
                 if (!$valueMsg->exists()) {
                     $valueMsg = new RawMessage('$1');
                 }
                 if (!$keyMsg->isDisabled() && !$valueMsg->isDisabled()) {
                     $valueMsg->params($value);
                     $limitReport .= "{$keyMsg->text()}: {$valueMsg->text()}\n";
                 }
             }
         }
         // Since we're not really outputting HTML, decode the entities and
         // then re-encode the things that need hiding inside HTML comments.
         $limitReport = htmlspecialchars_decode($limitReport);
         wfRunHooks('ParserLimitReport', array($this, &$limitReport));
         // Sanitize for comment. Note '‐' in the replacement is U+2010,
         // which looks much like the problematic '-'.
         $limitReport = str_replace(array('-', '&'), array('‐', '&amp;'), $limitReport);
         $text .= "\n<!-- \n{$limitReport}-->\n";
         if ($this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10) {
             wfDebugLog('generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' . $this->mTitle->getPrefixedDBkey());
         }
     }
     $this->mOutput->setText($text);
     $this->mRevisionId = $oldRevisionId;
     $this->mRevisionObject = $oldRevisionObject;
     $this->mRevisionTimestamp = $oldRevisionTimestamp;
     $this->mRevisionUser = $oldRevisionUser;
     $this->mRevisionSize = $oldRevisionSize;
     $this->mInputSize = false;
     wfProfileOut($fname);
     wfProfileOut(__METHOD__);
     return $this->mOutput;
 }
Esempio n. 12
0
 /**
  * Open a connection to a foreign DB, or return one if it is already open.
  *
  * Increments a reference count on the returned connection which locks the
  * connection to the requested wiki. This reference count can be
  * decremented by calling reuseConnection().
  *
  * If a connection is open to the appropriate server already, but with the wrong
  * database, it will be switched to the right database and returned, as long as
  * it has been freed first with reuseConnection().
  *
  * On error, returns false, and the connection which caused the
  * error will be available via $this->mErrorConnection.
  *
  * @param int $i Server index
  * @param string $wiki Wiki ID to open
  * @return DatabaseBase
  */
 private function openForeignConnection($i, $wiki)
 {
     list($dbName, $prefix) = wfSplitWikiID($wiki);
     if (isset($this->mConns['foreignUsed'][$i][$wiki])) {
         // Reuse an already-used connection
         $conn = $this->mConns['foreignUsed'][$i][$wiki];
         wfDebug(__METHOD__ . ": reusing connection {$i}/{$wiki}\n");
     } elseif (isset($this->mConns['foreignFree'][$i][$wiki])) {
         // Reuse a free connection for the same wiki
         $conn = $this->mConns['foreignFree'][$i][$wiki];
         unset($this->mConns['foreignFree'][$i][$wiki]);
         $this->mConns['foreignUsed'][$i][$wiki] = $conn;
         wfDebug(__METHOD__ . ": reusing free connection {$i}/{$wiki}\n");
     } elseif (!empty($this->mConns['foreignFree'][$i])) {
         // Reuse a connection from another wiki
         $conn = reset($this->mConns['foreignFree'][$i]);
         $oldWiki = key($this->mConns['foreignFree'][$i]);
         // The empty string as a DB name means "don't care".
         // DatabaseMysqlBase::open() already handle this on connection.
         if ($dbName !== '' && !$conn->selectDB($dbName)) {
             $this->mLastError = "Error selecting database {$dbName} on server " . $conn->getServer() . " from client host " . wfHostname() . "\n";
             $this->mErrorConnection = $conn;
             $conn = false;
         } else {
             $conn->tablePrefix($prefix);
             unset($this->mConns['foreignFree'][$i][$oldWiki]);
             $this->mConns['foreignUsed'][$i][$wiki] = $conn;
             wfDebug(__METHOD__ . ": reusing free connection from {$oldWiki} for {$wiki}\n");
         }
     } else {
         // Open a new connection
         $server = $this->mServers[$i];
         $server['serverIndex'] = $i;
         $server['foreignPoolRefCount'] = 0;
         $server['foreign'] = true;
         $conn = $this->reallyOpenConnection($server, $dbName);
         if (!$conn->isOpen()) {
             wfDebug(__METHOD__ . ": error opening connection for {$i}/{$wiki}\n");
             $this->mErrorConnection = $conn;
             $conn = false;
         } else {
             $conn->tablePrefix($prefix);
             $this->mConns['foreignUsed'][$i][$wiki] = $conn;
             wfDebug(__METHOD__ . ": opened new connection for {$i}/{$wiki}\n");
         }
     }
     // Increment reference count
     if ($conn) {
         $refCount = $conn->getLBInfo('foreignPoolRefCount');
         $conn->setLBInfo('foreignPoolRefCount', $refCount + 1);
     }
     return $conn;
 }
Esempio n. 13
0
 /**
  * Convert wikitext to HTML
  * Do not call this function recursively.
  *
  * @param string $text Text we want to parse
  * @param Title $title
  * @param ParserOptions $options
  * @param bool $linestart
  * @param bool $clearState
  * @param int $revid Number to pass in {{REVISIONID}}
  * @return ParserOutput A ParserOutput
  */
 public function parse($text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null)
 {
     /**
      * First pass--just handle <nowiki> sections, pass the rest off
      * to internalParse() which does all the real work.
      */
     global $wgShowHostnames;
     if ($clearState) {
         // We use U+007F DELETE to construct strip markers, so we have to make
         // sure that this character does not occur in the input text.
         $text = strtr($text, "", "?");
         $magicScopeVariable = $this->lock();
     }
     $this->startParse($title, $options, self::OT_HTML, $clearState);
     $this->currentRevisionCache = null;
     $this->mInputSize = strlen($text);
     if ($this->mOptions->getEnableLimitReport()) {
         $this->mOutput->resetParseStartTime();
     }
     $oldRevisionId = $this->mRevisionId;
     $oldRevisionObject = $this->mRevisionObject;
     $oldRevisionTimestamp = $this->mRevisionTimestamp;
     $oldRevisionUser = $this->mRevisionUser;
     $oldRevisionSize = $this->mRevisionSize;
     if ($revid !== null) {
         $this->mRevisionId = $revid;
         $this->mRevisionObject = null;
         $this->mRevisionTimestamp = null;
         $this->mRevisionUser = null;
         $this->mRevisionSize = null;
     }
     Hooks::run('ParserBeforeStrip', array(&$this, &$text, &$this->mStripState));
     # No more strip!
     Hooks::run('ParserAfterStrip', array(&$this, &$text, &$this->mStripState));
     $text = $this->internalParse($text);
     Hooks::run('ParserAfterParse', array(&$this, &$text, &$this->mStripState));
     $text = $this->internalParseHalfParsed($text, true, $linestart);
     /**
      * A converted title will be provided in the output object if title and
      * content conversion are enabled, the article text does not contain
      * a conversion-suppressing double-underscore tag, and no
      * {{DISPLAYTITLE:...}} is present. DISPLAYTITLE takes precedence over
      * automatic link conversion.
      */
     if (!($options->getDisableTitleConversion() || isset($this->mDoubleUnderscores['nocontentconvert']) || isset($this->mDoubleUnderscores['notitleconvert']) || $this->mOutput->getDisplayTitle() !== false)) {
         $convruletitle = $this->getConverterLanguage()->getConvRuleTitle();
         if ($convruletitle) {
             $this->mOutput->setTitleText($convruletitle);
         } else {
             $titleText = $this->getConverterLanguage()->convertTitle($title);
             $this->mOutput->setTitleText($titleText);
         }
     }
     if ($this->mExpensiveFunctionCount > $this->mOptions->getExpensiveParserFunctionLimit()) {
         $this->limitationWarn('expensive-parserfunction', $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit());
     }
     # Information on include size limits, for the benefit of users who try to skirt them
     if ($this->mOptions->getEnableLimitReport()) {
         $max = $this->mOptions->getMaxIncludeSize();
         $cpuTime = $this->mOutput->getTimeSinceStart('cpu');
         if ($cpuTime !== null) {
             $this->mOutput->setLimitReportData('limitreport-cputime', sprintf("%.3f", $cpuTime));
         }
         $wallTime = $this->mOutput->getTimeSinceStart('wall');
         $this->mOutput->setLimitReportData('limitreport-walltime', sprintf("%.3f", $wallTime));
         $this->mOutput->setLimitReportData('limitreport-ppvisitednodes', array($this->mPPNodeCount, $this->mOptions->getMaxPPNodeCount()));
         $this->mOutput->setLimitReportData('limitreport-ppgeneratednodes', array($this->mGeneratedPPNodeCount, $this->mOptions->getMaxGeneratedPPNodeCount()));
         $this->mOutput->setLimitReportData('limitreport-postexpandincludesize', array($this->mIncludeSizes['post-expand'], $max));
         $this->mOutput->setLimitReportData('limitreport-templateargumentsize', array($this->mIncludeSizes['arg'], $max));
         $this->mOutput->setLimitReportData('limitreport-expansiondepth', array($this->mHighestExpansionDepth, $this->mOptions->getMaxPPExpandDepth()));
         $this->mOutput->setLimitReportData('limitreport-expensivefunctioncount', array($this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit()));
         Hooks::run('ParserLimitReportPrepare', array($this, $this->mOutput));
         $limitReport = "NewPP limit report\n";
         if ($wgShowHostnames) {
             $limitReport .= 'Parsed by ' . wfHostname() . "\n";
         }
         $limitReport .= 'Cached time: ' . $this->mOutput->getCacheTime() . "\n";
         $limitReport .= 'Cache expiry: ' . $this->mOutput->getCacheExpiry() . "\n";
         $limitReport .= 'Dynamic content: ' . ($this->mOutput->hasDynamicContent() ? 'true' : 'false') . "\n";
         foreach ($this->mOutput->getLimitReportData() as $key => $value) {
             if (Hooks::run('ParserLimitReportFormat', array($key, &$value, &$limitReport, false, false))) {
                 $keyMsg = wfMessage($key)->inLanguage('en')->useDatabase(false);
                 $valueMsg = wfMessage(array("{$key}-value-text", "{$key}-value"))->inLanguage('en')->useDatabase(false);
                 if (!$valueMsg->exists()) {
                     $valueMsg = new RawMessage('$1');
                 }
                 if (!$keyMsg->isDisabled() && !$valueMsg->isDisabled()) {
                     $valueMsg->params($value);
                     $limitReport .= "{$keyMsg->text()}: {$valueMsg->text()}\n";
                 }
             }
         }
         // Since we're not really outputting HTML, decode the entities and
         // then re-encode the things that need hiding inside HTML comments.
         $limitReport = htmlspecialchars_decode($limitReport);
         Hooks::run('ParserLimitReport', array($this, &$limitReport));
         // Sanitize for comment. Note '‐' in the replacement is U+2010,
         // which looks much like the problematic '-'.
         $limitReport = str_replace(array('-', '&'), array('‐', '&amp;'), $limitReport);
         $text .= "\n<!-- \n{$limitReport}-->\n";
         // Add on template profiling data
         $dataByFunc = $this->mProfiler->getFunctionStats();
         uasort($dataByFunc, function ($a, $b) {
             return $a['real'] < $b['real'];
             // descending order
         });
         $profileReport = "Transclusion expansion time report (%,ms,calls,template)\n";
         foreach (array_slice($dataByFunc, 0, 10) as $item) {
             $profileReport .= sprintf("%6.2f%% %8.3f %6d - %s\n", $item['%real'], $item['real'], $item['calls'], htmlspecialchars($item['name']));
         }
         $text .= "\n<!-- \n{$profileReport}-->\n";
         if ($this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10) {
             wfDebugLog('generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' . $this->mTitle->getPrefixedDBkey());
         }
     }
     $this->mOutput->setText($text);
     $this->mRevisionId = $oldRevisionId;
     $this->mRevisionObject = $oldRevisionObject;
     $this->mRevisionTimestamp = $oldRevisionTimestamp;
     $this->mRevisionUser = $oldRevisionUser;
     $this->mRevisionSize = $oldRevisionSize;
     $this->mInputSize = false;
     $this->currentRevisionCache = null;
     return $this->mOutput;
 }
Esempio n. 14
0
 function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0)
 {
     global $wgDjvuRenderer, $wgDjvuPostProcessor;
     // Fetch XML and check it, to give a more informative error message than the one which
     // normaliseParams will inevitably give.
     $xml = $image->getMetadata();
     if (!$xml) {
         return new MediaTransformError('thumbnail_error', @$params['width'], @$params['height'], wfMsg('djvu_no_xml'));
     }
     if (!$this->normaliseParams($image, $params)) {
         return new TransformParameterError($params);
     }
     $width = $params['width'];
     $height = $params['height'];
     $srcPath = $image->getPath();
     $page = $params['page'];
     if ($page > $this->pageCount($image)) {
         return new MediaTransformError('thumbnail_error', $width, $height, wfMsg('djvu_page_error'));
     }
     if ($flags & self::TRANSFORM_LATER) {
         return new ThumbnailImage($image, $dstUrl, $width, $height, $dstPath, $page);
     }
     if (!wfMkdirParents(dirname($dstPath))) {
         return new MediaTransformError('thumbnail_error', $width, $height, wfMsg('thumbnail_dest_directory'));
     }
     # Use a subshell (brackets) to aggregate stderr from both pipeline commands
     # before redirecting it to the overall stdout. This works in both Linux and Windows XP.
     $cmd = '(' . wfEscapeShellArg($wgDjvuRenderer) . " -format=ppm -page={$page} -size={$width}x{$height} " . wfEscapeShellArg($srcPath);
     if ($wgDjvuPostProcessor) {
         $cmd .= " | {$wgDjvuPostProcessor}";
     }
     $cmd .= ' > ' . wfEscapeShellArg($dstPath) . ') 2>&1';
     wfProfileIn('ddjvu');
     wfDebug(__METHOD__ . ": {$cmd}\n");
     $err = wfShellExec($cmd, $retval);
     wfProfileOut('ddjvu');
     $removed = $this->removeBadFile($dstPath, $retval);
     if ($retval != 0 || $removed) {
         wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd));
         return new MediaTransformError('thumbnail_error', $width, $height, $err);
     } else {
         return new ThumbnailImage($image, $dstUrl, $width, $height, $dstPath, $page);
     }
 }
Esempio n. 15
0
/**
 * Returns a script tag that stores the amount of time it took MediaWiki to
 * handle the request in milliseconds as 'wgBackendResponseTime'.
 *
 * If $wgShowHostnames is true, the script will also set 'wgHostname' to the
 * hostname of the server handling the request.
 *
 * @return string
 */
function wfReportTime()
{
    global $wgRequestTime, $wgShowHostnames;
    $responseTime = round((microtime(true) - $wgRequestTime) * 1000);
    $reportVars = array('wgBackendResponseTime' => $responseTime);
    if ($wgShowHostnames) {
        $reportVars['wgHostname'] = wfHostname();
    }
    return Skin::makeVariablesScript($reportVars);
}
Esempio n. 16
0
/**
 * Output a thumbnail generation error message
 *
 * @param $status integer
 * @param $msg string
 * @return void
 */
function wfThumbError($status, $msg)
{
    global $wgShowHostnames;
    header('Cache-Control: no-cache');
    header('Content-Type: text/html; charset=utf-8');
    if ($status == 404) {
        header('HTTP/1.1 404 Not found');
    } elseif ($status == 403) {
        header('HTTP/1.1 403 Forbidden');
        header('Vary: Cookie');
    } else {
        header('HTTP/1.1 500 Internal server error');
    }
    if ($wgShowHostnames) {
        $url = htmlspecialchars(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '');
        $hostname = htmlspecialchars(wfHostname());
        $debug = "<!-- {$url} -->\n<!-- {$hostname} -->\n";
    } else {
        $debug = '';
    }
    echo <<<EOT
<html><head><title>Error generating thumbnail</title></head>
<body>
<h1>Error generating thumbnail</h1>
<p>
{$msg}
</p>
{$debug}
</body>
</html>

EOT;
}
Esempio n. 17
0
 /**
  * Log a function into the database.
  *
  * @param $name String: function name
  * @param $timeSum Float
  * @param $eventCount Integer: number of times that function was called
  * @param $memorySum Integer: memory used by the function
  */
 static function logToDB($name, $timeSum, $eventCount, $memorySum)
 {
     # Do not log anything if database is readonly (bug 5375)
     if (wfReadOnly()) {
         return;
     }
     global $wgProfilePerHost;
     $dbw = wfGetDB(DB_MASTER);
     if (!is_object($dbw)) {
         return false;
     }
     $errorState = $dbw->ignoreErrors(true);
     $name = substr($name, 0, 255);
     if ($wgProfilePerHost) {
         $pfhost = wfHostname();
     } else {
         $pfhost = '';
     }
     // Kludge
     $timeSum = $timeSum >= 0 ? $timeSum : 0;
     $memorySum = $memorySum >= 0 ? $memorySum : 0;
     $dbw->update('profiling', array("pf_count=pf_count+{$eventCount}", "pf_time=pf_time+{$timeSum}", "pf_memory=pf_memory+{$memorySum}"), array('pf_name' => $name, 'pf_server' => $pfhost), __METHOD__);
     $rc = $dbw->affectedRows();
     if ($rc == 0) {
         $dbw->insert('profiling', array('pf_name' => $name, 'pf_count' => $eventCount, 'pf_time' => $timeSum, 'pf_memory' => $memorySum, 'pf_server' => $pfhost), __METHOD__, array('IGNORE'));
     }
     // When we upgrade to mysql 4.1, the insert+update
     // can be merged into just a insert with this construct added:
     //     "ON DUPLICATE KEY UPDATE ".
     //     "pf_count=pf_count + VALUES(pf_count), ".
     //     "pf_time=pf_time + VALUES(pf_time)";
     $dbw->ignoreErrors($errorState);
 }
Esempio n. 18
0
 /**
  * Log an error that occurred in an external process
  *
  * Moved from BitmapHandler to MediaHandler with MediaWiki 1.23
  *
  * @since 1.23
  * @param int $retval
  * @param string $err Error reported by command. Anything longer than
  * MediaHandler::MAX_ERR_LOG_SIZE is stripped off.
  * @param string $cmd
  */
 protected function logErrorForExternalProcess($retval, $err, $cmd)
 {
     # Keep error output limited (bug 57985)
     $errMessage = trim(substr($err, 0, self::MAX_ERR_LOG_SIZE));
     wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, $errMessage, $cmd));
 }
 /**
  * Create a thumbnail.
  *
  * This sets up various parameters, and then calls a helper method
  * based on $this->getScalerType in order to scale the image.
  *
  * @param File $image
  * @param string $dstPath
  * @param string $dstUrl
  * @param array $params
  * @param int $flags
  * @return MediaTransformError|ThumbnailImage|TransformParameterError
  */
 function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0)
 {
     if (!$this->normaliseParams($image, $params)) {
         return new TransformParameterError($params);
     }
     # Create a parameter array to pass to the scaler
     $scalerParams = array('physicalWidth' => $params['physicalWidth'], 'physicalHeight' => $params['physicalHeight'], 'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}", 'clientWidth' => $params['width'], 'clientHeight' => $params['height'], 'comment' => isset($params['descriptionUrl']) ? "File source: {$params['descriptionUrl']}" : '', 'srcWidth' => $image->getWidth(), 'srcHeight' => $image->getHeight(), 'mimeType' => $image->getMimeType(), 'dstPath' => $dstPath, 'dstUrl' => $dstUrl);
     if (isset($params['quality']) && $params['quality'] === 'low') {
         $scalerParams['quality'] = 30;
     }
     // For subclasses that might be paged.
     if ($image->isMultipage() && isset($params['page'])) {
         $scalerParams['page'] = intval($params['page']);
     }
     # Determine scaler type
     $scaler = $this->getScalerType($dstPath);
     if (is_array($scaler)) {
         $scalerName = get_class($scaler[0]);
     } else {
         $scalerName = $scaler;
     }
     wfDebug(__METHOD__ . ": creating {$scalerParams['physicalDimensions']} " . "thumbnail at {$dstPath} using scaler {$scalerName}\n");
     if (!$image->mustRender() && $scalerParams['physicalWidth'] == $scalerParams['srcWidth'] && $scalerParams['physicalHeight'] == $scalerParams['srcHeight'] && !isset($scalerParams['quality'])) {
         # normaliseParams (or the user) wants us to return the unscaled image
         wfDebug(__METHOD__ . ": returning unscaled image\n");
         return $this->getClientScalingThumbnailImage($image, $scalerParams);
     }
     if ($scaler == 'client') {
         # Client-side image scaling, use the source URL
         # Using the destination URL in a TRANSFORM_LATER request would be incorrect
         return $this->getClientScalingThumbnailImage($image, $scalerParams);
     }
     if ($image->isTransformedLocally() && !$this->isImageAreaOkForThumbnaling($image, $params)) {
         global $wgMaxImageArea;
         return new TransformTooBigImageAreaError($params, $wgMaxImageArea);
     }
     if ($flags & self::TRANSFORM_LATER) {
         wfDebug(__METHOD__ . ": Transforming later per flags.\n");
         $newParams = array('width' => $scalerParams['clientWidth'], 'height' => $scalerParams['clientHeight']);
         if (isset($params['quality'])) {
             $newParams['quality'] = $params['quality'];
         }
         if (isset($params['page']) && $params['page']) {
             $newParams['page'] = $params['page'];
         }
         return new ThumbnailImage($image, $dstUrl, false, $newParams);
     }
     # Try to make a target path for the thumbnail
     if (!wfMkdirParents(dirname($dstPath), null, __METHOD__)) {
         wfDebug(__METHOD__ . ": Unable to create thumbnail destination " . "directory, falling back to client scaling\n");
         return $this->getClientScalingThumbnailImage($image, $scalerParams);
     }
     # Transform functions and binaries need a FS source file
     $thumbnailSource = $this->getThumbnailSource($image, $params);
     // If the source isn't the original, disable EXIF rotation because it's already been applied
     if ($scalerParams['srcWidth'] != $thumbnailSource['width'] || $scalerParams['srcHeight'] != $thumbnailSource['height']) {
         $scalerParams['disableRotation'] = true;
     }
     $scalerParams['srcPath'] = $thumbnailSource['path'];
     $scalerParams['srcWidth'] = $thumbnailSource['width'];
     $scalerParams['srcHeight'] = $thumbnailSource['height'];
     if ($scalerParams['srcPath'] === false) {
         // Failed to get local copy
         wfDebugLog('thumbnail', sprintf('Thumbnail failed on %s: could not get local copy of "%s"', wfHostname(), $image->getName()));
         return new MediaTransformError('thumbnail_error', $scalerParams['clientWidth'], $scalerParams['clientHeight'], wfMessage('filemissing')->text());
     }
     # Try a hook. Called "Bitmap" for historical reasons.
     /** @var $mto MediaTransformOutput */
     $mto = null;
     Hooks::run('BitmapHandlerTransform', array($this, $image, &$scalerParams, &$mto));
     if (!is_null($mto)) {
         wfDebug(__METHOD__ . ": Hook to BitmapHandlerTransform created an mto\n");
         $scaler = 'hookaborted';
     }
     // $scaler will return a MediaTransformError on failure, or false on success.
     // If the scaler is succesful, it will have created a thumbnail at the destination
     // path.
     if (is_array($scaler) && is_callable($scaler)) {
         // Allow subclasses to specify their own rendering methods.
         $err = call_user_func($scaler, $image, $scalerParams);
     } else {
         switch ($scaler) {
             case 'hookaborted':
                 # Handled by the hook above
                 $err = $mto->isError() ? $mto : false;
                 break;
             case 'im':
                 $err = $this->transformImageMagick($image, $scalerParams);
                 break;
             case 'custom':
                 $err = $this->transformCustom($image, $scalerParams);
                 break;
             case 'imext':
                 $err = $this->transformImageMagickExt($image, $scalerParams);
                 break;
             case 'gd':
             default:
                 $err = $this->transformGd($image, $scalerParams);
                 break;
         }
     }
     # Remove the file if a zero-byte thumbnail was created, or if there was an error
     $removed = $this->removeBadFile($dstPath, (bool) $err);
     if ($err) {
         # transform returned MediaTransforError
         return $err;
     } elseif ($removed) {
         # Thumbnail was zero-byte and had to be removed
         return new MediaTransformError('thumbnail_error', $scalerParams['clientWidth'], $scalerParams['clientHeight'], wfMessage('unknown-error')->text());
     } elseif ($mto) {
         return $mto;
     } else {
         $newParams = array('width' => $scalerParams['clientWidth'], 'height' => $scalerParams['clientHeight']);
         if (isset($params['quality'])) {
             $newParams['quality'] = $params['quality'];
         }
         if (isset($params['page']) && $params['page']) {
             $newParams['page'] = $params['page'];
         }
         return new ThumbnailImage($image, $dstUrl, $dstPath, $newParams);
     }
 }
Esempio n. 20
0
 /**
  * Format a message as `wfDebugLog() would have formatted it.
  *
  * @param string $channel
  * @param string $message
  * @param array $context
  * @return null
  */
 protected static function formatAsWfDebugLog($channel, $message, $context)
 {
     $time = wfTimestamp(TS_DB);
     $wiki = wfWikiID();
     $host = wfHostname();
     $text = "{$time} {$host} {$wiki}: {$message}\n";
     return $text;
 }
Esempio n. 21
0
 /**
  * Add response headers with debug data and statistics
  *
  * @param WebResponse $response
  * @author macbre
  */
 private static function addExtraHeaders(WebResponse $response)
 {
     global $wgRequestTime;
     $elapsed = microtime(true) - $wgRequestTime;
     $response->header(sprintf('X-Served-By:%s', wfHostname()));
     $response->header(sprintf('X-Backend-Response-Time:%01.3f', $elapsed));
     $response->header('X-Cache: ORIGIN');
     $response->header('X-Cache-Hits: ORIGIN');
 }
Esempio n. 22
0
 /** Open an MSSQL database and return a resource handle to it
  *  NOTE: only $dbName is used, the other parameters are irrelevant for MSSQL databases
  */
 function open($server, $user, $password, $dbName)
 {
     wfProfileIn(__METHOD__);
     # Test for missing mysql.so
     # First try to load it
     if (!@extension_loaded('mssql')) {
         @dl('mssql.so');
     }
     # Fail now
     # Otherwise we get a suppressed fatal error, which is very hard to track down
     if (!function_exists('mssql_connect')) {
         throw new DBConnectionError($this, "MSSQL functions missing, have you compiled PHP with the --with-mssql option?\n");
     }
     $this->close();
     $this->mServer = $server;
     $this->mUser = $user;
     $this->mPassword = $password;
     $this->mDBname = $dbName;
     wfProfileIn("dbconnect-{$server}");
     # Try to connect up to three times
     # The kernel's default SYN retransmission period is far too slow for us,
     # so we use a short timeout plus a manual retry.
     $this->mConn = false;
     $max = 3;
     for ($i = 0; $i < $max && !$this->mConn; $i++) {
         if ($i > 1) {
             usleep(1000);
         }
         if ($this->mFlags & DBO_PERSISTENT) {
             @($this->mConn = mssql_pconnect($server, $user, $password));
         } else {
             # Create a new connection...
             @($this->mConn = mssql_connect($server, $user, $password, true));
         }
     }
     wfProfileOut("dbconnect-{$server}");
     if ($dbName != '') {
         if ($this->mConn !== false) {
             $success = @mssql_select_db($dbName, $this->mConn);
             if (!$success) {
                 $error = "Error selecting database {$dbName} on server {$this->mServer} " . "from client host " . wfHostname() . "\n";
                 wfLogDBError(" Error selecting database {$dbName} on server {$this->mServer} \n");
                 wfDebug($error);
             }
         } else {
             wfDebug("DB connection error\n");
             wfDebug("Server: {$server}, User: {$user}, Password: "******"...\n");
             $success = false;
         }
     } else {
         # Delay USE query
         $success = (bool) $this->mConn;
     }
     if (!$success) {
         $this->reportConnectionError();
     }
     $this->mOpened = $success;
     wfProfileOut(__METHOD__);
     return $success;
 }
Esempio n. 23
0
	/**
	 * @param $server string
	 * @param $user string
	 * @param $password string
	 * @param $dbName string
	 * @return bool
	 * @throws DBConnectionError
	 */
	function open( $server, $user, $password, $dbName ) {
		global $wgAllDBsAreLocalhost, $wgDBmysql5, $wgSQLMode;
		wfProfileIn( __METHOD__ );

		# Debugging hack -- fake cluster
		if ( $wgAllDBsAreLocalhost ) {
			$realServer = 'localhost';
		} else {
			$realServer = $server;
		}
		$this->close();
		$this->mServer = $server;
		$this->mUser = $user;
		$this->mPassword = $password;
		$this->mDBname = $dbName;

		wfProfileIn( "dbconnect-$server" );

		# The kernel's default SYN retransmission period is far too slow for us,
		# so we use a short timeout plus a manual retry. Retrying means that a small
		# but finite rate of SYN packet loss won't cause user-visible errors.
		$this->mConn = false;
		$this->installErrorHandler();
		try {
			$this->mConn = $this->mysqlConnect( $realServer );
		} catch ( Exception $ex ) {
			wfProfileOut( "dbconnect-$server" );
			wfProfileOut( __METHOD__ );
			throw $ex;
		}
		$error = $this->restoreErrorHandler();

		wfProfileOut( "dbconnect-$server" );

		# Always log connection errors
		if ( !$this->mConn ) {
			if ( !$error ) {
				$error = $this->lastError();
			}
			wfLogDBError( "Error connecting to {$this->mServer}: $error\n" );
			wfDebug( "DB connection error\n" .
				"Server: $server, User: $user, Password: "******"..., error: " . $error . "\n" );

			wfProfileOut( __METHOD__ );
			return $this->reportConnectionError( $error );
		}

		if ( $dbName != '' ) {
			wfSuppressWarnings();
			$success = $this->selectDB( $dbName );
			wfRestoreWarnings();
			if ( !$success ) {
				wfLogDBError( "Error selecting database $dbName on server {$this->mServer}\n" );
				wfDebug( "Error selecting database $dbName on server {$this->mServer} " .
					"from client host " . wfHostname() . "\n" );

				wfProfileOut( __METHOD__ );
				return $this->reportConnectionError( "Error selecting database $dbName" );
			}
		}

		// Tell the server we're communicating with it in UTF-8.
		// This may engage various charset conversions.
		if ( $wgDBmysql5 ) {
			$this->query( 'SET NAMES utf8', __METHOD__ );
		} else {
			$this->query( 'SET NAMES binary', __METHOD__ );
		}
		// Set SQL mode, default is turning them all off, can be overridden or skipped with null
		if ( is_string( $wgSQLMode ) ) {
			$mode = $this->addQuotes( $wgSQLMode );
			$this->query( "SET sql_mode = $mode", __METHOD__ );
		}

		$this->mOpened = true;
		wfProfileOut( __METHOD__ );
		return true;
	}
Esempio n. 24
0
 /**
  * Convert wikitext to HTML
  * Do not call this function recursively.
  *
  * @param string $text Text we want to parse
  * @param Title $title
  * @param ParserOptions $options
  * @param bool $linestart
  * @param bool $clearState
  * @param int $revid Number to pass in {{REVISIONID}}
  * @return ParserOutput A ParserOutput
  */
 public function parse($text, Title $title, ParserOptions $options, $linestart = true, $clearState = true, $revid = null)
 {
     /**
      * First pass--just handle <nowiki> sections, pass the rest off
      * to internalParse() which does all the real work.
      */
     global $wgShowHostnames;
     if ($clearState) {
         // We use U+007F DELETE to construct strip markers, so we have to make
         // sure that this character does not occur in the input text.
         $text = strtr($text, "", "?");
         $magicScopeVariable = $this->lock();
     }
     $this->startParse($title, $options, self::OT_HTML, $clearState);
     $this->currentRevisionCache = null;
     $this->mInputSize = strlen($text);
     if ($this->mOptions->getEnableLimitReport()) {
         $this->mOutput->resetParseStartTime();
     }
     $oldRevisionId = $this->mRevisionId;
     $oldRevisionObject = $this->mRevisionObject;
     $oldRevisionTimestamp = $this->mRevisionTimestamp;
     $oldRevisionUser = $this->mRevisionUser;
     $oldRevisionSize = $this->mRevisionSize;
     if ($revid !== null) {
         $this->mRevisionId = $revid;
         $this->mRevisionObject = null;
         $this->mRevisionTimestamp = null;
         $this->mRevisionUser = null;
         $this->mRevisionSize = null;
     }
     Hooks::run('ParserBeforeStrip', [&$this, &$text, &$this->mStripState]);
     # No more strip!
     Hooks::run('ParserAfterStrip', [&$this, &$text, &$this->mStripState]);
     $text = $this->internalParse($text);
     Hooks::run('ParserAfterParse', [&$this, &$text, &$this->mStripState]);
     $text = $this->internalParseHalfParsed($text, true, $linestart);
     /**
      * A converted title will be provided in the output object if title and
      * content conversion are enabled, the article text does not contain
      * a conversion-suppressing double-underscore tag, and no
      * {{DISPLAYTITLE:...}} is present. DISPLAYTITLE takes precedence over
      * automatic link conversion.
      */
     if (!($options->getDisableTitleConversion() || isset($this->mDoubleUnderscores['nocontentconvert']) || isset($this->mDoubleUnderscores['notitleconvert']) || $this->mOutput->getDisplayTitle() !== false)) {
         $convruletitle = $this->getConverterLanguage()->getConvRuleTitle();
         if ($convruletitle) {
             $this->mOutput->setTitleText($convruletitle);
         } else {
             $titleText = $this->getConverterLanguage()->convertTitle($title);
             $this->mOutput->setTitleText($titleText);
         }
     }
     # Done parsing! Compute runtime adaptive expiry if set
     $this->mOutput->finalizeAdaptiveCacheExpiry();
     # Warn if too many heavyweight parser functions were used
     if ($this->mExpensiveFunctionCount > $this->mOptions->getExpensiveParserFunctionLimit()) {
         $this->limitationWarn('expensive-parserfunction', $this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit());
     }
     # Information on include size limits, for the benefit of users who try to skirt them
     if ($this->mOptions->getEnableLimitReport()) {
         $max = $this->mOptions->getMaxIncludeSize();
         $cpuTime = $this->mOutput->getTimeSinceStart('cpu');
         if ($cpuTime !== null) {
             $this->mOutput->setLimitReportData('limitreport-cputime', sprintf("%.3f", $cpuTime));
         }
         $wallTime = $this->mOutput->getTimeSinceStart('wall');
         $this->mOutput->setLimitReportData('limitreport-walltime', sprintf("%.3f", $wallTime));
         $this->mOutput->setLimitReportData('limitreport-ppvisitednodes', [$this->mPPNodeCount, $this->mOptions->getMaxPPNodeCount()]);
         $this->mOutput->setLimitReportData('limitreport-ppgeneratednodes', [$this->mGeneratedPPNodeCount, $this->mOptions->getMaxGeneratedPPNodeCount()]);
         $this->mOutput->setLimitReportData('limitreport-postexpandincludesize', [$this->mIncludeSizes['post-expand'], $max]);
         $this->mOutput->setLimitReportData('limitreport-templateargumentsize', [$this->mIncludeSizes['arg'], $max]);
         $this->mOutput->setLimitReportData('limitreport-expansiondepth', [$this->mHighestExpansionDepth, $this->mOptions->getMaxPPExpandDepth()]);
         $this->mOutput->setLimitReportData('limitreport-expensivefunctioncount', [$this->mExpensiveFunctionCount, $this->mOptions->getExpensiveParserFunctionLimit()]);
         Hooks::run('ParserLimitReportPrepare', [$this, $this->mOutput]);
         $limitReport = '';
         Hooks::run('ParserLimitReport', [$this, &$limitReport]);
         if ($limitReport != '') {
             // Sanitize for comment. Note '‐' in the replacement is U+2010,
             // which looks much like the problematic '-'.
             $limitReport = str_replace(['-', '&'], ['‐', '&amp;'], $limitReport);
             $text .= "\n<!-- \nNewPP limit report\n{$limitReport}-->\n";
         }
         // Add on template profiling data in human/machine readable way
         $dataByFunc = $this->mProfiler->getFunctionStats();
         uasort($dataByFunc, function ($a, $b) {
             return $a['real'] < $b['real'];
             // descending order
         });
         $profileReport = [];
         foreach (array_slice($dataByFunc, 0, 10) as $item) {
             $profileReport[] = sprintf("%6.2f%% %8.3f %6d %s", $item['%real'], $item['real'], $item['calls'], $item['name']);
         }
         $this->mOutput->setLimitReportData('limitreport-timingprofile', $profileReport);
         // Add other cache related metadata
         if ($wgShowHostnames) {
             $this->mOutput->setLimitReportData('cachereport-origin', wfHostname());
         }
         $this->mOutput->setLimitReportData('cachereport-timestamp', $this->mOutput->getCacheTime());
         $this->mOutput->setLimitReportData('cachereport-ttl', $this->mOutput->getCacheExpiry());
         $this->mOutput->setLimitReportData('cachereport-transientcontent', $this->mOutput->hasDynamicContent());
         if ($this->mGeneratedPPNodeCount > $this->mOptions->getMaxGeneratedPPNodeCount() / 10) {
             wfDebugLog('generated-pp-node-count', $this->mGeneratedPPNodeCount . ' ' . $this->mTitle->getPrefixedDBkey());
         }
     }
     $this->mOutput->setText($text);
     $this->mRevisionId = $oldRevisionId;
     $this->mRevisionObject = $oldRevisionObject;
     $this->mRevisionTimestamp = $oldRevisionTimestamp;
     $this->mRevisionUser = $oldRevisionUser;
     $this->mRevisionSize = $oldRevisionSize;
     $this->mInputSize = false;
     $this->currentRevisionCache = null;
     return $this->mOutput;
 }
Esempio n. 25
0
 /**
  * Log an error that occured in an external process
  *
  * @param $retval int
  * @param $err int
  * @param $cmd string
  */
 protected function logErrorForExternalProcess($retval, $err, $cmd)
 {
     wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd));
 }
Esempio n. 26
0
 /**
  * @param File $image
  * @param string $dstPath
  * @param string $dstUrl
  * @param array $params
  * @param int $flags
  * @return bool|MediaTransformError|ThumbnailImage|TransformParameterError
  */
 function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0)
 {
     if (!$this->normaliseParams($image, $params)) {
         return new TransformParameterError($params);
     }
     $clientWidth = $params['width'];
     $clientHeight = $params['height'];
     $physicalWidth = $params['physicalWidth'];
     $physicalHeight = $params['physicalHeight'];
     $lang = isset($params['lang']) ? $params['lang'] : $this->getDefaultRenderLanguage($image);
     if ($flags & self::TRANSFORM_LATER) {
         return new ThumbnailImage($image, $dstUrl, $dstPath, $params);
     }
     $metadata = $this->unpackMetadata($image->getMetadata());
     if (isset($metadata['error'])) {
         // sanity check
         $err = wfMessage('svg-long-error', $metadata['error']['message'])->text();
         return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err);
     }
     if (!wfMkdirParents(dirname($dstPath), null, __METHOD__)) {
         return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, wfMessage('thumbnail_dest_directory')->text());
     }
     $srcPath = $image->getLocalRefPath();
     if ($srcPath === false) {
         // Failed to get local copy
         wfDebugLog('thumbnail', sprintf('Thumbnail failed on %s: could not get local copy of "%s"', wfHostname(), $image->getName()));
         return new MediaTransformError('thumbnail_error', $params['width'], $params['height'], wfMessage('filemissing')->text());
     }
     // Make a temp dir with a symlink to the local copy in it.
     // This plays well with rsvg-convert policy for external entities.
     // https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e
     $tmpDir = wfTempDir() . '/svg_' . wfRandomString(24);
     $lnPath = "{$tmpDir}/" . basename($srcPath);
     $ok = mkdir($tmpDir, 0771) && symlink($srcPath, $lnPath);
     /** @noinspection PhpUnusedLocalVariableInspection */
     $cleaner = new ScopedCallback(function () use($tmpDir, $lnPath) {
         MediaWiki\suppressWarnings();
         unlink($lnPath);
         rmdir($tmpDir);
         MediaWiki\restoreWarnings();
     });
     if (!$ok) {
         wfDebugLog('thumbnail', sprintf('Thumbnail failed on %s: could not link %s to %s', wfHostname(), $lnPath, $srcPath));
         return new MediaTransformError('thumbnail_error', $params['width'], $params['height'], wfMessage('thumbnail-temp-create')->text());
     }
     $status = $this->rasterize($lnPath, $dstPath, $physicalWidth, $physicalHeight, $lang);
     if ($status === true) {
         return new ThumbnailImage($image, $dstUrl, $dstPath, $params);
     } else {
         return $status;
         // MediaTransformError
     }
 }
Esempio n. 27
0
 /**
  * Generate a debug comment indicating diff generating time,
  * server node, and generator backend.
  */
 protected function debug($generator = "internal")
 {
     global $wgShowHostnames;
     if (!$this->enableDebugComment) {
         return '';
     }
     $data = array($generator);
     if ($wgShowHostnames) {
         $data[] = wfHostname();
     }
     $data[] = wfTimestamp(TS_DB);
     return "<!-- diff generator: " . implode(" ", array_map("htmlspecialchars", $data)) . " -->\n";
 }
Esempio n. 28
0
 function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0)
 {
     global $wgUseImageMagick, $wgImageMagickConvertCommand, $wgImageMagickTempDir;
     global $wgCustomConvertCommand;
     global $wgSharpenParameter, $wgSharpenReductionThreshold;
     global $wgMaxAnimatedGifArea;
     if (!$this->normaliseParams($image, $params)) {
         return new TransformParameterError($params);
     }
     $physicalWidth = $params['physicalWidth'];
     $physicalHeight = $params['physicalHeight'];
     $clientWidth = $params['width'];
     $clientHeight = $params['height'];
     $srcWidth = $image->getWidth();
     $srcHeight = $image->getHeight();
     $mimeType = $image->getMimeType();
     $srcPath = $image->getPath();
     $retval = 0;
     wfDebug(__METHOD__ . ": creating {$physicalWidth}x{$physicalHeight} thumbnail at {$dstPath}\n");
     if (!$image->mustRender() && $physicalWidth == $srcWidth && $physicalHeight == $srcHeight) {
         # normaliseParams (or the user) wants us to return the unscaled image
         wfDebug(__METHOD__ . ": returning unscaled image\n");
         return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath);
     }
     if (!$dstPath) {
         // No output path available, client side scaling only
         $scaler = 'client';
     } elseif ($wgUseImageMagick) {
         $scaler = 'im';
     } elseif ($wgCustomConvertCommand) {
         $scaler = 'custom';
     } elseif (function_exists('imagecreatetruecolor')) {
         $scaler = 'gd';
     } else {
         $scaler = 'client';
     }
     wfDebug(__METHOD__ . ": scaler {$scaler}\n");
     if ($scaler == 'client') {
         # Client-side image scaling, use the source URL
         # Using the destination URL in a TRANSFORM_LATER request would be incorrect
         return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath);
     }
     if ($flags & self::TRANSFORM_LATER) {
         wfDebug(__METHOD__ . ": Transforming later per flags.\n");
         return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath);
     }
     if (!wfMkdirParents(dirname($dstPath))) {
         wfDebug(__METHOD__ . ": Unable to create thumbnail destination directory, falling back to client scaling\n");
         return new ThumbnailImage($image, $image->getURL(), $clientWidth, $clientHeight, $srcPath);
     }
     if ($scaler == 'im') {
         # use ImageMagick
         $quality = '';
         $sharpen = '';
         $frame = '';
         $animation = '';
         if ($mimeType == 'image/jpeg') {
             $quality = "-quality 80";
             // 80%
             # Sharpening, see bug 6193
             if (($physicalWidth + $physicalHeight) / ($srcWidth + $srcHeight) < $wgSharpenReductionThreshold) {
                 $sharpen = "-sharpen " . wfEscapeShellArg($wgSharpenParameter);
             }
         } elseif ($mimeType == 'image/png') {
             $quality = "-quality 95";
             // zlib 9, adaptive filtering
         } elseif ($mimeType == 'image/gif') {
             if ($srcWidth * $srcHeight > $wgMaxAnimatedGifArea) {
                 // Extract initial frame only; we're so big it'll
                 // be a total drag. :P
                 $frame = '[0]';
             } else {
                 // Coalesce is needed to scale animated GIFs properly (bug 1017).
                 $animation = ' -coalesce ';
             }
         }
         if (strval($wgImageMagickTempDir) !== '') {
             $tempEnv = 'MAGICK_TMPDIR=' . wfEscapeShellArg($wgImageMagickTempDir) . ' ';
         } else {
             $tempEnv = '';
         }
         # Specify white background color, will be used for transparent images
         # in Internet Explorer/Windows instead of default black.
         # Note, we specify "-size {$physicalWidth}" and NOT "-size {$physicalWidth}x{$physicalHeight}".
         # It seems that ImageMagick has a bug wherein it produces thumbnails of
         # the wrong size in the second case.
         $cmd = $tempEnv . wfEscapeShellArg($wgImageMagickConvertCommand) . " {$quality} -background white -size {$physicalWidth} " . wfEscapeShellArg($srcPath . $frame) . $animation . " -thumbnail " . wfEscapeShellArg("{$physicalWidth}x{$physicalHeight}!") . " -depth 8 {$sharpen} " . wfEscapeShellArg($dstPath) . " 2>&1";
         wfDebug(__METHOD__ . ": running ImageMagick: {$cmd}\n");
         wfProfileIn('convert');
         $err = wfShellExec($cmd, $retval);
         wfProfileOut('convert');
     } elseif ($scaler == 'custom') {
         # Use a custom convert command
         # Variables: %s %d %w %h
         $src = wfEscapeShellArg($srcPath);
         $dst = wfEscapeShellArg($dstPath);
         $cmd = $wgCustomConvertCommand;
         $cmd = str_replace('%s', $src, str_replace('%d', $dst, $cmd));
         # Filenames
         $cmd = str_replace('%h', $physicalHeight, str_replace('%w', $physicalWidth, $cmd));
         # Size
         wfDebug(__METHOD__ . ": Running custom convert command {$cmd}\n");
         wfProfileIn('convert');
         $err = wfShellExec($cmd, $retval);
         wfProfileOut('convert');
     } else {
         # Use PHP's builtin GD library functions.
         #
         # First find out what kind of file this is, and select the correct
         # input routine for this.
         $typemap = array('image/gif' => array('imagecreatefromgif', 'palette', 'imagegif'), 'image/jpeg' => array('imagecreatefromjpeg', 'truecolor', array(__CLASS__, 'imageJpegWrapper')), 'image/png' => array('imagecreatefrompng', 'bits', 'imagepng'), 'image/vnd.wap.wbmp' => array('imagecreatefromwbmp', 'palette', 'imagewbmp'), 'image/xbm' => array('imagecreatefromxbm', 'palette', 'imagexbm'));
         if (!isset($typemap[$mimeType])) {
             $err = 'Image type not supported';
             wfDebug("{$err}\n");
             return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err);
         }
         list($loader, $colorStyle, $saveType) = $typemap[$mimeType];
         if (!function_exists($loader)) {
             $err = "Incomplete GD library configuration: missing function {$loader}";
             wfDebug("{$err}\n");
             return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err);
         }
         $src_image = call_user_func($loader, $srcPath);
         $dst_image = imagecreatetruecolor($physicalWidth, $physicalHeight);
         // Initialise the destination image to transparent instead of
         // the default solid black, to support PNG and GIF transparency nicely
         $background = imagecolorallocate($dst_image, 0, 0, 0);
         imagecolortransparent($dst_image, $background);
         imagealphablending($dst_image, false);
         if ($colorStyle == 'palette') {
             // Don't resample for paletted GIF images.
             // It may just uglify them, and completely breaks transparency.
             imagecopyresized($dst_image, $src_image, 0, 0, 0, 0, $physicalWidth, $physicalHeight, imagesx($src_image), imagesy($src_image));
         } else {
             imagecopyresampled($dst_image, $src_image, 0, 0, 0, 0, $physicalWidth, $physicalHeight, imagesx($src_image), imagesy($src_image));
         }
         imagesavealpha($dst_image, true);
         call_user_func($saveType, $dst_image, $dstPath);
         imagedestroy($dst_image);
         imagedestroy($src_image);
         $retval = 0;
     }
     $removed = $this->removeBadFile($dstPath, $retval);
     if ($retval != 0 || $removed) {
         wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd));
         return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err);
     } else {
         return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath);
     }
 }
Esempio n. 29
0
 /**
  * @param string $server
  * @param string $user
  * @param string $password
  * @param string $dbName
  * @throws Exception|DBConnectionError
  * @return bool
  */
 function open($server, $user, $password, $dbName)
 {
     global $wgAllDBsAreLocalhost, $wgSQLMode;
     # Close/unset connection handle
     $this->close();
     # Debugging hack -- fake cluster
     $realServer = $wgAllDBsAreLocalhost ? 'localhost' : $server;
     $this->mServer = $server;
     $this->mUser = $user;
     $this->mPassword = $password;
     $this->mDBname = $dbName;
     $this->installErrorHandler();
     try {
         $this->mConn = $this->mysqlConnect($realServer);
     } catch (Exception $ex) {
         $this->restoreErrorHandler();
         throw $ex;
     }
     $error = $this->restoreErrorHandler();
     # Always log connection errors
     if (!$this->mConn) {
         if (!$error) {
             $error = $this->lastError();
         }
         wfLogDBError("Error connecting to {db_server}: {error}", $this->getLogContext(array('method' => __METHOD__, 'error' => $error)));
         wfDebug("DB connection error\n" . "Server: {$server}, User: {$user}, Password: "******"..., error: " . $error . "\n");
         $this->reportConnectionError($error);
     }
     if ($dbName != '') {
         MediaWiki\suppressWarnings();
         $success = $this->selectDB($dbName);
         MediaWiki\restoreWarnings();
         if (!$success) {
             wfLogDBError("Error selecting database {db_name} on server {db_server}", $this->getLogContext(array('method' => __METHOD__)));
             wfDebug("Error selecting database {$dbName} on server {$this->mServer} " . "from client host " . wfHostname() . "\n");
             $this->reportConnectionError("Error selecting database {$dbName}");
         }
     }
     // Tell the server what we're communicating with
     if (!$this->connectInitCharset()) {
         $this->reportConnectionError("Error setting character set");
     }
     // Abstract over any insane MySQL defaults
     $set = array('group_concat_max_len = 262144');
     // Set SQL mode, default is turning them all off, can be overridden or skipped with null
     if (is_string($wgSQLMode)) {
         $set[] = 'sql_mode = ' . $this->addQuotes($wgSQLMode);
     }
     // Set any custom settings defined by site config
     // (e.g. https://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html)
     foreach ($this->mSessionVars as $var => $val) {
         // Escape strings but not numbers to avoid MySQL complaining
         if (!is_int($val) && !is_float($val)) {
             $val = $this->addQuotes($val);
         }
         $set[] = $this->addIdentifierQuotes($var) . ' = ' . $val;
     }
     if ($set) {
         // Use doQuery() to avoid opening implicit transactions (DBO_TRX)
         $success = $this->doQuery('SET ' . implode(', ', $set));
         if (!$success) {
             wfLogDBError('Error setting MySQL variables on server {db_server} (check $wgSQLMode)', $this->getLogContext(array('method' => __METHOD__)));
             $this->reportConnectionError('Error setting MySQL variables on server {db_server} (check $wgSQLMode)');
         }
     }
     $this->mOpened = true;
     return true;
 }
Esempio n. 30
0
 /**
  * Initialize an initial random state based off of whatever we can find
  * @return string
  */
 protected function initialRandomState()
 {
     // $_SERVER contains a variety of unstable user and system specific information
     // It'll vary a little with each page, and vary even more with separate users
     // It'll also vary slightly across different machines
     $state = serialize($_SERVER);
     // To try vary the system information of the state a bit more
     // by including the system's hostname into the state
     $state .= wfHostname();
     // Try to gather a little entropy from the different php rand sources
     $state .= rand() . uniqid(mt_rand(), true);
     // Include some information about the filesystem's current state in the random state
     $files = array();
     // We know this file is here so grab some info about ourselves
     $files[] = __FILE__;
     // We must also have a parent folder, and with the usual file structure, a grandparent
     $files[] = __DIR__;
     $files[] = dirname(__DIR__);
     // The config file is likely the most often edited file we know should
     // be around so include its stat info into the state.
     // The constant with its location will almost always be defined, as
     // WebStart.php defines MW_CONFIG_FILE to $IP/LocalSettings.php unless
     // being configured with MW_CONFIG_CALLBACK (e.g. the installer).
     if (defined('MW_CONFIG_FILE')) {
         $files[] = MW_CONFIG_FILE;
     }
     foreach ($files as $file) {
         MediaWiki\suppressWarnings();
         $stat = stat($file);
         MediaWiki\restoreWarnings();
         if ($stat) {
             // stat() duplicates data into numeric and string keys so kill off all the numeric ones
             foreach ($stat as $k => $v) {
                 if (is_numeric($k)) {
                     unset($k);
                 }
             }
             // The absolute filename itself will differ from install to install so don't leave it out
             $path = realpath($file);
             if ($path !== false) {
                 $state .= $path;
             } else {
                 $state .= $file;
             }
             $state .= implode('', $stat);
         } else {
             // The fact that the file isn't there is worth at least a
             // minuscule amount of entropy.
             $state .= '0';
         }
     }
     // Try and make this a little more unstable by including the varying process
     // id of the php process we are running inside of if we are able to access it
     if (function_exists('getmypid')) {
         $state .= getmypid();
     }
     // If available try to increase the instability of the data by throwing in
     // the precise amount of memory that we happen to be using at the moment.
     if (function_exists('memory_get_usage')) {
         $state .= memory_get_usage(true);
     }
     // It's mostly worthless but throw the wiki's id into the data for a little more variance
     $state .= wfWikiID();
     // If we have a secret key set then throw it into the state as well
     global $wgSecretKey;
     if ($wgSecretKey) {
         $state .= $wgSecretKey;
     }
     return $state;
 }