public function __construct($parent)
 {
     global $wgMemc;
     $this->parent = $parent;
     $this->srvCache = ObjectCache::newAccelerator(array(), 'hash');
     $this->mainCache = $wgMemc ?: wfGetMainCache();
 }
 public function __construct()
 {
     // We use a try/catch instead of the $fallback parameter because
     // we don't want to fail here if $wgObjectCaches is not configured
     // properly for APC setup
     try {
         $this->cache = ObjectCache::newAccelerator();
     } catch (MWException $e) {
         $this->cache = new EmptyBagOStuff();
     }
 }
 /**
  * Returns a given template function if found, otherwise throws an exception.
  * @param string $templateName The name of the template (without file suffix)
  * @return callable
  * @throws RuntimeException
  */
 protected function getTemplate($templateName)
 {
     // If a renderer has already been defined for this template, reuse it
     if (isset($this->renderers[$templateName]) && is_callable($this->renderers[$templateName])) {
         return $this->renderers[$templateName];
     }
     $filename = $this->getTemplateFilename($templateName);
     if (!file_exists($filename)) {
         throw new RuntimeException("Could not locate template: {$filename}");
     }
     // Read the template file
     $fileContents = file_get_contents($filename);
     // Generate a quick hash for cache invalidation
     $fastHash = md5($fileContents);
     // Fetch a secret key for building a keyed hash of the PHP code
     $config = ConfigFactory::getDefaultInstance()->makeConfig('main');
     $secretKey = $config->get('SecretKey');
     if ($secretKey) {
         // See if the compiled PHP code is stored in cache.
         $cache = ObjectCache::newAccelerator(CACHE_ANYTHING);
         $key = $cache->makeKey('template', $templateName, $fastHash);
         $code = $this->forceRecompile ? null : $cache->get($key);
         if (!$code) {
             $code = $this->compileForEval($fileContents, $filename);
             // Prefix the cached code with a keyed hash (64 hex chars) as an integrity check
             $cache->set($key, hash_hmac('sha256', $code, $secretKey) . $code);
         } else {
             // Verify the integrity of the cached PHP code
             $keyedHash = substr($code, 0, 64);
             $code = substr($code, 64);
             if ($keyedHash !== hash_hmac('sha256', $code, $secretKey)) {
                 // Generate a notice if integrity check fails
                 trigger_error("Template failed integrity check: {$filename}");
             }
         }
         // If there is no secret key available, don't use cache
     } else {
         $code = $this->compileForEval($fileContents, $filename);
     }
     $renderer = eval($code);
     if (!is_callable($renderer)) {
         throw new RuntimeException("Requested template, {$templateName}, is not callable");
     }
     $this->renderers[$templateName] = $renderer;
     return $renderer;
 }
Beispiel #4
0
 /**
  * Return IDs that are sequential *only* for this node and bucket
  *
  * @see UIDGenerator::newSequentialPerNodeID()
  * @param string $bucket Arbitrary bucket name (should be ASCII)
  * @param int $bits Bit size (16 to 48) of resulting numbers before wrap-around
  * @param int $count Number of IDs to return (1 to 10000)
  * @param int $flags (supports UIDGenerator::QUICK_VOLATILE)
  * @return array Ordered list of float integer values
  * @throws MWException
  */
 protected function getSequentialPerNodeIDs($bucket, $bits, $count, $flags)
 {
     if ($count <= 0) {
         return array();
         // nothing to do
     } elseif ($count > 10000) {
         throw new MWException("Number of requested IDs ({$count}) is too high.");
     } elseif ($bits < 16 || $bits > 48) {
         throw new MWException("Requested bit size ({$bits}) is out of range.");
     }
     $counter = null;
     // post-increment persistent counter value
     // Use APC/eAccelerator/xcache if requested, available, and not in CLI mode;
     // Counter values would not survive accross script instances in CLI mode.
     $cache = null;
     if ($flags & self::QUICK_VOLATILE && PHP_SAPI !== 'cli') {
         try {
             $cache = ObjectCache::newAccelerator(array());
         } catch (Exception $e) {
             // not supported
         }
     }
     if ($cache) {
         $counter = $cache->incr($bucket, $count);
         if ($counter === false) {
             if (!$cache->add($bucket, (int) $count)) {
                 throw new MWException('Unable to set value to ' . get_class($cache));
             }
             $counter = $count;
         }
     }
     // Note: use of fmod() avoids "division by zero" on 32 bit machines
     if ($counter === null) {
         $path = wfTempDir() . '/mw-' . __CLASS__ . '-' . rawurlencode($bucket) . '-48';
         // Get the UID lock file handle
         if (isset($this->fileHandles[$path])) {
             $handle = $this->fileHandles[$path];
         } else {
             $handle = fopen($path, 'cb+');
             $this->fileHandles[$path] = $handle ?: null;
             // cache
         }
         // Acquire the UID lock file
         if ($handle === false) {
             throw new MWException("Could not open '{$path}'.");
         } elseif (!flock($handle, LOCK_EX)) {
             fclose($handle);
             throw new MWException("Could not acquire '{$path}'.");
         }
         // Fetch the counter value and increment it...
         rewind($handle);
         $counter = floor(trim(fgets($handle))) + $count;
         // fetch as float
         // Write back the new counter value
         ftruncate($handle, 0);
         rewind($handle);
         fwrite($handle, fmod($counter, pow(2, 48)));
         // warp-around as needed
         fflush($handle);
         // Release the UID lock file
         flock($handle, LOCK_UN);
     }
     $ids = array();
     $divisor = pow(2, $bits);
     $currentId = floor($counter - $count);
     // pre-increment counter value
     for ($i = 0; $i < $count; ++$i) {
         $ids[] = fmod(++$currentId, $divisor);
     }
     return $ids;
 }
Beispiel #5
0
 /**
  * Construct a new instance from configuration.
  *
  * @param array $config Parameters include:
  *   - dbServers   : Associative array of DB names to server configuration.
  *                   Configuration is an associative array that includes:
  *                     - host        : DB server name
  *                     - dbname      : DB name
  *                     - type        : DB type (mysql,postgres,...)
  *                     - user        : DB user
  *                     - password    : DB user password
  *                     - tablePrefix : DB table prefix
  *                     - flags       : DB flags (see DatabaseBase)
  *   - dbsByBucket : Array of 1-16 consecutive integer keys, starting from 0,
  *                   each having an odd-numbered list of DB names (peers) as values.
  *                   Any DB named 'localDBMaster' will automatically use the DB master
  *                   settings for this wiki (without the need for a dbServers entry).
  *                   Only use 'localDBMaster' if the domain is a valid wiki ID.
  *   - lockExpiry  : Lock timeout (seconds) for dropped connections. [optional]
  *                   This tells the DB server how long to wait before assuming
  *                   connection failure and releasing all the locks for a session.
  */
 public function __construct(array $config)
 {
     parent::__construct($config);
     $this->dbServers = isset($config['dbServers']) ? $config['dbServers'] : array();
     // likely just using 'localDBMaster'
     // Sanitize srvsByBucket config to prevent PHP errors
     $this->srvsByBucket = array_filter($config['dbsByBucket'], 'is_array');
     $this->srvsByBucket = array_values($this->srvsByBucket);
     // consecutive
     if (isset($config['lockExpiry'])) {
         $this->lockExpiry = $config['lockExpiry'];
     } else {
         $met = ini_get('max_execution_time');
         $this->lockExpiry = $met ? $met : 60;
         // use some sane amount if 0
     }
     $this->safeDelay = $this->lockExpiry <= 0 ? 60 : $this->lockExpiry;
     // cover worst case
     foreach ($this->srvsByBucket as $bucket) {
         if (count($bucket) > 1) {
             // multiple peers
             // Tracks peers that couldn't be queried recently to avoid lengthy
             // connection timeouts. This is useless if each bucket has one peer.
             try {
                 $this->statusCache = ObjectCache::newAccelerator();
             } catch (Exception $e) {
                 trigger_error(__CLASS__ . " using multiple DB peers without apc, xcache, or wincache.");
             }
             break;
         }
     }
     $this->session = wfRandomString(31);
 }
 /**
  * Compile a LESS file into CSS.
  *
  * Keeps track of all used files and adds them to localFileRefs.
  *
  * @since 1.22
  * @since 1.27 Added $context paramter.
  * @throws Exception If less.php encounters a parse error
  * @param string $fileName File path of LESS source
  * @param ResourceLoaderContext $context Context in which to generate script
  * @return string CSS source
  */
 protected function compileLessFile($fileName, ResourceLoaderContext $context)
 {
     static $cache;
     if (!$cache) {
         $cache = ObjectCache::newAccelerator(CACHE_ANYTHING);
     }
     // Construct a cache key from the LESS file name and a hash digest
     // of the LESS variables used for compilation.
     $vars = $this->getLessVars($context);
     ksort($vars);
     $varsHash = hash('md4', serialize($vars));
     $cacheKey = $cache->makeGlobalKey('LESS', $fileName, $varsHash);
     $cachedCompile = $cache->get($cacheKey);
     // If we got a cached value, we have to validate it by getting a
     // checksum of all the files that were loaded by the parser and
     // ensuring it matches the cached entry's.
     if (isset($cachedCompile['hash'])) {
         $contentHash = FileContentsHasher::getFileContentsHash($cachedCompile['files']);
         if ($contentHash === $cachedCompile['hash']) {
             $this->localFileRefs = array_merge($this->localFileRefs, $cachedCompile['files']);
             return $cachedCompile['css'];
         }
     }
     $compiler = ResourceLoader::getLessCompiler($this->getConfig(), $vars);
     $css = $compiler->parseFile($fileName)->getCss();
     $files = $compiler->AllParsedFiles();
     $this->localFileRefs = array_merge($this->localFileRefs, $files);
     $cache->set($cacheKey, array('css' => $css, 'files' => $files, 'hash' => FileContentsHasher::getFileContentsHash($files)), 60 * 60 * 24);
     // 86400 seconds, or 24 hours.
     return $css;
 }
 public function __construct($parent)
 {
     $this->parent = $parent;
     $this->srvCache = ObjectCache::newAccelerator('hash');
     $this->mainCache = ObjectCache::getLocalClusterInstance();
 }
Beispiel #8
0
 /**
  * @see FileBackendStore::__construct()
  * Additional $config params include:
  *   - swiftAuthUrl       : Swift authentication server URL
  *   - swiftUser          : Swift user used by MediaWiki (account:username)
  *   - swiftKey           : Swift authentication key for the above user
  *   - swiftAuthTTL       : Swift authentication TTL (seconds)
  *   - swiftTempUrlKey    : Swift "X-Account-Meta-Temp-URL-Key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *   - swiftAnonUser      : Swift user used for end-user requests (account:username).
  *                          If set, then views of public containers are assumed to go
  *                          through this user. If not set, then public containers are
  *                          accessible to unauthenticated requests via ".r:*" in the ACL.
  *   - swiftUseCDN        : Whether a Cloud Files Content Delivery Network is set up
  *   - swiftCDNExpiry     : How long (in seconds) to store content in the CDN.
  *                          If files may likely change, this should probably not exceed
  *                          a few days. For example, deletions may take this long to apply.
  *                          If object purging is enabled, however, this is not an issue.
  *   - swiftCDNPurgable   : Whether object purge requests are allowed by the CDN.
  *   - shardViaHashLevels : Map of container names to sharding config with:
  *                             - base   : base of hash characters, 16 or 36
  *                             - levels : the number of hash levels (and digits)
  *                             - repeat : hash subdirectories are prefixed with all the
  *                                        parent hash directory names (e.g. "a/ab/abc")
  *   - cacheAuthInfo      : Whether to cache authentication tokens in APC, XCache, ect.
  *                          If those are not available, then the main cache will be used.
  *                          This is probably insecure in shared hosting environments.
  *   - rgwS3AccessKey     : Ragos Gateway S3 "access key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *                          This is used for generating expiring pre-authenticated URLs.
  *                          Only use this when using rgw and to work around
  *                          http://tracker.newdream.net/issues/3454.
  *   - rgwS3SecretKey     : Ragos Gateway S3 "secret key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *                          This is used for generating expiring pre-authenticated URLs.
  *                          Only use this when using rgw and to work around
  *                          http://tracker.newdream.net/issues/3454.
  */
 public function __construct(array $config)
 {
     parent::__construct($config);
     if (!class_exists('CF_Constants')) {
         throw new MWException('SwiftCloudFiles extension not installed.');
     }
     // Required settings
     $this->auth = new CF_Authentication($config['swiftUser'], $config['swiftKey'], null, $config['swiftAuthUrl']);
     // Optional settings
     $this->authTTL = isset($config['swiftAuthTTL']) ? $config['swiftAuthTTL'] : 5 * 60;
     // some sane number
     $this->swiftAnonUser = isset($config['swiftAnonUser']) ? $config['swiftAnonUser'] : '';
     $this->swiftTempUrlKey = isset($config['swiftTempUrlKey']) ? $config['swiftTempUrlKey'] : '';
     $this->shardViaHashLevels = isset($config['shardViaHashLevels']) ? $config['shardViaHashLevels'] : '';
     $this->swiftUseCDN = isset($config['swiftUseCDN']) ? $config['swiftUseCDN'] : false;
     $this->swiftCDNExpiry = isset($config['swiftCDNExpiry']) ? $config['swiftCDNExpiry'] : 12 * 3600;
     // 12 hours is safe (tokens last 24 hours per http://docs.openstack.org)
     $this->swiftCDNPurgable = isset($config['swiftCDNPurgable']) ? $config['swiftCDNPurgable'] : true;
     $this->rgwS3AccessKey = isset($config['rgwS3AccessKey']) ? $config['rgwS3AccessKey'] : '';
     $this->rgwS3SecretKey = isset($config['rgwS3SecretKey']) ? $config['rgwS3SecretKey'] : '';
     // Cache container information to mask latency
     $this->memCache = wfGetMainCache();
     // Process cache for container info
     $this->connContainerCache = new ProcessCacheLRU(300);
     // Cache auth token information to avoid RTTs
     if (!empty($config['cacheAuthInfo'])) {
         if (PHP_SAPI === 'cli') {
             $this->srvCache = wfGetMainCache();
             // preferrably memcached
         } else {
             try {
                 // look for APC, XCache, WinCache, ect...
                 $this->srvCache = ObjectCache::newAccelerator(array());
             } catch (Exception $e) {
             }
         }
     }
     $this->srvCache = $this->srvCache ? $this->srvCache : new EmptyBagOStuff();
 }
/**
 * Determine if an image exists on the 'bad image list'.
 *
 * The format of MediaWiki:Bad_image_list is as follows:
 *    * Only list items (lines starting with "*") are considered
 *    * The first link on a line must be a link to a bad image
 *    * Any subsequent links on the same line are considered to be exceptions,
 *      i.e. articles where the image may occur inline.
 *
 * @param string $name The image name to check
 * @param Title|bool $contextTitle The page on which the image occurs, if known
 * @param string $blacklist Wikitext of a file blacklist
 * @return bool
 */
function wfIsBadImage($name, $contextTitle = false, $blacklist = null)
{
    # Handle redirects; callers almost always hit wfFindFile() anyway,
    # so just use that method because it has a fast process cache.
    $file = wfFindFile($name);
    // get the final name
    $name = $file ? $file->getTitle()->getDBkey() : $name;
    # Run the extension hook
    $bad = false;
    if (!Hooks::run('BadImage', array($name, &$bad))) {
        return $bad;
    }
    $cache = ObjectCache::newAccelerator('hash');
    $key = wfMemcKey('bad-image-list', $blacklist === null ? 'default' : md5($blacklist));
    $badImages = $cache->get($key);
    if ($badImages === false) {
        // cache miss
        if ($blacklist === null) {
            $blacklist = wfMessage('bad_image_list')->inContentLanguage()->plain();
            // site list
        }
        # Build the list now
        $badImages = array();
        $lines = explode("\n", $blacklist);
        foreach ($lines as $line) {
            # List items only
            if (substr($line, 0, 1) !== '*') {
                continue;
            }
            # Find all links
            $m = array();
            if (!preg_match_all('/\\[\\[:?(.*?)\\]\\]/', $line, $m)) {
                continue;
            }
            $exceptions = array();
            $imageDBkey = false;
            foreach ($m[1] as $i => $titleText) {
                $title = Title::newFromText($titleText);
                if (!is_null($title)) {
                    if ($i == 0) {
                        $imageDBkey = $title->getDBkey();
                    } else {
                        $exceptions[$title->getPrefixedDBkey()] = true;
                    }
                }
            }
            if ($imageDBkey !== false) {
                $badImages[$imageDBkey] = $exceptions;
            }
        }
        $cache->set($key, $badImages, 60);
    }
    $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
    $bad = isset($badImages[$name]) && !isset($badImages[$name][$contextKey]);
    return $bad;
}
Beispiel #10
0
 /**
  * Get the hostname and lag time of the most-lagged slave.
  * This is useful for maintenance scripts that need to throttle their updates.
  * May attempt to open connections to slaves on the default DB. If there is
  * no lag, the maximum lag will be reported as -1.
  *
  * @param bool|string $wiki Wiki ID, or false for the default database
  * @return array ( host, max lag, index of max lagged host )
  */
 function getMaxLag($wiki = false)
 {
     $maxLag = -1;
     $host = '';
     $maxIndex = 0;
     if ($this->getServerCount() <= 1) {
         // no replication = no lag
         return array($host, $maxLag, $maxIndex);
     }
     // Try to get the max lag info from the server cache
     $key = 'loadbalancer:maxlag:cluster:' . $this->mServers[0]['host'];
     $cache = ObjectCache::newAccelerator(array(), 'hash');
     $maxLagInfo = $cache->get($key);
     // (host, lag, index)
     // Fallback to connecting to each slave and getting the lag
     if (!$maxLagInfo) {
         foreach ($this->mServers as $i => $conn) {
             if ($i == $this->getWriterIndex()) {
                 continue;
                 // nothing to check
             }
             $conn = false;
             if ($wiki === false) {
                 $conn = $this->getAnyOpenConnection($i);
             }
             if (!$conn) {
                 $conn = $this->openConnection($i, $wiki);
             }
             if (!$conn) {
                 continue;
             }
             $lag = $conn->getLag();
             if ($lag > $maxLag) {
                 $maxLag = $lag;
                 $host = $this->mServers[$i]['host'];
                 $maxIndex = $i;
             }
         }
         $maxLagInfo = array($host, $maxLag, $maxIndex);
         $cache->set($key, $maxLagInfo, 5);
     }
     return $maxLagInfo;
 }
Beispiel #11
0
 /**
  * Return a singleton instance, based on the global configs.
  * @return HKDF
  */
 protected static function singleton()
 {
     global $wgHKDFAlgorithm, $wgHKDFSecret, $wgSecretKey;
     $secret = $wgHKDFSecret ?: $wgSecretKey;
     if (!$secret) {
         throw new MWException("Cannot use MWCryptHKDF without a secret.");
     }
     // In HKDF, the context can be known to the attacker, but this will
     // keep simultaneous runs from producing the same output.
     $context = array();
     $context[] = microtime();
     $context[] = getmypid();
     $context[] = gethostname();
     // Setup salt cache. Use APC, or fallback to the main cache if it isn't setup
     try {
         $cache = ObjectCache::newAccelerator(array());
     } catch (Exception $e) {
         $cache = wfGetMainCache();
     }
     if (is_null(self::$singleton)) {
         self::$singleton = new self($secret, $wgHKDFAlgorithm, $cache, $context);
     }
     return self::$singleton;
 }
