Sindbad~EG File Manager

Current Path : /var/www/web3/modules/core/classes/
Upload File :
Current File : /var/www/web3/modules/core/classes/GalleryDataCache.class

<?php
/*
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2007 Bharat Mediratta
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.
 */

/**
 * Utility class for caching data
 *
 * Very useful in the case where retrieving or building data sets is expensive, and the data
 * doesn't change during the lifetime of the request.  This class serves as a hash table where
 * any data class can store and retrieve cached data.
 *
 * @package GalleryCore
 * @subpackage Classes
 * @author Bharat Mediratta <bharat@menalto.com>
 * @version $Revision: 16011 $
 * @static
 */
class GalleryDataCache {

    /**
     * Get the static cache
     *
     * @return array the cache
     * @staticvar cache the singleton cache
     * @access private
     */
    function &_getCache() {
	static $cache;
	if (!isset($cache)) {
	    $cache['maxKeys'] = 300;
	    $cache['positions'] = array();
	    $cache['latestPosition'] = 0;
	    $cache['keys'] = array();
	    $cache['protected'] = array();
	    $cache['memoryCacheEnabled'] = 1;
	    $cache['fileCacheEnabled'] = 1;
	}
	return $cache;
    }

    /**
     * Is in-memory caching enabled?
     * @return boolean true if it's enabled
     */
    function isMemoryCachingEnabled() {
	$cache =& GalleryDataCache::_getCache();
	return $cache['memoryCacheEnabled'];
    }

    /**
     * Turn in-memory caching on or off
     * @param boolean $bool
     */
    function setMemoryCachingEnabled($bool) {
	$cache =& GalleryDataCache::_getCache();
	$cache['memoryCacheEnabled'] = $bool;
    }

