From 5e60795962d383b107a565944d994c51b4b36022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 5 Jun 2015 14:21:17 +0200 Subject: [PATCH] Bring back OC\Cache\File - fixes #16760 --- lib/base.php | 14 +++ lib/private/cache/file.php | 174 +++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 lib/private/cache/file.php diff --git a/lib/base.php b/lib/base.php index 77b0a89a90..abbb67ee5b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -652,6 +652,7 @@ class OC { OC_User::setupBackends(); } + self::registerCacheHooks(); self::registerFilesystemHooks(); if (\OC::$server->getSystemConfig()->getValue('enable_previews', true)) { self::registerPreviewHooks(); @@ -719,6 +720,19 @@ class OC { }); } + /** + * register hooks for the cache + */ + public static function registerCacheHooks() { + //don't try to do this before we are properly setup + if (\OC::$server->getSystemConfig()->getValue('installed', false) && !\OCP\Util::needUpgrade()) { + + // NOTE: This will be replaced to use OCP + $userSession = self::$server->getUserSession(); + $userSession->listen('postLogin', '\OC\Cache\File', 'loginListener'); + } + } + private static function registerEncryptionWrapper() { \OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OC\Encryption\Manager', 'setupStorage'); } diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php new file mode 100644 index 0000000000..c70698eb7f --- /dev/null +++ b/lib/private/cache/file.php @@ -0,0 +1,174 @@ + + * @author Bart Visscher + * @author Björn Schießle + * @author Jörn Friedrich Dreyer + * @author Michael Gapczynski + * @author Morris Jobke + * @author Robin Appelman + * @author Robin McCorkell + * @author Thomas Müller + * @author Thomas Tanghus + * @author Vincent Petry + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ + +namespace OC\Cache; + +use OC\Files\Filesystem; +use OC\Files\View; +use OCP\Security\ISecureRandom; + +class File { + protected $storage; + + /** + * Returns the cache storage for the logged in user + * + * @return \OC\Files\View cache storage + */ + protected function getStorage() { + if (isset($this->storage)) { + return $this->storage; + } + if (\OC_User::isLoggedIn()) { + $rootView = new View(); + $user = \OC::$server->getUserSession()->getUser(); + Filesystem::initMountPoints($user->getUID()); + if (!$rootView->file_exists('/' . $user->getUID() . '/cache')) { + $rootView->mkdir('/' . $user->getUID() . '/cache'); + } + $this->storage = new View('/' . $user->getUID() . '/cache'); + return $this->storage; + } else { + \OC_Log::write('core', 'Can\'t get cache storage, user not logged in', \OC_Log::ERROR); + throw new \OC\ForbiddenException('Can\t get cache storage, user not logged in'); + } + } + + /** + * @param string $key + */ + public function get($key) { + $result = null; + if ($this->hasKey($key)) { + $storage = $this->getStorage(); + $result = $storage->file_get_contents($key); + } + return $result; + } + + /** + * Returns the size of the stored/cached data + * + * @param string $key + * @return int + */ + public function size($key) { + $result = 0; + if ($this->hasKey($key)) { + $storage = $this->getStorage(); + $result = $storage->filesize($key); + } + return $result; + } + + /** + * @param string $key + */ + public function set($key, $value, $ttl = 0) { + $storage = $this->getStorage(); + $result = false; + // unique id to avoid chunk collision, just in case + $uniqueId = \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate( + 16, + ISecureRandom::CHAR_DIGITS . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER + ); + + // use part file to prevent hasKey() to find the key + // while it is being written + $keyPart = $key . '.' . $uniqueId . '.part'; + if ($storage and $storage->file_put_contents($keyPart, $value)) { + if ($ttl === 0) { + $ttl = 86400; // 60*60*24 + } + $result = $storage->touch($keyPart, time() + $ttl); + $result &= $storage->rename($keyPart, $key); + } + return $result; + } + + public function hasKey($key) { + $storage = $this->getStorage(); + if ($storage && $storage->is_file($key) && $storage->isReadable($key)) { + return true; + } + return false; + } + + /** + * @param string $key + */ + public function remove($key) { + $storage = $this->getStorage(); + if (!$storage) { + return false; + } + return $storage->unlink($key); + } + + public function clear($prefix = '') { + $storage = $this->getStorage(); + if ($storage and $storage->is_dir('/')) { + $dh = $storage->opendir('/'); + if (is_resource($dh)) { + while (($file = readdir($dh)) !== false) { + if ($file != '.' and $file != '..' and ($prefix === '' || strpos($file, $prefix) === 0)) { + $storage->unlink('/' . $file); + } + } + } + } + return true; + } + + public function gc() { + $storage = $this->getStorage(); + if ($storage and $storage->is_dir('/')) { + $now = time(); + $dh = $storage->opendir('/'); + if (!is_resource($dh)) { + return null; + } + while (($file = readdir($dh)) !== false) { + if ($file != '.' and $file != '..') { + $mtime = $storage->filemtime('/' . $file); + if ($mtime < $now) { + $storage->unlink('/' . $file); + } + } + } + } + } + + public static function loginListener() { + $c = new self(); + $c->gc(); + } +}