Beispiel #12
0
 /**
  * Load a library from the given file and execute it in the base environment.
  * @param string File name/path to load
  * @return mixed the export list, or null if there isn't one.
  */
 protected function loadLibraryFromFile($fileName)
 {
     static $cache = null;
     if (!$cache) {
         $cache = ObjectCache::newAccelerator(array(), 'hash');
     }
     $mtime = filemtime($fileName);
     if ($mtime === false) {
         throw new MWException('Lua file does not exist: ' . $fileName);
     }
     $cacheKey = wfGlobalCacheKey(__CLASS__, $fileName);
     $fileData = $cache->get($cacheKey);
     $code = false;
     if ($fileData) {
         list($code, $cachedMtime) = $fileData;
         if ($cachedMtime < $mtime) {
             $code = false;
         }
     }
     if (!$code) {
         $code = file_get_contents($fileName);
         if ($code === false) {
             throw new MWException('Lua file does not exist: ' . $fileName);
         }
         $cache->set($cacheKey, array($code, $mtime), 60 * 5);
     }
     # Prepending an "@" to the chunk name makes Lua think it is a filename
     $module = $this->getInterpreter()->loadString($code, '@' . basename($fileName));
     $ret = $this->getInterpreter()->callFunction($module);
     return isset($ret[0]) ? $ret[0] : null;
 }
 public function __construct($parent)
 {
     $this->parent = $parent;
     $this->srvCache = ObjectCache::newAccelerator('hash');
     $this->mainCache = wfGetMainCache();
 }
Beispiel #14
0
 /**
  * Record stats on slow function calls.
  *
  * @param string $moduleName
  * @param string $functionName
  * @param int $timing Function execution time in milliseconds.
  */
 public static function reportTiming($moduleName, $functionName, $timing)
 {
     global $wgScribuntoGatherFunctionStats, $wgScribuntoSlowFunctionThreshold;
     if (!$wgScribuntoGatherFunctionStats) {
         return;
     }
     $threshold = $wgScribuntoSlowFunctionThreshold;
     if (!(is_float($threshold) && $threshold > 0 && $threshold < 1)) {
         return;
     }
     static $cache;
     if (!$cache) {
         $cache = ObjectCache::newAccelerator(CACHE_NONE);
     }
     // To control the sampling rate, we keep a compact histogram of
     // observations in APC, and extract the Nth percentile (specified
     // via $wgScribuntoSlowFunctionThreshold; defaults to 0.90).
     // We need APC and \RunningStat\PSquare to do that.
     if (!class_exists('\\RunningStat\\PSquare') || $cache instanceof EmptyBagOStuff) {
         return;
     }
     $key = $cache->makeGlobalKey(__METHOD__, $threshold);
     // This is a classic "read-update-write" critical section with no
     // mutual exclusion, but the only consequence is that some samples
     // will be dropped. We only need enough samples to estimate the
     // the shape of the data, so that's fine.
     $ps = $cache->get($key) ?: new \RunningStat\PSquare($threshold);
     $ps->addObservation($timing);
     $cache->set($key, $ps, 60);
     if ($ps->getCount() < 1000 || $timing < $ps->getValue()) {
         return;
     }
     static $stats;
     if (!$stats) {
         $stats = RequestContext::getMain()->getStats();
     }
     $metricKey = sprintf('scribunto.traces.%s__%s__%s', wfWikiId(), $moduleName, $functionName);
     $stats->timing($metricKey, $timing);
 }
 /**
  * Constructor.
  */
 public function __construct()
 {
     $this->cache = ObjectCache::newAccelerator('hash');
 }
 /**
  * @return float[]
  */
 public static function getDefaultBoostTemplates()
 {
     if (self::$defaultBoostTemplates === null) {
         $cache = \ObjectCache::newAccelerator(CACHE_NONE);
         self::$defaultBoostTemplates = $cache->getWithSetCallback($cache->makeKey('cirrussearch-boost-templates'), 600, function () {
             $source = wfMessage('cirrussearch-boost-templates')->inContentLanguage();
             if (!$source->isDisabled()) {
                 $lines = Util::parseSettingsInMessage($source->plain());
                 return Util::parseBoostTemplates(implode(' ', $lines));
                 // Now parse the templates
             }
             return array();
         });
     }
     return self::$defaultBoostTemplates;
 }
 /**
  * @see FileBackendStore::__construct()
  * Additional $config params include:
  *   - swiftAuthUrl       : Swift authentication server URL
  *   - swiftUser          : Swift user used by MediaWiki (account:username)
  *   - swiftKey           : Swift authentication key for the above user
  *   - swiftAuthTTL       : Swift authentication TTL (seconds)
  *   - swiftTempUrlKey    : Swift "X-Account-Meta-Temp-URL-Key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *   - shardViaHashLevels : Map of container names to sharding config with:
  *                             - base   : base of hash characters, 16 or 36
  *                             - levels : the number of hash levels (and digits)
  *                             - repeat : hash subdirectories are prefixed with all the
  *                                        parent hash directory names (e.g. "a/ab/abc")
  *   - cacheAuthInfo      : Whether to cache authentication tokens in APC, XCache, ect.
  *                          If those are not available, then the main cache will be used.
  *                          This is probably insecure in shared hosting environments.
  *   - rgwS3AccessKey     : Rados Gateway S3 "access key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *                          This is used for generating expiring pre-authenticated URLs.
  *                          Only use this when using rgw and to work around
  *                          http://tracker.newdream.net/issues/3454.
  *   - rgwS3SecretKey     : Rados Gateway S3 "secret key" value on the account.
  *                          Do not set this until it has been set in the backend.
  *                          This is used for generating expiring pre-authenticated URLs.
  *                          Only use this when using rgw and to work around
  *                          http://tracker.newdream.net/issues/3454.
  */
 public function __construct(array $config)
 {
     parent::__construct($config);
     // Required settings
     $this->swiftAuthUrl = $config['swiftAuthUrl'];
     $this->swiftUser = $config['swiftUser'];
     $this->swiftKey = $config['swiftKey'];
     // Optional settings
     $this->authTTL = isset($config['swiftAuthTTL']) ? $config['swiftAuthTTL'] : 15 * 60;
     // some sane number
     $this->swiftTempUrlKey = isset($config['swiftTempUrlKey']) ? $config['swiftTempUrlKey'] : '';
     $this->shardViaHashLevels = isset($config['shardViaHashLevels']) ? $config['shardViaHashLevels'] : '';
     $this->rgwS3AccessKey = isset($config['rgwS3AccessKey']) ? $config['rgwS3AccessKey'] : '';
     $this->rgwS3SecretKey = isset($config['rgwS3SecretKey']) ? $config['rgwS3SecretKey'] : '';
     // HTTP helper client
     $this->http = new MultiHttpClient(array());
     // Cache container information to mask latency
     if (isset($config['wanCache']) && $config['wanCache'] instanceof WANObjectCache) {
         $this->memCache = $config['wanCache'];
     }
     // Process cache for container info
     $this->containerStatCache = new ProcessCacheLRU(300);
     // Cache auth token information to avoid RTTs
     if (!empty($config['cacheAuthInfo'])) {
         if (PHP_SAPI === 'cli') {
             $this->srvCache = wfGetMainCache();
             // preferrably memcached
         } else {
             try {
                 // look for APC, XCache, WinCache, ect...
                 $this->srvCache = ObjectCache::newAccelerator(array());
             } catch (Exception $e) {
             }
         }
     }
     $this->srvCache = $this->srvCache ?: new EmptyBagOStuff();
 }
 /**
  * Extract more like this settings from the i18n message cirrussearch-morelikethis-settings
  */
 private static function overrideMoreLikeThisOptionsFromMessage()
 {
     global $wgCirrusSearchMoreLikeThisConfig, $wgCirrusSearchMoreLikeThisUseFields, $wgCirrusSearchMoreLikeThisAllowedFields, $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit, $wgCirrusSearchMoreLikeThisFields;
     $cache = \ObjectCache::newAccelerator(CACHE_NONE);
     $lines = $cache->getWithSetCallback($cache->makeKey('cirrussearch-morelikethis-settings'), 600, function () {
         $source = wfMessage('cirrussearch-morelikethis-settings')->inContentLanguage();
         if ($source && $source->isDisabled()) {
             return array();
         }
         return Util::parseSettingsInMessage($source->plain());
     });
     foreach ($lines as $line) {
         list($k, $v) = explode(':', $line, 2);
         switch ($k) {
             case 'min_doc_freq':
             case 'max_doc_freq':
             case 'max_query_terms':
             case 'min_term_freq':
             case 'min_word_len':
             case 'max_word_len':
                 if (is_numeric($v) && $v >= 0) {
                     $wgCirrusSearchMoreLikeThisConfig[$k] = intval($v);
                 } else {
                     if ($v === 'null') {
                         unset($wgCirrusSearchMoreLikeThisConfig[$k]);
                     }
                 }
                 break;
             case 'percent_terms_to_match':
                 if (is_numeric($v) && $v > 0 && $v <= 1) {
                     $wgCirrusSearchMoreLikeThisConfig[$k] = $v;
                 } else {
                     if ($v === 'null') {
                         unset($wgCirrusSearchMoreLikeThisConfig[$k]);
                     }
                 }
                 break;
             case 'fields':
                 $wgCirrusSearchMoreLikeThisFields = array_intersect(array_map('trim', explode(',', $v)), $wgCirrusSearchMoreLikeThisAllowedFields);
                 break;
             case 'use_fields':
                 if ($v === 'true') {
                     $wgCirrusSearchMoreLikeThisUseFields = true;
                 } else {
                     if ($v === 'false') {
                         $wgCirrusSearchMoreLikeThisUseFields = false;
                     }
                 }
                 break;
         }
         if ($wgCirrusSearchMoreLikeThisConfig['max_query_terms'] > $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit) {
             $wgCirrusSearchMoreLikeThisConfig['max_query_terms'] = $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit;
         }
     }
 }
 /**
  * Get the namespace display name in the preferred variant.
  *
  * @param int $index Namespace id
  * @param string|null $variant Variant code or null for preferred variant
  * @return string Namespace name for display
  */
 public function convertNamespace($index, $variant = null)
 {
     if ($index === NS_MAIN) {
         return '';
     }
     if ($variant === null) {
         $variant = $this->getPreferredVariant();
     }
     $cache = ObjectCache::newAccelerator(CACHE_NONE);
     $key = wfMemcKey('languageconverter', 'namespace-text', $index, $variant);
     $nsVariantText = $cache->get($key);
     if ($nsVariantText !== false) {
         return $nsVariantText;
     }
     // First check if a message gives a converted name in the target variant.
     $nsConvMsg = wfMessage('conversion-ns' . $index)->inLanguage($variant);
     if ($nsConvMsg->exists()) {
         $nsVariantText = $nsConvMsg->plain();
     }
     // Then check if a message gives a converted name in content language
     // which needs extra translation to the target variant.
     if ($nsVariantText === false) {
         $nsConvMsg = wfMessage('conversion-ns' . $index)->inContentLanguage();
         if ($nsConvMsg->exists()) {
             $nsVariantText = $this->translate($nsConvMsg->plain(), $variant);
         }
     }
     if ($nsVariantText === false) {
         // No message exists, retrieve it from the target variant's namespace names.
         $langObj = $this->mLangObj->factory($variant);
         $nsVariantText = $langObj->getFormattedNsText($index);
     }
     $cache->set($key, $nsVariantText, 60);
     return $nsVariantText;
 }