    /**
     * Store data in the cache
     * You must provide a unique key.  Existing keys are overwritten.
     *
     * @param string $key
     * @param mixed $data
     * @param boolean $protected should this key survive a reset call?
     */
    function put($key, $data, $protected=false) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return;
	}

	$cache['keys'][$key] = $data;
	if ($protected) {
	    $cache['protected'][$key] = 1;
	} else {
	    $cache['positions'][$key] = $cache['latestPosition']++;
	}

	if ($cache['latestPosition'] % 150 == 0) {
	    GalleryDataCache::_performMaintenance();
	}
    }

    /**
     * Remove data from the cache
     * @param string $key
     */
    function remove($key) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return;
	}

	unset($cache['positions'][$key]);
	unset($cache['keys'][$key]);
	unset($cache['protected'][$key]);
    }

    /**
     * Remove data from the cache
     * @param string $pattern regexp
     */
    function removeByPattern($pattern) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return;
	}

	foreach (preg_grep("/$pattern/", array_keys($cache['keys'])) as $key) {
	    unset($cache['positions'][$key]);
	    unset($cache['keys'][$key]);
	    unset($cache['protected'][$key]);
	}
    }

    /**
     * Store a reference to the data in the cache
     *
     * You must provide a unique key.  Existing keys are overwritten.
     *
     * @param string $key
     * @param mixed $data
     * @param boolean $protected (optional) should this key survive a reset call?
     */
    function putByReference($key, &$data, $protected=false) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return;
	}

	$cache['keys'][$key] =& $data;
	if ($protected) {
	    $cache['protected'][$key] = 1;
	} else {
	    $cache['positions'][$key] = $cache['latestPosition']++;
	}

	if ($cache['latestPosition'] % 150 == 0) {
	    GalleryDataCache::_performMaintenance();
	}
    }

    /**
     * Perform some pruning of our cache to prevent it from growing too large when we're doing
     * exceptionally long operations like adding many items in one request.
     *
     * @access private
     */
    function _performMaintenance() {
	$cache =& GalleryDataCache::_getCache();
	$numToExpire = sizeof($cache['positions']) - $cache['maxKeys'];
	if ($numToExpire > 0) {
	    asort($cache['positions']);
	    foreach ($cache['positions'] as $key => $position) {
		unset($cache['keys'][$key]);
		unset($cache['positions'][$key]);
		if ($numToExpire-- == 0) {
		    break;
		}
	    }
	}
    }

    /**
     * Retrieve data from the cache
     * @param string $key
     * @return mixed the cached data
     */
    function get($key) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return null;
	}

	if (!isset($cache['protected'][$key])) {
	    $cache['positions'][$key] = $cache['latestPosition']++;
	}
	return $cache['keys'][$key];
    }

    /**
     * Does the cache contain the key specified?
     * @param string $key
     * @return boolean true if the cache contains the key given
     */
    function containsKey($key) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return false;
	}
	return isset($cache['keys'][$key]);
    }

    /**
     * Return all the keys in the cache
     * @return array string keys
     */
    function getAllKeys() {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return array();
	}

	return array_keys($cache['keys']);
    }

    /**
     * Empty the cache of all but protected entries
     * @param boolean $purgeProtected (optional) purge protected also?
     */
    function reset($purgeProtected=false) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['memoryCacheEnabled']) {
	    return;
	}

	if ($purgeProtected) {
	    $cache['positions'] = array();
	    $cache['keys'] = array();
	} else {
	    foreach (array_keys($cache['keys']) as $key) {
		if (!isset($cache['protected'][$key])) {
		    unset($cache['positions'][$key]);
		    unset($cache['keys'][$key]);
		}
	    }
	}
    }

    /**
     * Is caching to disk enabled?
     * @return boolean
     */
    function &isFileCachingEnabled() {
	$cache =& GalleryDataCache::_getCache();
	return $cache['fileCacheEnabled'];
    }

    /**
     * Turn caching to disk on or off
     * @param boolean $bool

     */
    function setFileCachingEnabled($bool) {
	$cache =& GalleryDataCache::_getCache();
	$cache['fileCacheEnabled'] = $bool;
    }

    /**
     * Get the file from disk.  PathInfo is of the form that can be passed to getCachePath
     * @see GalleryDataCache::getCachePath
     * @param array $pathInfo the path info
     * @return mixed object data
     */
    function &getFromDisk($pathInfo) {
	$null = null;
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['fileCacheEnabled']) {
	    return $null;
	}

	global $gallery;
	$platform =& $gallery->getPlatform();
	$cacheFile = GalleryDataCache::getCachePath($pathInfo);
	if ($platform->file_exists($cacheFile) &&
		$buf = $platform->file_get_contents($cacheFile)) {
	    /* Parse the cache file */
	    $marker = strcspn($buf, '|');
	    foreach (explode(',', substr($buf, 0, $marker)) as $classFile) {
		if ($classFile) {
		    GalleryCoreApi::requireOnce($classFile);
		}
	    }
	    $data = unserialize(substr($buf, $marker+1));
	    return $data;
	}

	return $null;
    }

    /**
     * Remove the cache file from disk.  PathInfo is of the form that can be passed to getCachePath
     * @see GalleryDataCache::getCachePath
     * @param array $pathInfo the path info
     */
    function removeFromDisk($pathInfo) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['fileCacheEnabled']) {
	    return null;
	}

	global $gallery;
	$platform =& $gallery->getPlatform();
	if ($pathInfo['type'] == 'entity' ||
		$pathInfo['type'] == 'derivative-meta' ||
		$pathInfo['type'] == 'module-data' ||
		isset($pathInfo['id'])) {
	    $cacheFile = GalleryDataCache::getCachePath($pathInfo);
	    if ($platform->file_exists($cacheFile)) {
		if ($platform->is_dir($cacheFile)) {
		    $platform->recursiveRmDir($cacheFile);
		} else {
		    $platform->unlink($cacheFile);
		}
	    }
	} else {
	    if ($pathInfo['type'] == 'module' || $pathInfo['type'] == 'theme') {
		list ($ret, $pluginStatus) = GalleryCoreApi::fetchPluginStatus($pathInfo['type']);
		if ($ret) {
		    return $ret;
		}

		foreach (array_keys($pluginStatus) as $pluginId) {
		    GalleryDataCache::removeFromDisk(array('type' => $pathInfo['type'],
							   'id' => $pluginId,
							   'itemId' => $pathInfo['itemId']));
		}
	    }
	}
    }

    /**
     * Put the specified data into a cache file from disk.  PathInfo is of the form that can
     * be passed to getCachePath.
     *
     * @param array $pathInfo the path info
     * @param mixed $data the object data
     * @param array $requiredClasses classes that must be loaded in order to retrieve this data
     * @see GalleryDataCache::getCachePath
     */
    function putToDisk($pathInfo, &$data, $requiredClasses=array()) {
	$cache =& GalleryDataCache::_getCache();
	if (!$cache['fileCacheEnabled']) {
	    return;
	}

	global $gallery;
	$cacheFile = GalleryDataCache::getCachePath($pathInfo);
	$platform =& $gallery->getPlatform();
	GalleryUtilities::guaranteeDirExists(dirname($cacheFile));

	/* This will either succeed, or leave no trace of its attempt. */
	$platform->atomicWrite(
	    $cacheFile, implode(',', $requiredClasses) . "|" . serialize($data));
    }

    /**
     * For a given id, return a tuple with the breakdown of the id.  The caching mechanism uses
     * this to determine where in the cache tree to place the file.  The breakdown happens
     * according to the digits of the id.  The first element returned is the hundreds digit,
     * the second element is the tens digit.
     *
     *  0..9     =>  0, 0
     *  10..19   =>  0, 1
     *  20..29   =>  0, 2
     *   ...
     *  100..109 =>  1, 0
     *  110..119 =>  1, 1
     *
     * @param int $id
     * @return array the tuple
     */
    function getCacheTuple($id) {
	$id = "$id";
	if ($id > 100) {
	    return array($id[0], $id[1]);
	} else if ($id > 10) {
	    return array('0', $id[0]);
	} else {
	    return array('0', '0');
	}
    }

    /**
     * Given a path info descriptor, return the path to the appropriate cache file.
     *
     * Path info contains the following variables:
     *  type:    entity, derivative, derivative-meta, module, theme
     *  itemId:  the item id
     *  id:      (module, theme only) a refinement of the type
     *
     * @return string the path
     */
    function getCachePath($pathInfo) {
	global $gallery;

	$base = $gallery->getConfig('data.gallery.cache');
	$cacheFile = null;
	switch ($pathInfo['type']) {
	case 'entity':
	    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
	    $cacheFile = sprintf('%sentity/%s/%s/%d.inc',
				 $base, $first, $second, $pathInfo['itemId']);
	    break;

	case 'derivative':
	    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
	    $cacheFile = sprintf('%sderivative/%s/%s/%d.dat',
				 $base, $first, $second, $pathInfo['itemId']);
	    break;

	case 'derivative-relative':
	    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
	    $cacheFile = sprintf('derivative/%s/%s/%d.dat',
				 $first, $second, $pathInfo['itemId']);
	    break;

	case 'derivative-meta':
	    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
	    $cacheFile = sprintf('%sderivative/%s/%s/%d-meta.inc',
				 $base, $first, $second, $pathInfo['itemId']);
	    break;

	case 'fast-download':
	    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
	    $cacheFile = sprintf('%sentity/%s/%s/%d-fast.inc',
				 $base, $first, $second, $pathInfo['itemId']);
	    break;

	case 'module':
	case 'theme':
	    if (isset($pathInfo['id'])) {
		if (strstr($pathInfo['id'], '..') !== false) {
		    $pathInfo['id'] = '0';
		}
		if (isset($pathInfo['itemId'])) {
		    if (strstr($pathInfo['itemId'], '..') !== false) {
			$pathInfo['itemId'] = '0';
		    }
		    list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);
		    $cacheFile = sprintf('%s%s/%s/%s/%s/%s.inc',
					 $base, $pathInfo['type'], $pathInfo['id'],
					 $first, $second, $pathInfo['itemId']);
		} else {
		    $cacheFile = sprintf('%s%s/%s', $base, $pathInfo['type'], $pathInfo['id']);
		}
	    }
	    break;

	case 'module-data':
	    if (strstr($pathInfo['module'], '..') !== false) {
		$pathInfo['module'] = '0';
	    }
	    if (isset($pathInfo['itemId'])) {
		list ($first, $second) = GalleryDataCache::getCacheTuple($pathInfo['itemId']);

		/* $itemId is overloaded here; sanitize it so that it only accepts [0-9A-Za-z_]+ */
		$itemId = preg_replace('/[^0-9A-Za-z_]/', '_', $pathInfo['itemId']);
		$cacheFile = sprintf('%s%s/%s/%s/%s/%s.dat',
				     $base, 'module', $pathInfo['module'],
				     $first, $second, $itemId);
	    } else {
		$cacheFile = sprintf('%s%s/%s/', $base, 'module', $pathInfo['module']);
	    }
	    break;
	}

	return $cacheFile;
    }

    /**
     * Store the given permission => ids mapping in the session cache
     * @param mixed $ids item ids (can be an array of ids or a single id)
     * @param string $permission
     */
    function cachePermissions($ids, $permission) {
	global $gallery;
	$session =& $gallery->getSession();
	if (!isset($session)) {
	    /* No session means we've got no cache */
	    return;
	}

	if (!is_array($ids)) {
	    $ids = array($ids);
	}

	$permissions = $session->get('permissionCache');

	/*
	 * We want to put all the permissions that we cache in this request into one entry in
	 * the session.  However we're going to get several separate requests.  So start by
	 * pruning down the total number of cached permission sets, then create a new set
	 * and add all cached values to that.
	 */
	static $initialized;
	if (!isset($initialized)) {
	    if (!isset($permissions)) {
		$permissions = array();
	    }

	    array_unshift($permissions, array());
	    /* Trim down the cache */
	    $max = 6;
	    if (sizeof($permissions) > $max) {
		array_splice($permissions, -1, sizeof($permissions) - $max);
	    }

	    $initialized = 1;
	}

	$cacheKey = 'GalleryDataCache::cachePermissions::newEntries';
	if (GalleryDataCache::containsKey($cacheKey)) {
	    $newEntries = GalleryDataCache::get($cacheKey);
	} else {
	    $newEntries = 0;
	}

	/* Make sure the session permission cache is not too large */
	$maxEntries = 40;
	/* Add our new data to the head of the list */
	while (($id = array_shift($ids)) && $maxEntries > $newEntries++) {
	    $permissions[0][$permission][$id] = 1;
	}

	GalleryDataCache::put($cacheKey, $newEntries);
	$session->put('permissionCache', $permissions);
    }

    /**
     * Look up the given permission in the cache.  Return true if the permission
     * exists in the cache, false if it doesn't.  A return of false doesn't mean
     * that the user doesn't have the permission -- just that it's not in the
     * cache.
     *
     * @param int $id the item id
     * @param string $permission
     * @return boolean
     */
    function hasPermission($id, $permission) {
	global $gallery;
	$session =& $gallery->getSession();
	if (!isset($session)) {
	    return;
	}

	$permissions = $session->get('permissionCache');
	/*
	 * Since we add all new data to the head of the list, the odds are good
	 * that we should find our answer in the first iteration of this loop.
	 */
	for ($i = 0; $i < sizeof($permissions); $i++) {
	    if (isset($permissions[$i][$permission][$id])) {
		return true;
	    }
	}

	return false;
    }

    /**
     * Clear permission cache for active user.
     */
    function clearPermissionCache() {
	global $gallery;
	$session =& $gallery->getSession();
	if (isset($session)) {
	    $session->remove('permissionCache');
	}
    }

    /**
     * Get page data from the cache.
     *
     * @param string $type the page type
     * @param mixed $keyData data to use to generate the unique key for this cache entry
     * @return array object GalleryStatus a status code
     *               string the page data
     */
    function getPageData($type, $keyData) {
	global $gallery;

	list ($ret, $acceleration) =
	    GalleryCoreApi::getPluginParameter('module', 'core', 'acceleration');
	if ($ret) {
	    return array($ret, null);
	}
	$acceleration = unserialize($acceleration);

	list ($ret, $isAnonymous) = GalleryCoreApi::isAnonymousUser();
	if ($ret) {
	    return array($ret, null);
	}

	$expiration = $acceleration[$isAnonymous ? 'guest' : 'user']['expiration'];
	$phpVm = $gallery->getPhpVm();
	$cutoff = $phpVm->time() - $expiration;

	list ($ret, $aclIds) =
	    GalleryCoreApi::fetchAccessListIds('core.view', $gallery->getActiveUserId());
	if ($ret) {
	    return array($ret, null);
	}

	list ($ret, $extraKey) = GalleryDataCache::_getExtraPageCacheKey();
	if ($ret) {
	    return array($ret, null);
	}

	$key = md5(serialize($keyData) . '|' . $extraKey . '|' . implode(",", $aclIds));
	$userId = $gallery->getActiveUserId();
	/*
	 * Note: there is no complete index for this WHERE clause because the MySQL query optimizer
	 * would still use the PK for this query. This should not lead to a performance decrease as
	 * PK is a unique index thus returning only 0/1 rows that need to be compared with isEmpty
	 * and timestamp.
	 */
	list ($ret, $results) = GalleryCoreApi::getMapEntry('GalleryCacheMap',
	    array('value'),
	    array('key' => $key, 'type' => $type, 'userId' => $userId,
		  'timestamp' => new GallerySqlFragment('>?', $cutoff), 'isEmpty' => 0));
	if ($ret) {
	    return array($ret, null);
	}

	if ($results->resultCount() > 0) {
	    $result = $results->nextResult();
	    $value = $result[0];
	    if (function_exists('gzinflate')) {
		$storage =& $gallery->getStorage();
		$value = $storage->decodeBlob($value);
		$value = gzinflate($value);
	    }
	} else {
	    $value = null;
	}

	return array(null, $value);
    }

    /**
     * Store page data from the cache.
     *
     * @param string $type the page type
     * @param int $itemId the itemId of the item this page is rendering
     * @param mixed $keyData data to use to generate the unique key for this cache entry
     * @param string $value the page data
     * @return object GalleryStatus a status code
     */
    function putPageData($type, $itemId, $keyData, $value) {
	global $gallery;

	$userId = $gallery->getActiveUserId();
	list ($ret, $aclIds) = GalleryCoreApi::fetchAccessListIds('core.view', $userId);
	if ($ret) {
	    return $ret;
	}

	list ($ret, $extraKey) = GalleryDataCache::_getExtraPageCacheKey();
	if ($ret) {
	    return $ret;
	}

	$key = md5(serialize($keyData) . '|' . $extraKey . '|' . implode(",", $aclIds));

	if (function_exists('gzdeflate')) {
	    $value = gzdeflate($value);
	    $storage =& $gallery->getStorage();
	    $value = $storage->encodeBlob($value);
	}

	$phpVm = $gallery->getPhpVm();
	$now = $phpVm->time();
	$ret = GalleryCoreApi::updateMapEntry(
	    'GalleryCacheMap',
	    array('key' => $key, 'userId' => $userId, 'itemId' => $itemId, 'type' => $type),
	    array('value' => $value, 'timestamp' => $now, 'isEmpty' => 0));

	$storage =& $gallery->getStorage();
	list ($ret, $affectedRows) = $storage->getAffectedRows();
	if ($ret) {
	    return $ret;
	}

	if (!$affectedRows) {
	    $ret = GalleryCoreApi::addMapEntry(
		'GalleryCacheMap',
		array('key' => $key, 'value' => $value, 'userId' => $userId,
		      'itemId' => $itemId, 'type' => $type, 'timestamp' => $now, 'isEmpty' => 0));
	    if ($ret) {
		return $ret;
	    }
	}

	/* Clear expired data only 5% of the time. */
	$dieRoll = $phpVm->rand(1,100);
	if($dieRoll <= 5){
	    $ret = GalleryDataCache::_cleanPageDataCache();
	    if ($ret) {
		return $ret;
	    }
	}

	return null;
    }

    /**
     * Remove all cached page data for the given item ids
     *
     * @param mixed $itemIds one item id, or an array of item ids
     * @return object GalleryStatus a status code
     */
    function removePageData($itemIds) {
	$ret = GalleryCoreApi::removeMapEntry('GalleryCacheMap', array('itemId' => $itemIds));
	if ($ret) {
	    return $ret;
	}
	return null;
    }

    /**
     * Should we use the cache for this page or not?  Right now we cache a page if it's a GET
     * request, the browser hasn't specified that it wants uncached data, and the caching policy
     * for the given user class is appropriate.
     *
     * @param string $action
     * @param string $type the page type
     * @return object GalleryStatus a status code
     */
    function shouldCache($action, $type) {
	global $gallery;

	if (GalleryUtilities::getServerVar('REQUEST_METHOD') != 'GET') {
	    return array(null, false);
	}

	$phpVm = $gallery->getPhpVm();
	if ($action == 'read') {
	    $noCache = (GalleryUtilities::getServerVar('HTTP_PRAGMA') == 'no-cache' ||
			GalleryUtilities::getServerVar('HTTP_CACHE_CONTROL') == 'no-cache');
	    if ($noCache) {
		return array(null, false);
	    }
	}

	/*
	 * Don't cache guest preview pages since we want a realtime preview
	 * and they are infrequently visited
	 */
	$session =& $gallery->getSession();
	if ($session->get('theme.guestPreviewMode')) {
	    return array(null, false);
	}

	list ($ret, $acceleration) =
	    GalleryCoreApi::getPluginParameter('module', 'core', 'acceleration');
	if ($ret) {
	    return array($ret, null);
	}
	$acceleration = unserialize($acceleration);
	list ($ret, $isAnonymous) = GalleryCoreApi::isAnonymousUser();
	if ($ret) {
	    return array($ret, null);
	}

	return array(null, $acceleration[$isAnonymous ? 'guest' : 'user']['type'] == $type);
    }

    /**
     * Returns session related page cache key, eg. to make the page cache language sensitive
     * @todo The extra key for exif module is a quick fix, not a permanent fix; it should be
     *       cached on the block level not on page level.
     *
     * @return array object GalleryStatus a status code
     *               string extra cache key
     */
    function _getExtraPageCacheKey() {
	global $gallery;
	$session =& $gallery->getSession();

	/* Add session specific flags & values to the cache key */
	list ($ret, $languageCode) = $gallery->getActiveLanguageCode();
	if ($ret) {
	    return array($ret, null);
	}
	$isEmbedded = (int)$gallery->isEmbedded();
	$extraKey = (int)($session->isUsingCookies()) . '-' . $languageCode . '-' . $isEmbedded;

	$mode = $session->get('exif.module.LoadExifInfo.mode');
	if (!empty($mode) && $mode != 'summary') {
	    $extraKey .= '-exif' . $mode;
	}

	return array(null, $extraKey);
    }

    /**
     * Delete value of obsolete cache data.
     *
     * @return object GalleryStatus a status code
     */
    function _cleanPageDataCache() {
	global $gallery;

	list ($ret, $anonymousUserId) =
	    GalleryCoreApi::getPluginParameter('module', 'core', 'id.anonymousUser');
	if ($ret) {
	    return $ret;
	}

	list ($ret, $acceleration) =
	    GalleryCoreApi::getPluginParameter('module', 'core', 'acceleration');
	if ($ret) {
	    return $ret;
	}
	$acceleration = unserialize($acceleration);

	list ($ret, $isAnonymous) = GalleryCoreApi::isAnonymousUser();
	if ($ret) {
	    return $ret;
	}

	$expiration = $acceleration[$isAnonymous ? 'guest' : 'user']['expiration'];
	$phpVm = $gallery->getPhpVm();
	$cutoff = $phpVm->time() - $expiration;

	/* Use UPDATE instead of DELETE since UPDATE is faster and we reuse the rows. */
	$storage =& $gallery->getStorage();

	if ($isAnonymous) {
	    $userIdForSql = (int)$anonymousUserId;
	} else {
	    $userIdForSql = new GallerySqlFragment('<> ?', (int)$anonymousUserId);
	}

	list ($ret, $results) = GalleryCoreApi::updateMapEntry('GalleryCacheMap',
		array('userId' => $userIdForSql,
		      'timestamp' => new GallerySqlFragment('< ?', (int)$cutoff), 'isEmpty' => 0),
		array('value' => null, 'isEmpty' => 1));
	if ($ret) {
	    return $ret;
	}

	return null;
    }
}
?>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists