From 6c86721bbbdfd78105b2e08f2d05aef2ffd14cab Mon Sep 17 00:00:00 2001 From: Dariush Hasanpoor Date: Fri, 6 Sep 2013 00:42:15 +0430 Subject: [PATCH] an internal cache system && a security upgrade to preventing unnecessary IO i added an internal cache `private static $_soft_cache = NULL;` and for security reasons [which we should ever encounter to this] i put general hash sum to cache file's content --- cache.class.php | 554 +++++++++++++++++++++++++----------------------- 1 file changed, 289 insertions(+), 265 deletions(-) diff --git a/cache.class.php b/cache.class.php index 9969671..948abcd 100644 --- a/cache.class.php +++ b/cache.class.php @@ -1,5 +1,4 @@ setCache($config); - } else if (is_array($config)) { - $this->setCache($config['name']); - $this->setCachePath($config['path']); - $this->setExtension($config['extension']); - } + /** + * Default constructor + * + * @param string|array [optional] $config + * @return void + */ + public function __construct($config = null) { + if (true === isset($config)) { + if (is_string($config)) { + $this->setCache($config); + } else if (is_array($config)) { + $this->setCache($config['name']); + $this->setCachePath($config['path']); + $this->setExtension($config['extension']); + } + } } - } - /** - * Check whether data accociated with a key - * - * @param string $key - * @return boolean - */ - public function isCached($key) { - if (false != $this->_loadCache()) { - $cachedData = $this->_loadCache(); - return isset($cachedData[$key]['data']); + /** + * Check whether data accociated with a key + * + * @param string $key + * @return boolean + */ + public function isCached($key) { + $cachedData = $this->_loadCache(); + if (!$cachedData) { + return isset($cachedData[$key]['data']); + } } - } - /** - * Store data in the cache - * - * @param string $key - * @param mixed $data - * @param integer [optional] $expiration - * @return object - */ - public function store($key, $data, $expiration = 0) { - $storeData = array( - 'time' => time(), - 'expire' => $expiration, - 'data' => $data - ); - if (true === is_array($this->_loadCache())) { - $dataArray = $this->_loadCache(); - $dataArray[$key] = $storeData; - } else { - $dataArray = array($key => $storeData); + /** + * Store data in the cache + * + * @param string $key + * @param mixed $data + * @param integer [optional] $expiration + * @return object + */ + public function store($key, $data, $expiration = 0) { + $storeData = array( + 'time' => time(), + 'expire' => $expiration, + 'data' => $data + ); + $dataArray = $this->_loadCache(); + if (true === is_array($dataArray)) { + $dataArray[$key] = $storeData; + } else { + $dataArray = array($key => $storeData); + } + $this->_saveData($dataArray); + return $this; + } + protected function _saveData(array $cacheData) + { + self::$_soft_cache = $cacheData; + $cacheData['hash-sum'] = $this->_getHash(serialize($cacheData)); + $cacheData = serialize($cacheData); + file_put_contents($this->getCacheDir(), $cacheData); + } + /** + * Retrieve cached data by its key + * + * @param string $key + * @param boolean [optional] $timestamp + * @return string + */ + public function retrieve($key, $timestamp = false) { + $cachedData = $this->_loadCache(); + (false === $timestamp) ? $type = 'data' : $type = 'time'; + if(!isset($cachedData[$key][$type])) return NULL; + return $cachedData[$key][$type]; } - $cacheData = json_encode($dataArray); - file_put_contents($this->getCacheDir(), $cacheData); - return $this; - } - - /** - * Retrieve cached data by its key - * - * @param string $key - * @param boolean [optional] $timestamp - * @return string - */ - public function retrieve($key, $timestamp = false) { - $cachedData = $this->_loadCache(); - (false === $timestamp) ? $type = 'data' : $type = 'time'; - return $cachedData[$key][$type]; - } - /** - * Retrieve all cached data - * - * @param boolean [optional] $meta - * @return array - */ - public function retrieveAll($meta = false) { - if ($meta === false) { - $results = array(); - $cachedData = $this->_loadCache(); - if ($cachedData) { - foreach ($cachedData as $k => $v) { - $results[$k] = $v['data']; + /** + * Retrieve all cached data + * + * @param boolean [optional] $meta + * @return array + */ + public function retrieveAll($meta = false) { + if ($meta === false) { + $results = array(); + $cachedData = $this->_loadCache(); + if ($cachedData) { + foreach ($cachedData as $k => $v) { + $results[$k] = $v['data']; + } + } + return $results; + } else { + return $this->_loadCache(); } - } - return $results; - } else { - return $this->_loadCache(); } - } - /** - * Erase cached entry by its key - * - * @param string $key - * @return object - */ - public function erase($key) { - $cacheData = $this->_loadCache(); - if (true === is_array($cacheData)) { - if (true === isset($cacheData[$key])) { - unset($cacheData[$key]); - $cacheData = json_encode($cacheData); - file_put_contents($this->getCacheDir(), $cacheData); - } else { - throw new Exception("Error: erase() - Key '{$key}' not found."); - } + /** + * Erase cached entry by its key + * + * @param string $key + * @return object + */ + public function erase($key) { + $cacheData = $this->_loadCache(); + if (true === is_array($cacheData)) { + if (true === isset($cacheData[$key])) { + unset($cacheData[$key]); + $this->_saveData($cacheData); + } else { + throw new Exception("Error: erase() - Key '{$key}' not found."); + } + } + return $this; } - return $this; - } - /** - * Erase all expired entries - * - * @return integer - */ - public function eraseExpired() { - $cacheData = $this->_loadCache(); - if (true === is_array($cacheData)) { - $counter = 0; - foreach ($cacheData as $key => $entry) { - if (true === $this->_checkExpired($entry['time'], $entry['expire'])) { - unset($cacheData[$key]); - $counter++; + /** + * Erase all expired entries + * + * @return integer + */ + public function eraseExpired() { + $cacheData = $this->_loadCache(); + if (true === is_array($cacheData)) { + $counter = 0; + foreach ($cacheData as $key => $entry) { + if (true === $this->_checkExpired($entry['time'], $entry['expire'])) { + unset($cacheData[$key]); + $counter++; + } + } + if ($counter > 0) { + $this->_saveData($cacheData); + } + return $counter; } - } - if ($counter > 0) { - $cacheData = json_encode($cacheData); - file_put_contents($this->getCacheDir(), $cacheData); - } - return $counter; } - } - /** - * Erase all cached entries - * - * @return object - */ - public function eraseAll() { - $cacheDir = $this->getCacheDir(); - if (true === file_exists($cacheDir)) { - $cacheFile = fopen($cacheDir, 'w'); - fclose($cacheFile); + /** + * Erase all cached entries + * + * @return object + */ + public function eraseAll() { + $cacheDir = $this->getCacheDir(); + if (true === file_exists($cacheDir)) { + $cacheFile = fopen($cacheDir, 'w'); + fclose($cacheFile); + } + return $this; } - return $this; - } - /** - * Load appointed cache - * - * @return mixed - */ - private function _loadCache() { - if (true === file_exists($this->getCacheDir())) { - $file = file_get_contents($this->getCacheDir()); - return json_decode($file, true); - } else { - return false; - } - } + /** + * Load appointed cache + * + * @return mixed + */ + private function _loadCache() { + if(self::$_soft_cache) + return self::$_soft_cache; - /** - * Get the cache directory path - * - * @return string - */ - public function getCacheDir() { - if (true === $this->_checkCacheDir()) { - $filename = $this->getCache(); - $filename = preg_replace('/[^0-9a-z\.\_\-]/i', '', strtolower($filename)); - return $this->getCachePath() . $this->_getHash($filename) . $this->getExtension(); + if (true === file_exists($this->getCacheDir())) { + $file = file_get_contents($this->getCacheDir()); + $u = unserialize($file); + if(!isset($u['hash-sum'])) + { + unlink($this->getCacheDir()); + die("cache data miss-hashed, cache file deleted..."); + } + $h = $u['hash-sum']; + unset($u['hash-sum']); + if($h != $this->_getHash(serialize($u))) + { + unlink($this->getCacheDir()); + die("cache data miss-hashed, cache file deleted..."); + } + return $u; + } + else { + return false; + } } - } - /** - * Get the filename hash - * - * @return string - */ - private function _getHash($filename) { - return sha1($filename); - } + /** + * Get the cache directory path + * + * @return string + */ + public function getCacheDir() { + if (true === $this->_checkCacheDir()) { + $filename = $this->getCache(); + $filename = preg_replace('/[^0-9a-z\.\_\-]/i', '', strtolower($filename)); + return $this->getCachePath() . $this->_getHash($filename) . $this->getExtension(); + } + } - /** - * Check whether a timestamp is still in the duration - * - * @param integer $timestamp - * @param integer $expiration - * @return boolean - */ - private function _checkExpired($timestamp, $expiration) { - $result = false; - if ($expiration !== 0) { - $timeDiff = time() - $timestamp; - ($timeDiff > $expiration) ? $result = true : $result = false; + /** + * Get the filename hash + * + * @return string + */ + private function _getHash($filename) { + return sha1($filename); } - return $result; - } - /** - * Check if a writable cache directory exists and if not create a new one - * - * @return boolean - */ - private function _checkCacheDir() { - if (!is_dir($this->getCachePath()) && !mkdir($this->getCachePath(), 0775, true)) { - throw new Exception('Unable to create cache directory ' . $this->getCachePath()); - } elseif (!is_readable($this->getCachePath()) || !is_writable($this->getCachePath())) { - if (!chmod($this->getCachePath(), 0775)) { - throw new Exception($this->getCachePath() . ' must be readable and writeable'); - } + /** + * Check whether a timestamp is still in the duration + * + * @param integer $timestamp + * @param integer $expiration + * @return boolean + */ + private function _checkExpired($timestamp, $expiration) { + $result = false; + if ($expiration !== 0) { + $timeDiff = time() - $timestamp; + ($timeDiff > $expiration) ? $result = true : $result = false; + } + return $result; } - return true; - } - /** - * Cache path Setter - * - * @param string $path - * @return object - */ - public function setCachePath($path) { - $this->_cachepath = $path; - return $this; - } + /** + * Check if a writable cache directory exists and if not create a new one + * + * @return boolean + */ + private function _checkCacheDir() { + if (!is_dir($this->getCachePath()) && !mkdir($this->getCachePath(), 0775, true)) { + throw new Exception('Unable to create cache directory ' . $this->getCachePath()); + } elseif (!is_readable($this->getCachePath()) || !is_writable($this->getCachePath())) { + if (!chmod($this->getCachePath(), 0775)) { + throw new Exception($this->getCachePath() . ' must be readable and writeable'); + } + } + return true; + } - /** - * Cache path Getter - * - * @return string - */ - public function getCachePath() { - return $this->_cachepath; - } + /** + * Cache path Setter + * + * @param string $path + * @return object + */ + public function setCachePath($path) { + $this->_cachepath = $path; + return $this; + } - /** - * Cache name Setter - * - * @param string $name - * @return object - */ - public function setCache($name) { - $this->_cachename = $name; - return $this; - } + /** + * Cache path Getter + * + * @return string + */ + public function getCachePath() { + return $this->_cachepath; + } - /** - * Cache name Getter - * - * @return void - */ - public function getCache() { - return $this->_cachename; - } + /** + * Cache name Setter + * + * @param string $name + * @return object + */ + public function setCache($name) { + $this->_cachename = $name; + return $this; + } - /** - * Cache file extension Setter - * - * @param string $ext - * @return object - */ - public function setExtension($ext) { - $this->_extension = $ext; - return $this; - } + /** + * Cache name Getter + * + * @return void + */ + public function getCache() { + return $this->_cachename; + } - /** - * Cache file extension Getter - * - * @return string - */ - public function getExtension() { - return $this->_extension; - } + /** + * Cache file extension Setter + * + * @param string $ext + * @return object + */ + public function setExtension($ext) { + $this->_extension = $ext; + return $this; + } -} \ No newline at end of file + /** + * Cache file extension Getter + * + * @return string + */ + public function getExtension() { + return $this->_extension; + } +}