Beispiel #20
0
 /**
  * Constructor.
  *
  * FIXME: It is possible to construct a Database object with no associated
  * connection object, by specifying no parameters to __construct(). This
  * feature is deprecated and should be removed.
  *
  * DatabaseBase subclasses should not be constructed directly in external
  * code. DatabaseBase::factory() should be used instead.
  *
  * @param array $params Parameters passed from DatabaseBase::factory()
  */
 function __construct(array $params)
 {
     global $wgDBprefix, $wgDBmwschema, $wgCommandLineMode;
     $this->mTrxAtomicLevels = new SplStack();
     $this->srvCache = ObjectCache::newAccelerator('hash');
     $server = $params['host'];
     $user = $params['user'];
     $password = $params['password'];
     $dbName = $params['dbname'];
     $flags = $params['flags'];
     $tablePrefix = $params['tablePrefix'];
     $schema = $params['schema'];
     $foreign = $params['foreign'];
     $this->mFlags = $flags;
     if ($this->mFlags & DBO_DEFAULT) {
         if ($wgCommandLineMode) {
             $this->mFlags &= ~DBO_TRX;
         } else {
             $this->mFlags |= DBO_TRX;
         }
     }
     $this->mSessionVars = $params['variables'];
     /** Get the default table prefix*/
     if ($tablePrefix === 'get from global') {
         $this->mTablePrefix = $wgDBprefix;
     } else {
         $this->mTablePrefix = $tablePrefix;
     }
     /** Get the database schema*/
     if ($schema === 'get from global') {
         $this->mSchema = $wgDBmwschema;
     } else {
         $this->mSchema = $schema;
     }
     $this->mForeign = $foreign;
     if (isset($params['trxProfiler'])) {
         $this->trxProfiler = $params['trxProfiler'];
         // override
     }
     if ($user) {
         $this->open($server, $user, $password, $dbName);
     }
 }
Beispiel #21
0
 /**
  * Run JavaScript or CSS data through a filter, caching the filtered result for future calls.
  *
  * Available filters are:
  *
  *    - minify-js \see JavaScriptMinifier::minify
  *    - minify-css \see CSSMin::minify
  *
  * If $data is empty, only contains whitespace or the filter was unknown,
  * $data is returned unmodified.
  *
  * @param string $filter Name of filter to run
  * @param string $data Text to filter, such as JavaScript or CSS text
  * @param array $options Keys:
  *  - (bool) cache: Whether to allow caching this data. Default: true.
  * @return string Filtered data, or a comment containing an error message
  */
 public static function filter($filter, $data, array $options = array())
 {
     if (strpos($data, ResourceLoader::FILTER_NOMIN) !== false) {
         return $data;
     }
     if (isset($options['cache']) && $options['cache'] === false) {
         return self::applyFilter($filter, $data);
     }
     $stats = RequestContext::getMain()->getStats();
     $cache = ObjectCache::newAccelerator(CACHE_ANYTHING);
     $key = wfGlobalCacheKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data));
     $result = $cache->get($key);
     if ($result === false) {
         $stats->increment("resourceloader_cache.{$filter}.miss");
         $result = self::applyFilter($filter, $data);
         $cache->set($key, $result, 24 * 3600);
     } else {
         $stats->increment("resourceloader_cache.{$filter}.hit");
     }
     if ($result === null) {
         // Cached failure
         $result = $data;
     }
     return $result;
 }
 /**
  * Compute a non-cryptographic string hash of a file's contents.
  * If the file does not exist or cannot be read, returns an empty string.
  *
  * @since 1.26 Uses MD4 instead of SHA1.
  * @param string $filePath File path
  * @return string Hash
  */
 protected static function safeFileHash($filePath)
 {
     static $cache;
     if (!$cache) {
         $cache = ObjectCache::newAccelerator(CACHE_NONE);
     }
     MediaWiki\suppressWarnings();
     $mtime = filemtime($filePath);
     MediaWiki\restoreWarnings();
     if (!$mtime) {
         return '';
     }
     $cacheKey = wfGlobalCacheKey('resourceloader', __METHOD__, $filePath);
     $cachedHash = $cache->get($cacheKey);
     if (isset($cachedHash['mtime']) && $cachedHash['mtime'] === $mtime) {
         return $cachedHash['hash'];
     }
     MediaWiki\suppressWarnings();
     $contents = file_get_contents($filePath);
     MediaWiki\restoreWarnings();
     if (!$contents) {
         return '';
     }
     $hash = hash('md4', $contents);
     $cache->set($cacheKey, array('mtime' => $mtime, 'hash' => $hash), 60 * 60 * 24);
     return $hash;
 }
 /**
  * @param BagOStuff $memCached A cache instance. If none, fall back to CACHE_NONE.
  * @param bool $useDB
  * @param int $expiry Lifetime for cache. @see $mExpiry.
  */
 function __construct($memCached, $useDB, $expiry)
 {
     global $wgUseLocalMessageCache;
     if (!$memCached) {
         $memCached = wfGetCache(CACHE_NONE);
     }
     $this->mMemc = $memCached;
     $this->mDisable = !$useDB;
     $this->mExpiry = $expiry;
     if ($wgUseLocalMessageCache) {
         $this->localCache = ObjectCache::newAccelerator(CACHE_NONE);
     } else {
         $this->localCache = wfGetCache(CACHE_NONE);
     }
     $this->wanCache = ObjectCache::getMainWANInstance();
 }
 /**
  * Run JavaScript or CSS data through a filter, caching the filtered result for future calls.
  *
  * Available filters are:
  *
  *    - minify-js \see JavaScriptMinifier::minify
  *    - minify-css \see CSSMin::minify
  *
  * If $data is empty, only contains whitespace or the filter was unknown,
  * $data is returned unmodified.
  *
  * @param string $filter Name of filter to run
  * @param string $data Text to filter, such as JavaScript or CSS text
  * @param array $options For back-compat, can also be the boolean value for "cacheReport". Keys:
  *  - (bool) cache: Whether to allow caching this data. Default: true.
  *  - (bool) cacheReport: Whether to include the "cache key" report comment. Default: false.
  * @return string Filtered data, or a comment containing an error message
  */
 public function filter($filter, $data, $options = array())
 {
     // Back-compat
     if (is_bool($options)) {
         $options = array('cacheReport' => $options);
     }
     // Defaults
     $options += array('cache' => true, 'cacheReport' => false);
     $stats = RequestContext::getMain()->getStats();
     // Don't filter empty content
     if (trim($data) === '') {
         return $data;
     }
     if (!in_array($filter, array('minify-js', 'minify-css'))) {
         $this->logger->warning('Invalid filter {filter}', array('filter' => $filter));
         return $data;
     }
     if (!$options['cache']) {
         $result = self::applyFilter($filter, $data, $this->config);
     } else {
         $key = wfGlobalCacheKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data));
         $cache = ObjectCache::newAccelerator(CACHE_ANYTHING);
         $cacheEntry = $cache->get($key);
         if (is_string($cacheEntry)) {
             $stats->increment("resourceloader_cache.{$filter}.hit");
             return $cacheEntry;
         }
         $result = '';
         try {
             $statStart = microtime(true);
             $result = self::applyFilter($filter, $data, $this->config);
             $statTiming = microtime(true) - $statStart;
             $stats->increment("resourceloader_cache.{$filter}.miss");
             $stats->timing("resourceloader_cache.{$filter}.timing", 1000 * $statTiming);
             if ($options['cacheReport']) {
                 $result .= "\n/* cache key: {$key} */";
             }
             // Set a TTL since HHVM's APC doesn't have any limitation or eviction logic.
             $cache->set($key, $result, 24 * 3600);
         } catch (Exception $e) {
             MWExceptionHandler::logException($e);
             $this->logger->warning('Minification failed: {exception}', array('exception' => $e));
             $this->errors[] = self::formatExceptionNoComment($e);
         }
     }
     return $result;
 }