@@ -34,61 +34,61 @@ |
||
| 34 | 34 | require_once __DIR__ . '/lib/versioncheck.php'; |
| 35 | 35 | |
| 36 | 36 | try { |
| 37 | - require_once __DIR__ . '/lib/base.php'; |
|
| 38 | - if (\OCP\Util::needUpgrade()) { |
|
| 39 | - // since the behavior of apps or remotes are unpredictable during |
|
| 40 | - // an upgrade, return a 503 directly |
|
| 41 | - OC_Template::printErrorPage('Service unavailable', '', 503); |
|
| 42 | - exit; |
|
| 43 | - } |
|
| 37 | + require_once __DIR__ . '/lib/base.php'; |
|
| 38 | + if (\OCP\Util::needUpgrade()) { |
|
| 39 | + // since the behavior of apps or remotes are unpredictable during |
|
| 40 | + // an upgrade, return a 503 directly |
|
| 41 | + OC_Template::printErrorPage('Service unavailable', '', 503); |
|
| 42 | + exit; |
|
| 43 | + } |
|
| 44 | 44 | |
| 45 | - OC::checkMaintenanceMode(\OC::$server->get(\OC\SystemConfig::class)); |
|
| 46 | - $request = \OC::$server->getRequest(); |
|
| 47 | - $pathInfo = $request->getPathInfo(); |
|
| 45 | + OC::checkMaintenanceMode(\OC::$server->get(\OC\SystemConfig::class)); |
|
| 46 | + $request = \OC::$server->getRequest(); |
|
| 47 | + $pathInfo = $request->getPathInfo(); |
|
| 48 | 48 | |
| 49 | - if (!$pathInfo && $request->getParam('service', '') === '') { |
|
| 50 | - http_response_code(404); |
|
| 51 | - exit; |
|
| 52 | - } elseif ($request->getParam('service', '')) { |
|
| 53 | - $service = $request->getParam('service', ''); |
|
| 54 | - } else { |
|
| 55 | - $pathInfo = trim($pathInfo, '/'); |
|
| 56 | - [$service] = explode('/', $pathInfo); |
|
| 57 | - } |
|
| 58 | - $file = \OC::$server->getConfig()->getAppValue('core', 'public_' . strip_tags($service)); |
|
| 59 | - if ($file === '') { |
|
| 60 | - http_response_code(404); |
|
| 61 | - exit; |
|
| 62 | - } |
|
| 49 | + if (!$pathInfo && $request->getParam('service', '') === '') { |
|
| 50 | + http_response_code(404); |
|
| 51 | + exit; |
|
| 52 | + } elseif ($request->getParam('service', '')) { |
|
| 53 | + $service = $request->getParam('service', ''); |
|
| 54 | + } else { |
|
| 55 | + $pathInfo = trim($pathInfo, '/'); |
|
| 56 | + [$service] = explode('/', $pathInfo); |
|
| 57 | + } |
|
| 58 | + $file = \OC::$server->getConfig()->getAppValue('core', 'public_' . strip_tags($service)); |
|
| 59 | + if ($file === '') { |
|
| 60 | + http_response_code(404); |
|
| 61 | + exit; |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - $parts = explode('/', $file, 2); |
|
| 65 | - $app = $parts[0]; |
|
| 64 | + $parts = explode('/', $file, 2); |
|
| 65 | + $app = $parts[0]; |
|
| 66 | 66 | |
| 67 | - // Load all required applications |
|
| 68 | - \OC::$REQUESTEDAPP = $app; |
|
| 69 | - OC_App::loadApps(['authentication']); |
|
| 70 | - OC_App::loadApps(['filesystem', 'logging']); |
|
| 67 | + // Load all required applications |
|
| 68 | + \OC::$REQUESTEDAPP = $app; |
|
| 69 | + OC_App::loadApps(['authentication']); |
|
| 70 | + OC_App::loadApps(['filesystem', 'logging']); |
|
| 71 | 71 | |
| 72 | - if (!\OC::$server->getAppManager()->isInstalled($app)) { |
|
| 73 | - http_response_code(404); |
|
| 74 | - exit; |
|
| 75 | - } |
|
| 76 | - OC_App::loadApp($app); |
|
| 77 | - OC_User::setIncognitoMode(true); |
|
| 72 | + if (!\OC::$server->getAppManager()->isInstalled($app)) { |
|
| 73 | + http_response_code(404); |
|
| 74 | + exit; |
|
| 75 | + } |
|
| 76 | + OC_App::loadApp($app); |
|
| 77 | + OC_User::setIncognitoMode(true); |
|
| 78 | 78 | |
| 79 | - $baseuri = OC::$WEBROOT . '/public.php/' . $service . '/'; |
|
| 79 | + $baseuri = OC::$WEBROOT . '/public.php/' . $service . '/'; |
|
| 80 | 80 | |
| 81 | - require_once OC_App::getAppPath($app) . '/' . $parts[1]; |
|
| 81 | + require_once OC_App::getAppPath($app) . '/' . $parts[1]; |
|
| 82 | 82 | } catch (Exception $ex) { |
| 83 | - $status = 500; |
|
| 84 | - if ($ex instanceof \OC\ServiceUnavailableException) { |
|
| 85 | - $status = 503; |
|
| 86 | - } |
|
| 87 | - //show the user a detailed error page |
|
| 88 | - \OC::$server->getLogger()->logException($ex, ['app' => 'public']); |
|
| 89 | - OC_Template::printExceptionErrorPage($ex, $status); |
|
| 83 | + $status = 500; |
|
| 84 | + if ($ex instanceof \OC\ServiceUnavailableException) { |
|
| 85 | + $status = 503; |
|
| 86 | + } |
|
| 87 | + //show the user a detailed error page |
|
| 88 | + \OC::$server->getLogger()->logException($ex, ['app' => 'public']); |
|
| 89 | + OC_Template::printExceptionErrorPage($ex, $status); |
|
| 90 | 90 | } catch (Error $ex) { |
| 91 | - //show the user a detailed error page |
|
| 92 | - \OC::$server->getLogger()->logException($ex, ['app' => 'public']); |
|
| 93 | - OC_Template::printExceptionErrorPage($ex, 500); |
|
| 91 | + //show the user a detailed error page |
|
| 92 | + \OC::$server->getLogger()->logException($ex, ['app' => 'public']); |
|
| 93 | + OC_Template::printExceptionErrorPage($ex, 500); |
|
| 94 | 94 | } |
@@ -31,10 +31,10 @@ discard block |
||
| 31 | 31 | * |
| 32 | 32 | */ |
| 33 | 33 | |
| 34 | -require_once __DIR__ . '/lib/versioncheck.php'; |
|
| 34 | +require_once __DIR__.'/lib/versioncheck.php'; |
|
| 35 | 35 | |
| 36 | 36 | try { |
| 37 | - require_once __DIR__ . '/lib/base.php'; |
|
| 37 | + require_once __DIR__.'/lib/base.php'; |
|
| 38 | 38 | if (\OCP\Util::needUpgrade()) { |
| 39 | 39 | // since the behavior of apps or remotes are unpredictable during |
| 40 | 40 | // an upgrade, return a 503 directly |
@@ -55,7 +55,7 @@ discard block |
||
| 55 | 55 | $pathInfo = trim($pathInfo, '/'); |
| 56 | 56 | [$service] = explode('/', $pathInfo); |
| 57 | 57 | } |
| 58 | - $file = \OC::$server->getConfig()->getAppValue('core', 'public_' . strip_tags($service)); |
|
| 58 | + $file = \OC::$server->getConfig()->getAppValue('core', 'public_'.strip_tags($service)); |
|
| 59 | 59 | if ($file === '') { |
| 60 | 60 | http_response_code(404); |
| 61 | 61 | exit; |
@@ -76,9 +76,9 @@ discard block |
||
| 76 | 76 | OC_App::loadApp($app); |
| 77 | 77 | OC_User::setIncognitoMode(true); |
| 78 | 78 | |
| 79 | - $baseuri = OC::$WEBROOT . '/public.php/' . $service . '/'; |
|
| 79 | + $baseuri = OC::$WEBROOT.'/public.php/'.$service.'/'; |
|
| 80 | 80 | |
| 81 | - require_once OC_App::getAppPath($app) . '/' . $parts[1]; |
|
| 81 | + require_once OC_App::getAppPath($app).'/'.$parts[1]; |
|
| 82 | 82 | } catch (Exception $ex) { |
| 83 | 83 | $status = 500; |
| 84 | 84 | if ($ex instanceof \OC\ServiceUnavailableException) { |
@@ -40,151 +40,151 @@ |
||
| 40 | 40 | use OCP\ILogger; |
| 41 | 41 | |
| 42 | 42 | class Autoloader { |
| 43 | - /** @var bool */ |
|
| 44 | - private $useGlobalClassPath = true; |
|
| 45 | - /** @var array */ |
|
| 46 | - private $validRoots = []; |
|
| 47 | - |
|
| 48 | - /** |
|
| 49 | - * Optional low-latency memory cache for class to path mapping. |
|
| 50 | - * |
|
| 51 | - * @var \OC\Memcache\Cache |
|
| 52 | - */ |
|
| 53 | - protected $memoryCache; |
|
| 54 | - |
|
| 55 | - /** |
|
| 56 | - * Autoloader constructor. |
|
| 57 | - * |
|
| 58 | - * @param string[] $validRoots |
|
| 59 | - */ |
|
| 60 | - public function __construct(array $validRoots) { |
|
| 61 | - foreach ($validRoots as $root) { |
|
| 62 | - $this->validRoots[$root] = true; |
|
| 63 | - } |
|
| 64 | - } |
|
| 65 | - |
|
| 66 | - /** |
|
| 67 | - * Add a path to the list of valid php roots for auto loading |
|
| 68 | - * |
|
| 69 | - * @param string $root |
|
| 70 | - */ |
|
| 71 | - public function addValidRoot(string $root) { |
|
| 72 | - $root = stream_resolve_include_path($root); |
|
| 73 | - $this->validRoots[$root] = true; |
|
| 74 | - } |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * disable the usage of the global classpath \OC::$CLASSPATH |
|
| 78 | - */ |
|
| 79 | - public function disableGlobalClassPath() { |
|
| 80 | - $this->useGlobalClassPath = false; |
|
| 81 | - } |
|
| 82 | - |
|
| 83 | - /** |
|
| 84 | - * enable the usage of the global classpath \OC::$CLASSPATH |
|
| 85 | - */ |
|
| 86 | - public function enableGlobalClassPath() { |
|
| 87 | - $this->useGlobalClassPath = true; |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - /** |
|
| 91 | - * get the possible paths for a class |
|
| 92 | - * |
|
| 93 | - * @param string $class |
|
| 94 | - * @return array an array of possible paths |
|
| 95 | - */ |
|
| 96 | - public function findClass(string $class): array { |
|
| 97 | - $class = trim($class, '\\'); |
|
| 98 | - |
|
| 99 | - $paths = []; |
|
| 100 | - if ($this->useGlobalClassPath && array_key_exists($class, \OC::$CLASSPATH)) { |
|
| 101 | - $paths[] = \OC::$CLASSPATH[$class]; |
|
| 102 | - /** |
|
| 103 | - * @TODO: Remove this when necessary |
|
| 104 | - * Remove "apps/" from inclusion path for smooth migration to multi app dir |
|
| 105 | - */ |
|
| 106 | - if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { |
|
| 107 | - \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', ILogger::DEBUG); |
|
| 108 | - $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); |
|
| 109 | - } |
|
| 110 | - } elseif (strpos($class, 'OC_') === 0) { |
|
| 111 | - $paths[] = \OC::$SERVERROOT . '/lib/private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); |
|
| 112 | - } elseif (strpos($class, 'OCA\\') === 0) { |
|
| 113 | - [, $app, $rest] = explode('\\', $class, 3); |
|
| 114 | - $app = strtolower($app); |
|
| 115 | - $appPath = \OC_App::getAppPath($app); |
|
| 116 | - if ($appPath && stream_resolve_include_path($appPath)) { |
|
| 117 | - $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 118 | - // If not found in the root of the app directory, insert '/lib' after app id and try again. |
|
| 119 | - $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 120 | - } |
|
| 121 | - } elseif ($class === 'Test\\TestCase') { |
|
| 122 | - // This File is considered public API, so we make sure that the class |
|
| 123 | - // can still be loaded, although the PSR-4 paths have not been loaded. |
|
| 124 | - $paths[] = \OC::$SERVERROOT . '/tests/lib/TestCase.php'; |
|
| 125 | - } |
|
| 126 | - return $paths; |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - /** |
|
| 130 | - * @param string $fullPath |
|
| 131 | - * @return bool |
|
| 132 | - * @throws AutoloadNotAllowedException |
|
| 133 | - */ |
|
| 134 | - protected function isValidPath(string $fullPath): bool { |
|
| 135 | - foreach ($this->validRoots as $root => $true) { |
|
| 136 | - if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') { |
|
| 137 | - return true; |
|
| 138 | - } |
|
| 139 | - } |
|
| 140 | - throw new AutoloadNotAllowedException($fullPath); |
|
| 141 | - } |
|
| 142 | - |
|
| 143 | - /** |
|
| 144 | - * Load the specified class |
|
| 145 | - * |
|
| 146 | - * @param string $class |
|
| 147 | - * @return bool |
|
| 148 | - * @throws AutoloadNotAllowedException |
|
| 149 | - */ |
|
| 150 | - public function load(string $class): bool { |
|
| 151 | - $pathsToRequire = null; |
|
| 152 | - if ($this->memoryCache) { |
|
| 153 | - $pathsToRequire = $this->memoryCache->get($class); |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - if (class_exists($class, false)) { |
|
| 157 | - return false; |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - if (!is_array($pathsToRequire)) { |
|
| 161 | - // No cache or cache miss |
|
| 162 | - $pathsToRequire = []; |
|
| 163 | - foreach ($this->findClass($class) as $path) { |
|
| 164 | - $fullPath = stream_resolve_include_path($path); |
|
| 165 | - if ($fullPath && $this->isValidPath($fullPath)) { |
|
| 166 | - $pathsToRequire[] = $fullPath; |
|
| 167 | - } |
|
| 168 | - } |
|
| 169 | - |
|
| 170 | - if ($this->memoryCache) { |
|
| 171 | - $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec |
|
| 172 | - } |
|
| 173 | - } |
|
| 174 | - |
|
| 175 | - foreach ($pathsToRequire as $fullPath) { |
|
| 176 | - require_once $fullPath; |
|
| 177 | - } |
|
| 178 | - |
|
| 179 | - return false; |
|
| 180 | - } |
|
| 181 | - |
|
| 182 | - /** |
|
| 183 | - * Sets the optional low-latency cache for class to path mapping. |
|
| 184 | - * |
|
| 185 | - * @param \OC\Memcache\Cache $memoryCache Instance of memory cache. |
|
| 186 | - */ |
|
| 187 | - public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) { |
|
| 188 | - $this->memoryCache = $memoryCache; |
|
| 189 | - } |
|
| 43 | + /** @var bool */ |
|
| 44 | + private $useGlobalClassPath = true; |
|
| 45 | + /** @var array */ |
|
| 46 | + private $validRoots = []; |
|
| 47 | + |
|
| 48 | + /** |
|
| 49 | + * Optional low-latency memory cache for class to path mapping. |
|
| 50 | + * |
|
| 51 | + * @var \OC\Memcache\Cache |
|
| 52 | + */ |
|
| 53 | + protected $memoryCache; |
|
| 54 | + |
|
| 55 | + /** |
|
| 56 | + * Autoloader constructor. |
|
| 57 | + * |
|
| 58 | + * @param string[] $validRoots |
|
| 59 | + */ |
|
| 60 | + public function __construct(array $validRoots) { |
|
| 61 | + foreach ($validRoots as $root) { |
|
| 62 | + $this->validRoots[$root] = true; |
|
| 63 | + } |
|
| 64 | + } |
|
| 65 | + |
|
| 66 | + /** |
|
| 67 | + * Add a path to the list of valid php roots for auto loading |
|
| 68 | + * |
|
| 69 | + * @param string $root |
|
| 70 | + */ |
|
| 71 | + public function addValidRoot(string $root) { |
|
| 72 | + $root = stream_resolve_include_path($root); |
|
| 73 | + $this->validRoots[$root] = true; |
|
| 74 | + } |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * disable the usage of the global classpath \OC::$CLASSPATH |
|
| 78 | + */ |
|
| 79 | + public function disableGlobalClassPath() { |
|
| 80 | + $this->useGlobalClassPath = false; |
|
| 81 | + } |
|
| 82 | + |
|
| 83 | + /** |
|
| 84 | + * enable the usage of the global classpath \OC::$CLASSPATH |
|
| 85 | + */ |
|
| 86 | + public function enableGlobalClassPath() { |
|
| 87 | + $this->useGlobalClassPath = true; |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + /** |
|
| 91 | + * get the possible paths for a class |
|
| 92 | + * |
|
| 93 | + * @param string $class |
|
| 94 | + * @return array an array of possible paths |
|
| 95 | + */ |
|
| 96 | + public function findClass(string $class): array { |
|
| 97 | + $class = trim($class, '\\'); |
|
| 98 | + |
|
| 99 | + $paths = []; |
|
| 100 | + if ($this->useGlobalClassPath && array_key_exists($class, \OC::$CLASSPATH)) { |
|
| 101 | + $paths[] = \OC::$CLASSPATH[$class]; |
|
| 102 | + /** |
|
| 103 | + * @TODO: Remove this when necessary |
|
| 104 | + * Remove "apps/" from inclusion path for smooth migration to multi app dir |
|
| 105 | + */ |
|
| 106 | + if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { |
|
| 107 | + \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', ILogger::DEBUG); |
|
| 108 | + $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); |
|
| 109 | + } |
|
| 110 | + } elseif (strpos($class, 'OC_') === 0) { |
|
| 111 | + $paths[] = \OC::$SERVERROOT . '/lib/private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); |
|
| 112 | + } elseif (strpos($class, 'OCA\\') === 0) { |
|
| 113 | + [, $app, $rest] = explode('\\', $class, 3); |
|
| 114 | + $app = strtolower($app); |
|
| 115 | + $appPath = \OC_App::getAppPath($app); |
|
| 116 | + if ($appPath && stream_resolve_include_path($appPath)) { |
|
| 117 | + $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 118 | + // If not found in the root of the app directory, insert '/lib' after app id and try again. |
|
| 119 | + $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 120 | + } |
|
| 121 | + } elseif ($class === 'Test\\TestCase') { |
|
| 122 | + // This File is considered public API, so we make sure that the class |
|
| 123 | + // can still be loaded, although the PSR-4 paths have not been loaded. |
|
| 124 | + $paths[] = \OC::$SERVERROOT . '/tests/lib/TestCase.php'; |
|
| 125 | + } |
|
| 126 | + return $paths; |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + /** |
|
| 130 | + * @param string $fullPath |
|
| 131 | + * @return bool |
|
| 132 | + * @throws AutoloadNotAllowedException |
|
| 133 | + */ |
|
| 134 | + protected function isValidPath(string $fullPath): bool { |
|
| 135 | + foreach ($this->validRoots as $root => $true) { |
|
| 136 | + if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') { |
|
| 137 | + return true; |
|
| 138 | + } |
|
| 139 | + } |
|
| 140 | + throw new AutoloadNotAllowedException($fullPath); |
|
| 141 | + } |
|
| 142 | + |
|
| 143 | + /** |
|
| 144 | + * Load the specified class |
|
| 145 | + * |
|
| 146 | + * @param string $class |
|
| 147 | + * @return bool |
|
| 148 | + * @throws AutoloadNotAllowedException |
|
| 149 | + */ |
|
| 150 | + public function load(string $class): bool { |
|
| 151 | + $pathsToRequire = null; |
|
| 152 | + if ($this->memoryCache) { |
|
| 153 | + $pathsToRequire = $this->memoryCache->get($class); |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + if (class_exists($class, false)) { |
|
| 157 | + return false; |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + if (!is_array($pathsToRequire)) { |
|
| 161 | + // No cache or cache miss |
|
| 162 | + $pathsToRequire = []; |
|
| 163 | + foreach ($this->findClass($class) as $path) { |
|
| 164 | + $fullPath = stream_resolve_include_path($path); |
|
| 165 | + if ($fullPath && $this->isValidPath($fullPath)) { |
|
| 166 | + $pathsToRequire[] = $fullPath; |
|
| 167 | + } |
|
| 168 | + } |
|
| 169 | + |
|
| 170 | + if ($this->memoryCache) { |
|
| 171 | + $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec |
|
| 172 | + } |
|
| 173 | + } |
|
| 174 | + |
|
| 175 | + foreach ($pathsToRequire as $fullPath) { |
|
| 176 | + require_once $fullPath; |
|
| 177 | + } |
|
| 178 | + |
|
| 179 | + return false; |
|
| 180 | + } |
|
| 181 | + |
|
| 182 | + /** |
|
| 183 | + * Sets the optional low-latency cache for class to path mapping. |
|
| 184 | + * |
|
| 185 | + * @param \OC\Memcache\Cache $memoryCache Instance of memory cache. |
|
| 186 | + */ |
|
| 187 | + public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) { |
|
| 188 | + $this->memoryCache = $memoryCache; |
|
| 189 | + } |
|
| 190 | 190 | } |
@@ -104,24 +104,24 @@ discard block |
||
| 104 | 104 | * Remove "apps/" from inclusion path for smooth migration to multi app dir |
| 105 | 105 | */ |
| 106 | 106 | if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { |
| 107 | - \OCP\Util::writeLog('core', 'include path for class "' . $class . '" starts with "apps/"', ILogger::DEBUG); |
|
| 107 | + \OCP\Util::writeLog('core', 'include path for class "'.$class.'" starts with "apps/"', ILogger::DEBUG); |
|
| 108 | 108 | $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); |
| 109 | 109 | } |
| 110 | 110 | } elseif (strpos($class, 'OC_') === 0) { |
| 111 | - $paths[] = \OC::$SERVERROOT . '/lib/private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); |
|
| 111 | + $paths[] = \OC::$SERVERROOT.'/lib/private/legacy/'.strtolower(str_replace('_', '/', substr($class, 3)).'.php'); |
|
| 112 | 112 | } elseif (strpos($class, 'OCA\\') === 0) { |
| 113 | 113 | [, $app, $rest] = explode('\\', $class, 3); |
| 114 | 114 | $app = strtolower($app); |
| 115 | 115 | $appPath = \OC_App::getAppPath($app); |
| 116 | 116 | if ($appPath && stream_resolve_include_path($appPath)) { |
| 117 | - $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 117 | + $paths[] = $appPath.'/'.strtolower(str_replace('\\', '/', $rest).'.php'); |
|
| 118 | 118 | // If not found in the root of the app directory, insert '/lib' after app id and try again. |
| 119 | - $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); |
|
| 119 | + $paths[] = $appPath.'/lib/'.strtolower(str_replace('\\', '/', $rest).'.php'); |
|
| 120 | 120 | } |
| 121 | 121 | } elseif ($class === 'Test\\TestCase') { |
| 122 | 122 | // This File is considered public API, so we make sure that the class |
| 123 | 123 | // can still be loaded, although the PSR-4 paths have not been loaded. |
| 124 | - $paths[] = \OC::$SERVERROOT . '/tests/lib/TestCase.php'; |
|
| 124 | + $paths[] = \OC::$SERVERROOT.'/tests/lib/TestCase.php'; |
|
| 125 | 125 | } |
| 126 | 126 | return $paths; |
| 127 | 127 | } |
@@ -133,7 +133,7 @@ discard block |
||
| 133 | 133 | */ |
| 134 | 134 | protected function isValidPath(string $fullPath): bool { |
| 135 | 135 | foreach ($this->validRoots as $root => $true) { |
| 136 | - if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') { |
|
| 136 | + if (substr($fullPath, 0, strlen($root) + 1) === $root.'/') { |
|
| 137 | 137 | return true; |
| 138 | 138 | } |
| 139 | 139 | } |
@@ -53,235 +53,235 @@ |
||
| 53 | 53 | use Psr\Http\Message\RequestInterface; |
| 54 | 54 | |
| 55 | 55 | class SwiftFactory { |
| 56 | - private $cache; |
|
| 57 | - private $params; |
|
| 58 | - /** @var Container|null */ |
|
| 59 | - private $container = null; |
|
| 60 | - private $logger; |
|
| 56 | + private $cache; |
|
| 57 | + private $params; |
|
| 58 | + /** @var Container|null */ |
|
| 59 | + private $container = null; |
|
| 60 | + private $logger; |
|
| 61 | 61 | |
| 62 | - public const DEFAULT_OPTIONS = [ |
|
| 63 | - 'autocreate' => false, |
|
| 64 | - 'urlType' => 'publicURL', |
|
| 65 | - 'catalogName' => 'swift', |
|
| 66 | - 'catalogType' => 'object-store' |
|
| 67 | - ]; |
|
| 62 | + public const DEFAULT_OPTIONS = [ |
|
| 63 | + 'autocreate' => false, |
|
| 64 | + 'urlType' => 'publicURL', |
|
| 65 | + 'catalogName' => 'swift', |
|
| 66 | + 'catalogType' => 'object-store' |
|
| 67 | + ]; |
|
| 68 | 68 | |
| 69 | - public function __construct(ICache $cache, array $params, ILogger $logger) { |
|
| 70 | - $this->cache = $cache; |
|
| 71 | - $this->params = $params; |
|
| 72 | - $this->logger = $logger; |
|
| 73 | - } |
|
| 69 | + public function __construct(ICache $cache, array $params, ILogger $logger) { |
|
| 70 | + $this->cache = $cache; |
|
| 71 | + $this->params = $params; |
|
| 72 | + $this->logger = $logger; |
|
| 73 | + } |
|
| 74 | 74 | |
| 75 | - /** |
|
| 76 | - * Gets currently cached token id |
|
| 77 | - * |
|
| 78 | - * @return string |
|
| 79 | - * @throws StorageAuthException |
|
| 80 | - */ |
|
| 81 | - public function getCachedTokenId() { |
|
| 82 | - if (!isset($this->params['cachedToken'])) { |
|
| 83 | - throw new StorageAuthException('Unauthenticated ObjectStore connection'); |
|
| 84 | - } |
|
| 75 | + /** |
|
| 76 | + * Gets currently cached token id |
|
| 77 | + * |
|
| 78 | + * @return string |
|
| 79 | + * @throws StorageAuthException |
|
| 80 | + */ |
|
| 81 | + public function getCachedTokenId() { |
|
| 82 | + if (!isset($this->params['cachedToken'])) { |
|
| 83 | + throw new StorageAuthException('Unauthenticated ObjectStore connection'); |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | - // Is it V2 token? |
|
| 87 | - if (isset($this->params['cachedToken']['token'])) { |
|
| 88 | - return $this->params['cachedToken']['token']['id']; |
|
| 89 | - } |
|
| 86 | + // Is it V2 token? |
|
| 87 | + if (isset($this->params['cachedToken']['token'])) { |
|
| 88 | + return $this->params['cachedToken']['token']['id']; |
|
| 89 | + } |
|
| 90 | 90 | |
| 91 | - return $this->params['cachedToken']['id']; |
|
| 92 | - } |
|
| 91 | + return $this->params['cachedToken']['id']; |
|
| 92 | + } |
|
| 93 | 93 | |
| 94 | - private function getCachedToken(string $cacheKey) { |
|
| 95 | - $cachedTokenString = $this->cache->get($cacheKey . '/token'); |
|
| 96 | - if ($cachedTokenString) { |
|
| 97 | - return json_decode($cachedTokenString, true); |
|
| 98 | - } else { |
|
| 99 | - return null; |
|
| 100 | - } |
|
| 101 | - } |
|
| 94 | + private function getCachedToken(string $cacheKey) { |
|
| 95 | + $cachedTokenString = $this->cache->get($cacheKey . '/token'); |
|
| 96 | + if ($cachedTokenString) { |
|
| 97 | + return json_decode($cachedTokenString, true); |
|
| 98 | + } else { |
|
| 99 | + return null; |
|
| 100 | + } |
|
| 101 | + } |
|
| 102 | 102 | |
| 103 | - private function cacheToken(Token $token, string $serviceUrl, string $cacheKey) { |
|
| 104 | - if ($token instanceof \OpenStack\Identity\v3\Models\Token) { |
|
| 105 | - // for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately |
|
| 106 | - $value = $token->export(); |
|
| 107 | - } else { |
|
| 108 | - /** @var \OpenStack\Identity\v2\Models\Token $token */ |
|
| 109 | - $value = [ |
|
| 110 | - 'serviceUrl' => $serviceUrl, |
|
| 111 | - 'token' => [ |
|
| 112 | - 'issued_at' => $token->issuedAt->format('c'), |
|
| 113 | - 'expires' => $token->expires->format('c'), |
|
| 114 | - 'id' => $token->id, |
|
| 115 | - 'tenant' => $token->tenant |
|
| 116 | - ] |
|
| 117 | - ]; |
|
| 118 | - } |
|
| 103 | + private function cacheToken(Token $token, string $serviceUrl, string $cacheKey) { |
|
| 104 | + if ($token instanceof \OpenStack\Identity\v3\Models\Token) { |
|
| 105 | + // for v3 the catalog is cached as part of the token, so no need to cache $serviceUrl separately |
|
| 106 | + $value = $token->export(); |
|
| 107 | + } else { |
|
| 108 | + /** @var \OpenStack\Identity\v2\Models\Token $token */ |
|
| 109 | + $value = [ |
|
| 110 | + 'serviceUrl' => $serviceUrl, |
|
| 111 | + 'token' => [ |
|
| 112 | + 'issued_at' => $token->issuedAt->format('c'), |
|
| 113 | + 'expires' => $token->expires->format('c'), |
|
| 114 | + 'id' => $token->id, |
|
| 115 | + 'tenant' => $token->tenant |
|
| 116 | + ] |
|
| 117 | + ]; |
|
| 118 | + } |
|
| 119 | 119 | |
| 120 | - $this->params['cachedToken'] = $value; |
|
| 121 | - $this->cache->set($cacheKey . '/token', json_encode($value)); |
|
| 122 | - } |
|
| 120 | + $this->params['cachedToken'] = $value; |
|
| 121 | + $this->cache->set($cacheKey . '/token', json_encode($value)); |
|
| 122 | + } |
|
| 123 | 123 | |
| 124 | - /** |
|
| 125 | - * @return OpenStack |
|
| 126 | - * @throws StorageAuthException |
|
| 127 | - */ |
|
| 128 | - private function getClient() { |
|
| 129 | - if (isset($this->params['bucket'])) { |
|
| 130 | - $this->params['container'] = $this->params['bucket']; |
|
| 131 | - } |
|
| 132 | - if (!isset($this->params['container'])) { |
|
| 133 | - $this->params['container'] = 'nextcloud'; |
|
| 134 | - } |
|
| 135 | - if (isset($this->params['user']) && is_array($this->params['user'])) { |
|
| 136 | - $userName = $this->params['user']['name']; |
|
| 137 | - } else { |
|
| 138 | - if (!isset($this->params['username']) && isset($this->params['user'])) { |
|
| 139 | - $this->params['username'] = $this->params['user']; |
|
| 140 | - } |
|
| 141 | - $userName = $this->params['username']; |
|
| 142 | - } |
|
| 143 | - if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) { |
|
| 144 | - $this->params['tenantName'] = $this->params['tenant']; |
|
| 145 | - } |
|
| 146 | - if (isset($this->params['domain'])) { |
|
| 147 | - $this->params['scope']['project']['name'] = $this->params['tenant']; |
|
| 148 | - $this->params['scope']['project']['domain']['name'] = $this->params['domain']; |
|
| 149 | - } |
|
| 150 | - $this->params = array_merge(self::DEFAULT_OPTIONS, $this->params); |
|
| 124 | + /** |
|
| 125 | + * @return OpenStack |
|
| 126 | + * @throws StorageAuthException |
|
| 127 | + */ |
|
| 128 | + private function getClient() { |
|
| 129 | + if (isset($this->params['bucket'])) { |
|
| 130 | + $this->params['container'] = $this->params['bucket']; |
|
| 131 | + } |
|
| 132 | + if (!isset($this->params['container'])) { |
|
| 133 | + $this->params['container'] = 'nextcloud'; |
|
| 134 | + } |
|
| 135 | + if (isset($this->params['user']) && is_array($this->params['user'])) { |
|
| 136 | + $userName = $this->params['user']['name']; |
|
| 137 | + } else { |
|
| 138 | + if (!isset($this->params['username']) && isset($this->params['user'])) { |
|
| 139 | + $this->params['username'] = $this->params['user']; |
|
| 140 | + } |
|
| 141 | + $userName = $this->params['username']; |
|
| 142 | + } |
|
| 143 | + if (!isset($this->params['tenantName']) && isset($this->params['tenant'])) { |
|
| 144 | + $this->params['tenantName'] = $this->params['tenant']; |
|
| 145 | + } |
|
| 146 | + if (isset($this->params['domain'])) { |
|
| 147 | + $this->params['scope']['project']['name'] = $this->params['tenant']; |
|
| 148 | + $this->params['scope']['project']['domain']['name'] = $this->params['domain']; |
|
| 149 | + } |
|
| 150 | + $this->params = array_merge(self::DEFAULT_OPTIONS, $this->params); |
|
| 151 | 151 | |
| 152 | - $cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container']; |
|
| 153 | - $token = $this->getCachedToken($cacheKey); |
|
| 154 | - $this->params['cachedToken'] = $token; |
|
| 152 | + $cacheKey = $userName . '@' . $this->params['url'] . '/' . $this->params['container']; |
|
| 153 | + $token = $this->getCachedToken($cacheKey); |
|
| 154 | + $this->params['cachedToken'] = $token; |
|
| 155 | 155 | |
| 156 | - $httpClient = new Client([ |
|
| 157 | - 'base_uri' => TransportUtils::normalizeUrl($this->params['url']), |
|
| 158 | - 'handler' => HandlerStack::create() |
|
| 159 | - ]); |
|
| 156 | + $httpClient = new Client([ |
|
| 157 | + 'base_uri' => TransportUtils::normalizeUrl($this->params['url']), |
|
| 158 | + 'handler' => HandlerStack::create() |
|
| 159 | + ]); |
|
| 160 | 160 | |
| 161 | - if (isset($this->params['user']) && is_array($this->params['user']) && isset($this->params['user']['name'])) { |
|
| 162 | - if (!isset($this->params['scope'])) { |
|
| 163 | - throw new StorageAuthException('Scope has to be defined for V3 requests'); |
|
| 164 | - } |
|
| 161 | + if (isset($this->params['user']) && is_array($this->params['user']) && isset($this->params['user']['name'])) { |
|
| 162 | + if (!isset($this->params['scope'])) { |
|
| 163 | + throw new StorageAuthException('Scope has to be defined for V3 requests'); |
|
| 164 | + } |
|
| 165 | 165 | |
| 166 | - return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey); |
|
| 167 | - } else { |
|
| 168 | - return $this->auth(SwiftV2CachingAuthService::factory($httpClient), $cacheKey); |
|
| 169 | - } |
|
| 170 | - } |
|
| 166 | + return $this->auth(IdentityV3Service::factory($httpClient), $cacheKey); |
|
| 167 | + } else { |
|
| 168 | + return $this->auth(SwiftV2CachingAuthService::factory($httpClient), $cacheKey); |
|
| 169 | + } |
|
| 170 | + } |
|
| 171 | 171 | |
| 172 | - /** |
|
| 173 | - * @param IdentityV2Service|IdentityV3Service $authService |
|
| 174 | - * @param string $cacheKey |
|
| 175 | - * @return OpenStack |
|
| 176 | - * @throws StorageAuthException |
|
| 177 | - */ |
|
| 178 | - private function auth($authService, string $cacheKey) { |
|
| 179 | - $this->params['identityService'] = $authService; |
|
| 180 | - $this->params['authUrl'] = $this->params['url']; |
|
| 172 | + /** |
|
| 173 | + * @param IdentityV2Service|IdentityV3Service $authService |
|
| 174 | + * @param string $cacheKey |
|
| 175 | + * @return OpenStack |
|
| 176 | + * @throws StorageAuthException |
|
| 177 | + */ |
|
| 178 | + private function auth($authService, string $cacheKey) { |
|
| 179 | + $this->params['identityService'] = $authService; |
|
| 180 | + $this->params['authUrl'] = $this->params['url']; |
|
| 181 | 181 | |
| 182 | - $cachedToken = $this->params['cachedToken']; |
|
| 183 | - $hasValidCachedToken = false; |
|
| 184 | - if (\is_array($cachedToken)) { |
|
| 185 | - if ($authService instanceof IdentityV3Service) { |
|
| 186 | - $token = $authService->generateTokenFromCache($cachedToken); |
|
| 187 | - if (\is_null($token->catalog)) { |
|
| 188 | - $this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken)); |
|
| 189 | - } elseif ($token->hasExpired()) { |
|
| 190 | - $this->logger->debug('Cached token for swift expired'); |
|
| 191 | - } else { |
|
| 192 | - $hasValidCachedToken = true; |
|
| 193 | - } |
|
| 194 | - } else { |
|
| 195 | - try { |
|
| 196 | - /** @var \OpenStack\Identity\v2\Models\Token $token */ |
|
| 197 | - $token = $authService->model(\OpenStack\Identity\v2\Models\Token::class, $cachedToken['token']); |
|
| 198 | - $now = new \DateTimeImmutable("now"); |
|
| 199 | - if ($token->expires > $now) { |
|
| 200 | - $hasValidCachedToken = true; |
|
| 201 | - $this->params['v2cachedToken'] = $token; |
|
| 202 | - $this->params['v2serviceUrl'] = $cachedToken['serviceUrl']; |
|
| 203 | - } else { |
|
| 204 | - $this->logger->debug('Cached token for swift expired'); |
|
| 205 | - } |
|
| 206 | - } catch (\Exception $e) { |
|
| 207 | - $this->logger->logException($e); |
|
| 208 | - } |
|
| 209 | - } |
|
| 210 | - } |
|
| 182 | + $cachedToken = $this->params['cachedToken']; |
|
| 183 | + $hasValidCachedToken = false; |
|
| 184 | + if (\is_array($cachedToken)) { |
|
| 185 | + if ($authService instanceof IdentityV3Service) { |
|
| 186 | + $token = $authService->generateTokenFromCache($cachedToken); |
|
| 187 | + if (\is_null($token->catalog)) { |
|
| 188 | + $this->logger->warning('Invalid cached token for swift, no catalog set: ' . json_encode($cachedToken)); |
|
| 189 | + } elseif ($token->hasExpired()) { |
|
| 190 | + $this->logger->debug('Cached token for swift expired'); |
|
| 191 | + } else { |
|
| 192 | + $hasValidCachedToken = true; |
|
| 193 | + } |
|
| 194 | + } else { |
|
| 195 | + try { |
|
| 196 | + /** @var \OpenStack\Identity\v2\Models\Token $token */ |
|
| 197 | + $token = $authService->model(\OpenStack\Identity\v2\Models\Token::class, $cachedToken['token']); |
|
| 198 | + $now = new \DateTimeImmutable("now"); |
|
| 199 | + if ($token->expires > $now) { |
|
| 200 | + $hasValidCachedToken = true; |
|
| 201 | + $this->params['v2cachedToken'] = $token; |
|
| 202 | + $this->params['v2serviceUrl'] = $cachedToken['serviceUrl']; |
|
| 203 | + } else { |
|
| 204 | + $this->logger->debug('Cached token for swift expired'); |
|
| 205 | + } |
|
| 206 | + } catch (\Exception $e) { |
|
| 207 | + $this->logger->logException($e); |
|
| 208 | + } |
|
| 209 | + } |
|
| 210 | + } |
|
| 211 | 211 | |
| 212 | - if (!$hasValidCachedToken) { |
|
| 213 | - unset($this->params['cachedToken']); |
|
| 214 | - try { |
|
| 215 | - [$token, $serviceUrl] = $authService->authenticate($this->params); |
|
| 216 | - $this->cacheToken($token, $serviceUrl, $cacheKey); |
|
| 217 | - } catch (ConnectException $e) { |
|
| 218 | - throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e); |
|
| 219 | - } catch (ClientException $e) { |
|
| 220 | - $statusCode = $e->getResponse()->getStatusCode(); |
|
| 221 | - if ($statusCode === 404) { |
|
| 222 | - throw new StorageAuthException('Keystone not found, verify the keystone url', $e); |
|
| 223 | - } elseif ($statusCode === 412) { |
|
| 224 | - throw new StorageAuthException('Precondition failed, verify the keystone url', $e); |
|
| 225 | - } elseif ($statusCode === 401) { |
|
| 226 | - throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e); |
|
| 227 | - } else { |
|
| 228 | - throw new StorageAuthException('Unknown error', $e); |
|
| 229 | - } |
|
| 230 | - } catch (RequestException $e) { |
|
| 231 | - throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e); |
|
| 232 | - } |
|
| 233 | - } |
|
| 212 | + if (!$hasValidCachedToken) { |
|
| 213 | + unset($this->params['cachedToken']); |
|
| 214 | + try { |
|
| 215 | + [$token, $serviceUrl] = $authService->authenticate($this->params); |
|
| 216 | + $this->cacheToken($token, $serviceUrl, $cacheKey); |
|
| 217 | + } catch (ConnectException $e) { |
|
| 218 | + throw new StorageAuthException('Failed to connect to keystone, verify the keystone url', $e); |
|
| 219 | + } catch (ClientException $e) { |
|
| 220 | + $statusCode = $e->getResponse()->getStatusCode(); |
|
| 221 | + if ($statusCode === 404) { |
|
| 222 | + throw new StorageAuthException('Keystone not found, verify the keystone url', $e); |
|
| 223 | + } elseif ($statusCode === 412) { |
|
| 224 | + throw new StorageAuthException('Precondition failed, verify the keystone url', $e); |
|
| 225 | + } elseif ($statusCode === 401) { |
|
| 226 | + throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e); |
|
| 227 | + } else { |
|
| 228 | + throw new StorageAuthException('Unknown error', $e); |
|
| 229 | + } |
|
| 230 | + } catch (RequestException $e) { |
|
| 231 | + throw new StorageAuthException('Connection reset while connecting to keystone, verify the keystone url', $e); |
|
| 232 | + } |
|
| 233 | + } |
|
| 234 | 234 | |
| 235 | 235 | |
| 236 | - $client = new OpenStack($this->params); |
|
| 236 | + $client = new OpenStack($this->params); |
|
| 237 | 237 | |
| 238 | - return $client; |
|
| 239 | - } |
|
| 238 | + return $client; |
|
| 239 | + } |
|
| 240 | 240 | |
| 241 | - /** |
|
| 242 | - * @return \OpenStack\ObjectStore\v1\Models\Container |
|
| 243 | - * @throws StorageAuthException |
|
| 244 | - * @throws StorageNotAvailableException |
|
| 245 | - */ |
|
| 246 | - public function getContainer() { |
|
| 247 | - if (is_null($this->container)) { |
|
| 248 | - $this->container = $this->createContainer(); |
|
| 249 | - } |
|
| 241 | + /** |
|
| 242 | + * @return \OpenStack\ObjectStore\v1\Models\Container |
|
| 243 | + * @throws StorageAuthException |
|
| 244 | + * @throws StorageNotAvailableException |
|
| 245 | + */ |
|
| 246 | + public function getContainer() { |
|
| 247 | + if (is_null($this->container)) { |
|
| 248 | + $this->container = $this->createContainer(); |
|
| 249 | + } |
|
| 250 | 250 | |
| 251 | - return $this->container; |
|
| 252 | - } |
|
| 251 | + return $this->container; |
|
| 252 | + } |
|
| 253 | 253 | |
| 254 | - /** |
|
| 255 | - * @return \OpenStack\ObjectStore\v1\Models\Container |
|
| 256 | - * @throws StorageAuthException |
|
| 257 | - * @throws StorageNotAvailableException |
|
| 258 | - */ |
|
| 259 | - private function createContainer() { |
|
| 260 | - $client = $this->getClient(); |
|
| 261 | - $objectStoreService = $client->objectStoreV1(); |
|
| 254 | + /** |
|
| 255 | + * @return \OpenStack\ObjectStore\v1\Models\Container |
|
| 256 | + * @throws StorageAuthException |
|
| 257 | + * @throws StorageNotAvailableException |
|
| 258 | + */ |
|
| 259 | + private function createContainer() { |
|
| 260 | + $client = $this->getClient(); |
|
| 261 | + $objectStoreService = $client->objectStoreV1(); |
|
| 262 | 262 | |
| 263 | - $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true; |
|
| 264 | - try { |
|
| 265 | - $container = $objectStoreService->getContainer($this->params['container']); |
|
| 266 | - if ($autoCreate) { |
|
| 267 | - $container->getMetadata(); |
|
| 268 | - } |
|
| 269 | - return $container; |
|
| 270 | - } catch (BadResponseError $ex) { |
|
| 271 | - // if the container does not exist and autocreate is true try to create the container on the fly |
|
| 272 | - if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) { |
|
| 273 | - return $objectStoreService->createContainer([ |
|
| 274 | - 'name' => $this->params['container'] |
|
| 275 | - ]); |
|
| 276 | - } else { |
|
| 277 | - throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $ex); |
|
| 278 | - } |
|
| 279 | - } catch (ConnectException $e) { |
|
| 280 | - /** @var RequestInterface $request */ |
|
| 281 | - $request = $e->getRequest(); |
|
| 282 | - $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort(); |
|
| 283 | - \OC::$server->getLogger()->error("Can't connect to object storage server at $host"); |
|
| 284 | - throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e); |
|
| 285 | - } |
|
| 286 | - } |
|
| 263 | + $autoCreate = isset($this->params['autocreate']) && $this->params['autocreate'] === true; |
|
| 264 | + try { |
|
| 265 | + $container = $objectStoreService->getContainer($this->params['container']); |
|
| 266 | + if ($autoCreate) { |
|
| 267 | + $container->getMetadata(); |
|
| 268 | + } |
|
| 269 | + return $container; |
|
| 270 | + } catch (BadResponseError $ex) { |
|
| 271 | + // if the container does not exist and autocreate is true try to create the container on the fly |
|
| 272 | + if ($ex->getResponse()->getStatusCode() === 404 && $autoCreate) { |
|
| 273 | + return $objectStoreService->createContainer([ |
|
| 274 | + 'name' => $this->params['container'] |
|
| 275 | + ]); |
|
| 276 | + } else { |
|
| 277 | + throw new StorageNotAvailableException('Invalid response while trying to get container info', StorageNotAvailableException::STATUS_ERROR, $ex); |
|
| 278 | + } |
|
| 279 | + } catch (ConnectException $e) { |
|
| 280 | + /** @var RequestInterface $request */ |
|
| 281 | + $request = $e->getRequest(); |
|
| 282 | + $host = $request->getUri()->getHost() . ':' . $request->getUri()->getPort(); |
|
| 283 | + \OC::$server->getLogger()->error("Can't connect to object storage server at $host"); |
|
| 284 | + throw new StorageNotAvailableException("Can't connect to object storage server at $host", StorageNotAvailableException::STATUS_ERROR, $e); |
|
| 285 | + } |
|
| 286 | + } |
|
| 287 | 287 | } |
@@ -47,380 +47,380 @@ |
||
| 47 | 47 | * Cache mounts points per user in the cache so we can easilly look them up |
| 48 | 48 | */ |
| 49 | 49 | class UserMountCache implements IUserMountCache { |
| 50 | - /** |
|
| 51 | - * @var IDBConnection |
|
| 52 | - */ |
|
| 53 | - private $connection; |
|
| 54 | - |
|
| 55 | - /** |
|
| 56 | - * @var IUserManager |
|
| 57 | - */ |
|
| 58 | - private $userManager; |
|
| 59 | - |
|
| 60 | - /** |
|
| 61 | - * Cached mount info. |
|
| 62 | - * Map of $userId to ICachedMountInfo. |
|
| 63 | - * |
|
| 64 | - * @var ICache |
|
| 65 | - **/ |
|
| 66 | - private $mountsForUsers; |
|
| 67 | - |
|
| 68 | - /** |
|
| 69 | - * @var ILogger |
|
| 70 | - */ |
|
| 71 | - private $logger; |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * @var ICache |
|
| 75 | - */ |
|
| 76 | - private $cacheInfoCache; |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * UserMountCache constructor. |
|
| 80 | - * |
|
| 81 | - * @param IDBConnection $connection |
|
| 82 | - * @param IUserManager $userManager |
|
| 83 | - * @param ILogger $logger |
|
| 84 | - */ |
|
| 85 | - public function __construct(IDBConnection $connection, IUserManager $userManager, ILogger $logger) { |
|
| 86 | - $this->connection = $connection; |
|
| 87 | - $this->userManager = $userManager; |
|
| 88 | - $this->logger = $logger; |
|
| 89 | - $this->cacheInfoCache = new CappedMemoryCache(); |
|
| 90 | - $this->mountsForUsers = new CappedMemoryCache(); |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - public function registerMounts(IUser $user, array $mounts) { |
|
| 94 | - // filter out non-proper storages coming from unit tests |
|
| 95 | - $mounts = array_filter($mounts, function (IMountPoint $mount) { |
|
| 96 | - return $mount instanceof SharedMount || $mount->getStorage() && $mount->getStorage()->getCache(); |
|
| 97 | - }); |
|
| 98 | - /** @var ICachedMountInfo[] $newMounts */ |
|
| 99 | - $newMounts = array_map(function (IMountPoint $mount) use ($user) { |
|
| 100 | - // filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet) |
|
| 101 | - if ($mount->getStorageRootId() === -1) { |
|
| 102 | - return null; |
|
| 103 | - } else { |
|
| 104 | - return new LazyStorageMountInfo($user, $mount); |
|
| 105 | - } |
|
| 106 | - }, $mounts); |
|
| 107 | - $newMounts = array_values(array_filter($newMounts)); |
|
| 108 | - $newMountRootIds = array_map(function (ICachedMountInfo $mount) { |
|
| 109 | - return $mount->getRootId(); |
|
| 110 | - }, $newMounts); |
|
| 111 | - $newMounts = array_combine($newMountRootIds, $newMounts); |
|
| 112 | - |
|
| 113 | - $cachedMounts = $this->getMountsForUser($user); |
|
| 114 | - $cachedMountRootIds = array_map(function (ICachedMountInfo $mount) { |
|
| 115 | - return $mount->getRootId(); |
|
| 116 | - }, $cachedMounts); |
|
| 117 | - $cachedMounts = array_combine($cachedMountRootIds, $cachedMounts); |
|
| 118 | - |
|
| 119 | - $addedMounts = []; |
|
| 120 | - $removedMounts = []; |
|
| 121 | - |
|
| 122 | - foreach ($newMounts as $rootId => $newMount) { |
|
| 123 | - if (!isset($cachedMounts[$rootId])) { |
|
| 124 | - $addedMounts[] = $newMount; |
|
| 125 | - } |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - foreach ($cachedMounts as $rootId => $cachedMount) { |
|
| 129 | - if (!isset($newMounts[$rootId])) { |
|
| 130 | - $removedMounts[] = $cachedMount; |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - $changedMounts = $this->findChangedMounts($newMounts, $cachedMounts); |
|
| 135 | - |
|
| 136 | - foreach ($addedMounts as $mount) { |
|
| 137 | - $this->addToCache($mount); |
|
| 138 | - $this->mountsForUsers[$user->getUID()][] = $mount; |
|
| 139 | - } |
|
| 140 | - foreach ($removedMounts as $mount) { |
|
| 141 | - $this->removeFromCache($mount); |
|
| 142 | - $index = array_search($mount, $this->mountsForUsers[$user->getUID()]); |
|
| 143 | - unset($this->mountsForUsers[$user->getUID()][$index]); |
|
| 144 | - } |
|
| 145 | - foreach ($changedMounts as $mount) { |
|
| 146 | - $this->updateCachedMount($mount); |
|
| 147 | - } |
|
| 148 | - } |
|
| 149 | - |
|
| 150 | - /** |
|
| 151 | - * @param ICachedMountInfo[] $newMounts |
|
| 152 | - * @param ICachedMountInfo[] $cachedMounts |
|
| 153 | - * @return ICachedMountInfo[] |
|
| 154 | - */ |
|
| 155 | - private function findChangedMounts(array $newMounts, array $cachedMounts) { |
|
| 156 | - $new = []; |
|
| 157 | - foreach ($newMounts as $mount) { |
|
| 158 | - $new[$mount->getRootId()] = $mount; |
|
| 159 | - } |
|
| 160 | - $changed = []; |
|
| 161 | - foreach ($cachedMounts as $cachedMount) { |
|
| 162 | - $rootId = $cachedMount->getRootId(); |
|
| 163 | - if (isset($new[$rootId])) { |
|
| 164 | - $newMount = $new[$rootId]; |
|
| 165 | - if ( |
|
| 166 | - $newMount->getMountPoint() !== $cachedMount->getMountPoint() || |
|
| 167 | - $newMount->getStorageId() !== $cachedMount->getStorageId() || |
|
| 168 | - $newMount->getMountId() !== $cachedMount->getMountId() |
|
| 169 | - ) { |
|
| 170 | - $changed[] = $newMount; |
|
| 171 | - } |
|
| 172 | - } |
|
| 173 | - } |
|
| 174 | - return $changed; |
|
| 175 | - } |
|
| 176 | - |
|
| 177 | - private function addToCache(ICachedMountInfo $mount) { |
|
| 178 | - if ($mount->getStorageId() !== -1) { |
|
| 179 | - $this->connection->insertIfNotExist('*PREFIX*mounts', [ |
|
| 180 | - 'storage_id' => $mount->getStorageId(), |
|
| 181 | - 'root_id' => $mount->getRootId(), |
|
| 182 | - 'user_id' => $mount->getUser()->getUID(), |
|
| 183 | - 'mount_point' => $mount->getMountPoint(), |
|
| 184 | - 'mount_id' => $mount->getMountId() |
|
| 185 | - ], ['root_id', 'user_id']); |
|
| 186 | - } else { |
|
| 187 | - // in some cases this is legitimate, like orphaned shares |
|
| 188 | - $this->logger->debug('Could not get storage info for mount at ' . $mount->getMountPoint()); |
|
| 189 | - } |
|
| 190 | - } |
|
| 191 | - |
|
| 192 | - private function updateCachedMount(ICachedMountInfo $mount) { |
|
| 193 | - $builder = $this->connection->getQueryBuilder(); |
|
| 194 | - |
|
| 195 | - $query = $builder->update('mounts') |
|
| 196 | - ->set('storage_id', $builder->createNamedParameter($mount->getStorageId())) |
|
| 197 | - ->set('mount_point', $builder->createNamedParameter($mount->getMountPoint())) |
|
| 198 | - ->set('mount_id', $builder->createNamedParameter($mount->getMountId(), IQueryBuilder::PARAM_INT)) |
|
| 199 | - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) |
|
| 200 | - ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT))); |
|
| 201 | - |
|
| 202 | - $query->execute(); |
|
| 203 | - } |
|
| 204 | - |
|
| 205 | - private function removeFromCache(ICachedMountInfo $mount) { |
|
| 206 | - $builder = $this->connection->getQueryBuilder(); |
|
| 207 | - |
|
| 208 | - $query = $builder->delete('mounts') |
|
| 209 | - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) |
|
| 210 | - ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT))); |
|
| 211 | - $query->execute(); |
|
| 212 | - } |
|
| 213 | - |
|
| 214 | - private function dbRowToMountInfo(array $row) { |
|
| 215 | - $user = $this->userManager->get($row['user_id']); |
|
| 216 | - if (is_null($user)) { |
|
| 217 | - return null; |
|
| 218 | - } |
|
| 219 | - $mount_id = $row['mount_id']; |
|
| 220 | - if (!is_null($mount_id)) { |
|
| 221 | - $mount_id = (int)$mount_id; |
|
| 222 | - } |
|
| 223 | - return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $mount_id, isset($row['path']) ? $row['path'] : ''); |
|
| 224 | - } |
|
| 225 | - |
|
| 226 | - /** |
|
| 227 | - * @param IUser $user |
|
| 228 | - * @return ICachedMountInfo[] |
|
| 229 | - */ |
|
| 230 | - public function getMountsForUser(IUser $user) { |
|
| 231 | - if (!isset($this->mountsForUsers[$user->getUID()])) { |
|
| 232 | - $builder = $this->connection->getQueryBuilder(); |
|
| 233 | - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 234 | - ->from('mounts', 'm') |
|
| 235 | - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 236 | - ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID()))); |
|
| 237 | - |
|
| 238 | - $result = $query->execute(); |
|
| 239 | - $rows = $result->fetchAll(); |
|
| 240 | - $result->closeCursor(); |
|
| 241 | - |
|
| 242 | - $this->mountsForUsers[$user->getUID()] = array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 243 | - } |
|
| 244 | - return $this->mountsForUsers[$user->getUID()]; |
|
| 245 | - } |
|
| 246 | - |
|
| 247 | - /** |
|
| 248 | - * @param int $numericStorageId |
|
| 249 | - * @param string|null $user limit the results to a single user |
|
| 250 | - * @return CachedMountInfo[] |
|
| 251 | - */ |
|
| 252 | - public function getMountsForStorageId($numericStorageId, $user = null) { |
|
| 253 | - $builder = $this->connection->getQueryBuilder(); |
|
| 254 | - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 255 | - ->from('mounts', 'm') |
|
| 256 | - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 257 | - ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT))); |
|
| 258 | - |
|
| 259 | - if ($user) { |
|
| 260 | - $query->andWhere($builder->expr()->eq('user_id', $builder->createPositionalParameter($user))); |
|
| 261 | - } |
|
| 262 | - |
|
| 263 | - $result = $query->execute(); |
|
| 264 | - $rows = $result->fetchAll(); |
|
| 265 | - $result->closeCursor(); |
|
| 266 | - |
|
| 267 | - return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 268 | - } |
|
| 269 | - |
|
| 270 | - /** |
|
| 271 | - * @param int $rootFileId |
|
| 272 | - * @return CachedMountInfo[] |
|
| 273 | - */ |
|
| 274 | - public function getMountsForRootId($rootFileId) { |
|
| 275 | - $builder = $this->connection->getQueryBuilder(); |
|
| 276 | - $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 277 | - ->from('mounts', 'm') |
|
| 278 | - ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 279 | - ->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT))); |
|
| 280 | - |
|
| 281 | - $result = $query->execute(); |
|
| 282 | - $rows = $result->fetchAll(); |
|
| 283 | - $result->closeCursor(); |
|
| 284 | - |
|
| 285 | - return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 286 | - } |
|
| 287 | - |
|
| 288 | - /** |
|
| 289 | - * @param $fileId |
|
| 290 | - * @return array |
|
| 291 | - * @throws \OCP\Files\NotFoundException |
|
| 292 | - */ |
|
| 293 | - private function getCacheInfoFromFileId($fileId) { |
|
| 294 | - if (!isset($this->cacheInfoCache[$fileId])) { |
|
| 295 | - $builder = $this->connection->getQueryBuilder(); |
|
| 296 | - $query = $builder->select('storage', 'path', 'mimetype') |
|
| 297 | - ->from('filecache') |
|
| 298 | - ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); |
|
| 299 | - |
|
| 300 | - $result = $query->execute(); |
|
| 301 | - $row = $result->fetch(); |
|
| 302 | - $result->closeCursor(); |
|
| 303 | - |
|
| 304 | - if (is_array($row)) { |
|
| 305 | - $this->cacheInfoCache[$fileId] = [ |
|
| 306 | - (int)$row['storage'], |
|
| 307 | - $row['path'], |
|
| 308 | - (int)$row['mimetype'] |
|
| 309 | - ]; |
|
| 310 | - } else { |
|
| 311 | - throw new NotFoundException('File with id "' . $fileId . '" not found'); |
|
| 312 | - } |
|
| 313 | - } |
|
| 314 | - return $this->cacheInfoCache[$fileId]; |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - /** |
|
| 318 | - * @param int $fileId |
|
| 319 | - * @param string|null $user optionally restrict the results to a single user |
|
| 320 | - * @return ICachedMountFileInfo[] |
|
| 321 | - * @since 9.0.0 |
|
| 322 | - */ |
|
| 323 | - public function getMountsForFileId($fileId, $user = null) { |
|
| 324 | - try { |
|
| 325 | - [$storageId, $internalPath] = $this->getCacheInfoFromFileId($fileId); |
|
| 326 | - } catch (NotFoundException $e) { |
|
| 327 | - return []; |
|
| 328 | - } |
|
| 329 | - $mountsForStorage = $this->getMountsForStorageId($storageId, $user); |
|
| 330 | - |
|
| 331 | - // filter mounts that are from the same storage but a different directory |
|
| 332 | - $filteredMounts = array_filter($mountsForStorage, function (ICachedMountInfo $mount) use ($internalPath, $fileId) { |
|
| 333 | - if ($fileId === $mount->getRootId()) { |
|
| 334 | - return true; |
|
| 335 | - } |
|
| 336 | - $internalMountPath = $mount->getRootInternalPath(); |
|
| 337 | - |
|
| 338 | - return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/'; |
|
| 339 | - }); |
|
| 340 | - |
|
| 341 | - return array_map(function (ICachedMountInfo $mount) use ($internalPath) { |
|
| 342 | - return new CachedMountFileInfo( |
|
| 343 | - $mount->getUser(), |
|
| 344 | - $mount->getStorageId(), |
|
| 345 | - $mount->getRootId(), |
|
| 346 | - $mount->getMountPoint(), |
|
| 347 | - $mount->getMountId(), |
|
| 348 | - $mount->getRootInternalPath(), |
|
| 349 | - $internalPath |
|
| 350 | - ); |
|
| 351 | - }, $filteredMounts); |
|
| 352 | - } |
|
| 353 | - |
|
| 354 | - /** |
|
| 355 | - * Remove all cached mounts for a user |
|
| 356 | - * |
|
| 357 | - * @param IUser $user |
|
| 358 | - */ |
|
| 359 | - public function removeUserMounts(IUser $user) { |
|
| 360 | - $builder = $this->connection->getQueryBuilder(); |
|
| 361 | - |
|
| 362 | - $query = $builder->delete('mounts') |
|
| 363 | - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID()))); |
|
| 364 | - $query->execute(); |
|
| 365 | - } |
|
| 366 | - |
|
| 367 | - public function removeUserStorageMount($storageId, $userId) { |
|
| 368 | - $builder = $this->connection->getQueryBuilder(); |
|
| 369 | - |
|
| 370 | - $query = $builder->delete('mounts') |
|
| 371 | - ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId))) |
|
| 372 | - ->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))); |
|
| 373 | - $query->execute(); |
|
| 374 | - } |
|
| 375 | - |
|
| 376 | - public function remoteStorageMounts($storageId) { |
|
| 377 | - $builder = $this->connection->getQueryBuilder(); |
|
| 378 | - |
|
| 379 | - $query = $builder->delete('mounts') |
|
| 380 | - ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))); |
|
| 381 | - $query->execute(); |
|
| 382 | - } |
|
| 383 | - |
|
| 384 | - /** |
|
| 385 | - * @param array $users |
|
| 386 | - * @return array |
|
| 387 | - */ |
|
| 388 | - public function getUsedSpaceForUsers(array $users) { |
|
| 389 | - $builder = $this->connection->getQueryBuilder(); |
|
| 390 | - |
|
| 391 | - $slash = $builder->createNamedParameter('/'); |
|
| 392 | - |
|
| 393 | - $mountPoint = $builder->func()->concat( |
|
| 394 | - $builder->func()->concat($slash, 'user_id'), |
|
| 395 | - $slash |
|
| 396 | - ); |
|
| 397 | - |
|
| 398 | - $userIds = array_map(function (IUser $user) { |
|
| 399 | - return $user->getUID(); |
|
| 400 | - }, $users); |
|
| 401 | - |
|
| 402 | - $query = $builder->select('m.user_id', 'f.size') |
|
| 403 | - ->from('mounts', 'm') |
|
| 404 | - ->innerJoin('m', 'filecache', 'f', |
|
| 405 | - $builder->expr()->andX( |
|
| 406 | - $builder->expr()->eq('m.storage_id', 'f.storage'), |
|
| 407 | - $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files'))) |
|
| 408 | - )) |
|
| 409 | - ->where($builder->expr()->eq('m.mount_point', $mountPoint)) |
|
| 410 | - ->andWhere($builder->expr()->in('m.user_id', $builder->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY))); |
|
| 411 | - |
|
| 412 | - $result = $query->execute(); |
|
| 413 | - |
|
| 414 | - $results = []; |
|
| 415 | - while ($row = $result->fetch()) { |
|
| 416 | - $results[$row['user_id']] = $row['size']; |
|
| 417 | - } |
|
| 418 | - $result->closeCursor(); |
|
| 419 | - return $results; |
|
| 420 | - } |
|
| 421 | - |
|
| 422 | - public function clear(): void { |
|
| 423 | - $this->cacheInfoCache = new CappedMemoryCache(); |
|
| 424 | - $this->mountsForUsers = new CappedMemoryCache(); |
|
| 425 | - } |
|
| 50 | + /** |
|
| 51 | + * @var IDBConnection |
|
| 52 | + */ |
|
| 53 | + private $connection; |
|
| 54 | + |
|
| 55 | + /** |
|
| 56 | + * @var IUserManager |
|
| 57 | + */ |
|
| 58 | + private $userManager; |
|
| 59 | + |
|
| 60 | + /** |
|
| 61 | + * Cached mount info. |
|
| 62 | + * Map of $userId to ICachedMountInfo. |
|
| 63 | + * |
|
| 64 | + * @var ICache |
|
| 65 | + **/ |
|
| 66 | + private $mountsForUsers; |
|
| 67 | + |
|
| 68 | + /** |
|
| 69 | + * @var ILogger |
|
| 70 | + */ |
|
| 71 | + private $logger; |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * @var ICache |
|
| 75 | + */ |
|
| 76 | + private $cacheInfoCache; |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * UserMountCache constructor. |
|
| 80 | + * |
|
| 81 | + * @param IDBConnection $connection |
|
| 82 | + * @param IUserManager $userManager |
|
| 83 | + * @param ILogger $logger |
|
| 84 | + */ |
|
| 85 | + public function __construct(IDBConnection $connection, IUserManager $userManager, ILogger $logger) { |
|
| 86 | + $this->connection = $connection; |
|
| 87 | + $this->userManager = $userManager; |
|
| 88 | + $this->logger = $logger; |
|
| 89 | + $this->cacheInfoCache = new CappedMemoryCache(); |
|
| 90 | + $this->mountsForUsers = new CappedMemoryCache(); |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + public function registerMounts(IUser $user, array $mounts) { |
|
| 94 | + // filter out non-proper storages coming from unit tests |
|
| 95 | + $mounts = array_filter($mounts, function (IMountPoint $mount) { |
|
| 96 | + return $mount instanceof SharedMount || $mount->getStorage() && $mount->getStorage()->getCache(); |
|
| 97 | + }); |
|
| 98 | + /** @var ICachedMountInfo[] $newMounts */ |
|
| 99 | + $newMounts = array_map(function (IMountPoint $mount) use ($user) { |
|
| 100 | + // filter out any storages which aren't scanned yet since we aren't interested in files from those storages (yet) |
|
| 101 | + if ($mount->getStorageRootId() === -1) { |
|
| 102 | + return null; |
|
| 103 | + } else { |
|
| 104 | + return new LazyStorageMountInfo($user, $mount); |
|
| 105 | + } |
|
| 106 | + }, $mounts); |
|
| 107 | + $newMounts = array_values(array_filter($newMounts)); |
|
| 108 | + $newMountRootIds = array_map(function (ICachedMountInfo $mount) { |
|
| 109 | + return $mount->getRootId(); |
|
| 110 | + }, $newMounts); |
|
| 111 | + $newMounts = array_combine($newMountRootIds, $newMounts); |
|
| 112 | + |
|
| 113 | + $cachedMounts = $this->getMountsForUser($user); |
|
| 114 | + $cachedMountRootIds = array_map(function (ICachedMountInfo $mount) { |
|
| 115 | + return $mount->getRootId(); |
|
| 116 | + }, $cachedMounts); |
|
| 117 | + $cachedMounts = array_combine($cachedMountRootIds, $cachedMounts); |
|
| 118 | + |
|
| 119 | + $addedMounts = []; |
|
| 120 | + $removedMounts = []; |
|
| 121 | + |
|
| 122 | + foreach ($newMounts as $rootId => $newMount) { |
|
| 123 | + if (!isset($cachedMounts[$rootId])) { |
|
| 124 | + $addedMounts[] = $newMount; |
|
| 125 | + } |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + foreach ($cachedMounts as $rootId => $cachedMount) { |
|
| 129 | + if (!isset($newMounts[$rootId])) { |
|
| 130 | + $removedMounts[] = $cachedMount; |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + $changedMounts = $this->findChangedMounts($newMounts, $cachedMounts); |
|
| 135 | + |
|
| 136 | + foreach ($addedMounts as $mount) { |
|
| 137 | + $this->addToCache($mount); |
|
| 138 | + $this->mountsForUsers[$user->getUID()][] = $mount; |
|
| 139 | + } |
|
| 140 | + foreach ($removedMounts as $mount) { |
|
| 141 | + $this->removeFromCache($mount); |
|
| 142 | + $index = array_search($mount, $this->mountsForUsers[$user->getUID()]); |
|
| 143 | + unset($this->mountsForUsers[$user->getUID()][$index]); |
|
| 144 | + } |
|
| 145 | + foreach ($changedMounts as $mount) { |
|
| 146 | + $this->updateCachedMount($mount); |
|
| 147 | + } |
|
| 148 | + } |
|
| 149 | + |
|
| 150 | + /** |
|
| 151 | + * @param ICachedMountInfo[] $newMounts |
|
| 152 | + * @param ICachedMountInfo[] $cachedMounts |
|
| 153 | + * @return ICachedMountInfo[] |
|
| 154 | + */ |
|
| 155 | + private function findChangedMounts(array $newMounts, array $cachedMounts) { |
|
| 156 | + $new = []; |
|
| 157 | + foreach ($newMounts as $mount) { |
|
| 158 | + $new[$mount->getRootId()] = $mount; |
|
| 159 | + } |
|
| 160 | + $changed = []; |
|
| 161 | + foreach ($cachedMounts as $cachedMount) { |
|
| 162 | + $rootId = $cachedMount->getRootId(); |
|
| 163 | + if (isset($new[$rootId])) { |
|
| 164 | + $newMount = $new[$rootId]; |
|
| 165 | + if ( |
|
| 166 | + $newMount->getMountPoint() !== $cachedMount->getMountPoint() || |
|
| 167 | + $newMount->getStorageId() !== $cachedMount->getStorageId() || |
|
| 168 | + $newMount->getMountId() !== $cachedMount->getMountId() |
|
| 169 | + ) { |
|
| 170 | + $changed[] = $newMount; |
|
| 171 | + } |
|
| 172 | + } |
|
| 173 | + } |
|
| 174 | + return $changed; |
|
| 175 | + } |
|
| 176 | + |
|
| 177 | + private function addToCache(ICachedMountInfo $mount) { |
|
| 178 | + if ($mount->getStorageId() !== -1) { |
|
| 179 | + $this->connection->insertIfNotExist('*PREFIX*mounts', [ |
|
| 180 | + 'storage_id' => $mount->getStorageId(), |
|
| 181 | + 'root_id' => $mount->getRootId(), |
|
| 182 | + 'user_id' => $mount->getUser()->getUID(), |
|
| 183 | + 'mount_point' => $mount->getMountPoint(), |
|
| 184 | + 'mount_id' => $mount->getMountId() |
|
| 185 | + ], ['root_id', 'user_id']); |
|
| 186 | + } else { |
|
| 187 | + // in some cases this is legitimate, like orphaned shares |
|
| 188 | + $this->logger->debug('Could not get storage info for mount at ' . $mount->getMountPoint()); |
|
| 189 | + } |
|
| 190 | + } |
|
| 191 | + |
|
| 192 | + private function updateCachedMount(ICachedMountInfo $mount) { |
|
| 193 | + $builder = $this->connection->getQueryBuilder(); |
|
| 194 | + |
|
| 195 | + $query = $builder->update('mounts') |
|
| 196 | + ->set('storage_id', $builder->createNamedParameter($mount->getStorageId())) |
|
| 197 | + ->set('mount_point', $builder->createNamedParameter($mount->getMountPoint())) |
|
| 198 | + ->set('mount_id', $builder->createNamedParameter($mount->getMountId(), IQueryBuilder::PARAM_INT)) |
|
| 199 | + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) |
|
| 200 | + ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT))); |
|
| 201 | + |
|
| 202 | + $query->execute(); |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | + private function removeFromCache(ICachedMountInfo $mount) { |
|
| 206 | + $builder = $this->connection->getQueryBuilder(); |
|
| 207 | + |
|
| 208 | + $query = $builder->delete('mounts') |
|
| 209 | + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($mount->getUser()->getUID()))) |
|
| 210 | + ->andWhere($builder->expr()->eq('root_id', $builder->createNamedParameter($mount->getRootId(), IQueryBuilder::PARAM_INT))); |
|
| 211 | + $query->execute(); |
|
| 212 | + } |
|
| 213 | + |
|
| 214 | + private function dbRowToMountInfo(array $row) { |
|
| 215 | + $user = $this->userManager->get($row['user_id']); |
|
| 216 | + if (is_null($user)) { |
|
| 217 | + return null; |
|
| 218 | + } |
|
| 219 | + $mount_id = $row['mount_id']; |
|
| 220 | + if (!is_null($mount_id)) { |
|
| 221 | + $mount_id = (int)$mount_id; |
|
| 222 | + } |
|
| 223 | + return new CachedMountInfo($user, (int)$row['storage_id'], (int)$row['root_id'], $row['mount_point'], $mount_id, isset($row['path']) ? $row['path'] : ''); |
|
| 224 | + } |
|
| 225 | + |
|
| 226 | + /** |
|
| 227 | + * @param IUser $user |
|
| 228 | + * @return ICachedMountInfo[] |
|
| 229 | + */ |
|
| 230 | + public function getMountsForUser(IUser $user) { |
|
| 231 | + if (!isset($this->mountsForUsers[$user->getUID()])) { |
|
| 232 | + $builder = $this->connection->getQueryBuilder(); |
|
| 233 | + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 234 | + ->from('mounts', 'm') |
|
| 235 | + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 236 | + ->where($builder->expr()->eq('user_id', $builder->createPositionalParameter($user->getUID()))); |
|
| 237 | + |
|
| 238 | + $result = $query->execute(); |
|
| 239 | + $rows = $result->fetchAll(); |
|
| 240 | + $result->closeCursor(); |
|
| 241 | + |
|
| 242 | + $this->mountsForUsers[$user->getUID()] = array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 243 | + } |
|
| 244 | + return $this->mountsForUsers[$user->getUID()]; |
|
| 245 | + } |
|
| 246 | + |
|
| 247 | + /** |
|
| 248 | + * @param int $numericStorageId |
|
| 249 | + * @param string|null $user limit the results to a single user |
|
| 250 | + * @return CachedMountInfo[] |
|
| 251 | + */ |
|
| 252 | + public function getMountsForStorageId($numericStorageId, $user = null) { |
|
| 253 | + $builder = $this->connection->getQueryBuilder(); |
|
| 254 | + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 255 | + ->from('mounts', 'm') |
|
| 256 | + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 257 | + ->where($builder->expr()->eq('storage_id', $builder->createPositionalParameter($numericStorageId, IQueryBuilder::PARAM_INT))); |
|
| 258 | + |
|
| 259 | + if ($user) { |
|
| 260 | + $query->andWhere($builder->expr()->eq('user_id', $builder->createPositionalParameter($user))); |
|
| 261 | + } |
|
| 262 | + |
|
| 263 | + $result = $query->execute(); |
|
| 264 | + $rows = $result->fetchAll(); |
|
| 265 | + $result->closeCursor(); |
|
| 266 | + |
|
| 267 | + return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 268 | + } |
|
| 269 | + |
|
| 270 | + /** |
|
| 271 | + * @param int $rootFileId |
|
| 272 | + * @return CachedMountInfo[] |
|
| 273 | + */ |
|
| 274 | + public function getMountsForRootId($rootFileId) { |
|
| 275 | + $builder = $this->connection->getQueryBuilder(); |
|
| 276 | + $query = $builder->select('storage_id', 'root_id', 'user_id', 'mount_point', 'mount_id', 'f.path') |
|
| 277 | + ->from('mounts', 'm') |
|
| 278 | + ->innerJoin('m', 'filecache', 'f', $builder->expr()->eq('m.root_id', 'f.fileid')) |
|
| 279 | + ->where($builder->expr()->eq('root_id', $builder->createPositionalParameter($rootFileId, IQueryBuilder::PARAM_INT))); |
|
| 280 | + |
|
| 281 | + $result = $query->execute(); |
|
| 282 | + $rows = $result->fetchAll(); |
|
| 283 | + $result->closeCursor(); |
|
| 284 | + |
|
| 285 | + return array_filter(array_map([$this, 'dbRowToMountInfo'], $rows)); |
|
| 286 | + } |
|
| 287 | + |
|
| 288 | + /** |
|
| 289 | + * @param $fileId |
|
| 290 | + * @return array |
|
| 291 | + * @throws \OCP\Files\NotFoundException |
|
| 292 | + */ |
|
| 293 | + private function getCacheInfoFromFileId($fileId) { |
|
| 294 | + if (!isset($this->cacheInfoCache[$fileId])) { |
|
| 295 | + $builder = $this->connection->getQueryBuilder(); |
|
| 296 | + $query = $builder->select('storage', 'path', 'mimetype') |
|
| 297 | + ->from('filecache') |
|
| 298 | + ->where($builder->expr()->eq('fileid', $builder->createNamedParameter($fileId, IQueryBuilder::PARAM_INT))); |
|
| 299 | + |
|
| 300 | + $result = $query->execute(); |
|
| 301 | + $row = $result->fetch(); |
|
| 302 | + $result->closeCursor(); |
|
| 303 | + |
|
| 304 | + if (is_array($row)) { |
|
| 305 | + $this->cacheInfoCache[$fileId] = [ |
|
| 306 | + (int)$row['storage'], |
|
| 307 | + $row['path'], |
|
| 308 | + (int)$row['mimetype'] |
|
| 309 | + ]; |
|
| 310 | + } else { |
|
| 311 | + throw new NotFoundException('File with id "' . $fileId . '" not found'); |
|
| 312 | + } |
|
| 313 | + } |
|
| 314 | + return $this->cacheInfoCache[$fileId]; |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + /** |
|
| 318 | + * @param int $fileId |
|
| 319 | + * @param string|null $user optionally restrict the results to a single user |
|
| 320 | + * @return ICachedMountFileInfo[] |
|
| 321 | + * @since 9.0.0 |
|
| 322 | + */ |
|
| 323 | + public function getMountsForFileId($fileId, $user = null) { |
|
| 324 | + try { |
|
| 325 | + [$storageId, $internalPath] = $this->getCacheInfoFromFileId($fileId); |
|
| 326 | + } catch (NotFoundException $e) { |
|
| 327 | + return []; |
|
| 328 | + } |
|
| 329 | + $mountsForStorage = $this->getMountsForStorageId($storageId, $user); |
|
| 330 | + |
|
| 331 | + // filter mounts that are from the same storage but a different directory |
|
| 332 | + $filteredMounts = array_filter($mountsForStorage, function (ICachedMountInfo $mount) use ($internalPath, $fileId) { |
|
| 333 | + if ($fileId === $mount->getRootId()) { |
|
| 334 | + return true; |
|
| 335 | + } |
|
| 336 | + $internalMountPath = $mount->getRootInternalPath(); |
|
| 337 | + |
|
| 338 | + return $internalMountPath === '' || substr($internalPath, 0, strlen($internalMountPath) + 1) === $internalMountPath . '/'; |
|
| 339 | + }); |
|
| 340 | + |
|
| 341 | + return array_map(function (ICachedMountInfo $mount) use ($internalPath) { |
|
| 342 | + return new CachedMountFileInfo( |
|
| 343 | + $mount->getUser(), |
|
| 344 | + $mount->getStorageId(), |
|
| 345 | + $mount->getRootId(), |
|
| 346 | + $mount->getMountPoint(), |
|
| 347 | + $mount->getMountId(), |
|
| 348 | + $mount->getRootInternalPath(), |
|
| 349 | + $internalPath |
|
| 350 | + ); |
|
| 351 | + }, $filteredMounts); |
|
| 352 | + } |
|
| 353 | + |
|
| 354 | + /** |
|
| 355 | + * Remove all cached mounts for a user |
|
| 356 | + * |
|
| 357 | + * @param IUser $user |
|
| 358 | + */ |
|
| 359 | + public function removeUserMounts(IUser $user) { |
|
| 360 | + $builder = $this->connection->getQueryBuilder(); |
|
| 361 | + |
|
| 362 | + $query = $builder->delete('mounts') |
|
| 363 | + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($user->getUID()))); |
|
| 364 | + $query->execute(); |
|
| 365 | + } |
|
| 366 | + |
|
| 367 | + public function removeUserStorageMount($storageId, $userId) { |
|
| 368 | + $builder = $this->connection->getQueryBuilder(); |
|
| 369 | + |
|
| 370 | + $query = $builder->delete('mounts') |
|
| 371 | + ->where($builder->expr()->eq('user_id', $builder->createNamedParameter($userId))) |
|
| 372 | + ->andWhere($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))); |
|
| 373 | + $query->execute(); |
|
| 374 | + } |
|
| 375 | + |
|
| 376 | + public function remoteStorageMounts($storageId) { |
|
| 377 | + $builder = $this->connection->getQueryBuilder(); |
|
| 378 | + |
|
| 379 | + $query = $builder->delete('mounts') |
|
| 380 | + ->where($builder->expr()->eq('storage_id', $builder->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))); |
|
| 381 | + $query->execute(); |
|
| 382 | + } |
|
| 383 | + |
|
| 384 | + /** |
|
| 385 | + * @param array $users |
|
| 386 | + * @return array |
|
| 387 | + */ |
|
| 388 | + public function getUsedSpaceForUsers(array $users) { |
|
| 389 | + $builder = $this->connection->getQueryBuilder(); |
|
| 390 | + |
|
| 391 | + $slash = $builder->createNamedParameter('/'); |
|
| 392 | + |
|
| 393 | + $mountPoint = $builder->func()->concat( |
|
| 394 | + $builder->func()->concat($slash, 'user_id'), |
|
| 395 | + $slash |
|
| 396 | + ); |
|
| 397 | + |
|
| 398 | + $userIds = array_map(function (IUser $user) { |
|
| 399 | + return $user->getUID(); |
|
| 400 | + }, $users); |
|
| 401 | + |
|
| 402 | + $query = $builder->select('m.user_id', 'f.size') |
|
| 403 | + ->from('mounts', 'm') |
|
| 404 | + ->innerJoin('m', 'filecache', 'f', |
|
| 405 | + $builder->expr()->andX( |
|
| 406 | + $builder->expr()->eq('m.storage_id', 'f.storage'), |
|
| 407 | + $builder->expr()->eq('f.path_hash', $builder->createNamedParameter(md5('files'))) |
|
| 408 | + )) |
|
| 409 | + ->where($builder->expr()->eq('m.mount_point', $mountPoint)) |
|
| 410 | + ->andWhere($builder->expr()->in('m.user_id', $builder->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY))); |
|
| 411 | + |
|
| 412 | + $result = $query->execute(); |
|
| 413 | + |
|
| 414 | + $results = []; |
|
| 415 | + while ($row = $result->fetch()) { |
|
| 416 | + $results[$row['user_id']] = $row['size']; |
|
| 417 | + } |
|
| 418 | + $result->closeCursor(); |
|
| 419 | + return $results; |
|
| 420 | + } |
|
| 421 | + |
|
| 422 | + public function clear(): void { |
|
| 423 | + $this->cacheInfoCache = new CappedMemoryCache(); |
|
| 424 | + $this->mountsForUsers = new CappedMemoryCache(); |
|
| 425 | + } |
|
| 426 | 426 | } |
@@ -37,190 +37,190 @@ |
||
| 37 | 37 | * Tools for transforming search queries into database queries |
| 38 | 38 | */ |
| 39 | 39 | class QuerySearchHelper { |
| 40 | - protected static $searchOperatorMap = [ |
|
| 41 | - ISearchComparison::COMPARE_LIKE => 'iLike', |
|
| 42 | - ISearchComparison::COMPARE_EQUAL => 'eq', |
|
| 43 | - ISearchComparison::COMPARE_GREATER_THAN => 'gt', |
|
| 44 | - ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte', |
|
| 45 | - ISearchComparison::COMPARE_LESS_THAN => 'lt', |
|
| 46 | - ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte' |
|
| 47 | - ]; |
|
| 48 | - |
|
| 49 | - protected static $searchOperatorNegativeMap = [ |
|
| 50 | - ISearchComparison::COMPARE_LIKE => 'notLike', |
|
| 51 | - ISearchComparison::COMPARE_EQUAL => 'neq', |
|
| 52 | - ISearchComparison::COMPARE_GREATER_THAN => 'lte', |
|
| 53 | - ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt', |
|
| 54 | - ISearchComparison::COMPARE_LESS_THAN => 'gte', |
|
| 55 | - ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt' |
|
| 56 | - ]; |
|
| 57 | - |
|
| 58 | - public const TAG_FAVORITE = '_$!<Favorite>!$_'; |
|
| 59 | - |
|
| 60 | - /** @var IMimeTypeLoader */ |
|
| 61 | - private $mimetypeLoader; |
|
| 62 | - |
|
| 63 | - /** |
|
| 64 | - * QuerySearchUtil constructor. |
|
| 65 | - * |
|
| 66 | - * @param IMimeTypeLoader $mimetypeLoader |
|
| 67 | - */ |
|
| 68 | - public function __construct(IMimeTypeLoader $mimetypeLoader) { |
|
| 69 | - $this->mimetypeLoader = $mimetypeLoader; |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - /** |
|
| 73 | - * Whether or not the tag tables should be joined to complete the search |
|
| 74 | - * |
|
| 75 | - * @param ISearchOperator $operator |
|
| 76 | - * @return boolean |
|
| 77 | - */ |
|
| 78 | - public function shouldJoinTags(ISearchOperator $operator) { |
|
| 79 | - if ($operator instanceof ISearchBinaryOperator) { |
|
| 80 | - return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) { |
|
| 81 | - return $shouldJoin || $this->shouldJoinTags($operator); |
|
| 82 | - }, false); |
|
| 83 | - } elseif ($operator instanceof ISearchComparison) { |
|
| 84 | - return $operator->getField() === 'tagname' || $operator->getField() === 'favorite'; |
|
| 85 | - } |
|
| 86 | - return false; |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - /** |
|
| 90 | - * @param IQueryBuilder $builder |
|
| 91 | - * @param ISearchOperator $operator |
|
| 92 | - */ |
|
| 93 | - public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) { |
|
| 94 | - return array_filter(array_map(function ($operator) use ($builder) { |
|
| 95 | - return $this->searchOperatorToDBExpr($builder, $operator); |
|
| 96 | - }, $operators)); |
|
| 97 | - } |
|
| 98 | - |
|
| 99 | - public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) { |
|
| 100 | - $expr = $builder->expr(); |
|
| 101 | - if ($operator instanceof ISearchBinaryOperator) { |
|
| 102 | - if (count($operator->getArguments()) === 0) { |
|
| 103 | - return null; |
|
| 104 | - } |
|
| 105 | - |
|
| 106 | - switch ($operator->getType()) { |
|
| 107 | - case ISearchBinaryOperator::OPERATOR_NOT: |
|
| 108 | - $negativeOperator = $operator->getArguments()[0]; |
|
| 109 | - if ($negativeOperator instanceof ISearchComparison) { |
|
| 110 | - return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap); |
|
| 111 | - } else { |
|
| 112 | - throw new \InvalidArgumentException('Binary operators inside "not" is not supported'); |
|
| 113 | - } |
|
| 114 | - // no break |
|
| 115 | - case ISearchBinaryOperator::OPERATOR_AND: |
|
| 116 | - return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments())); |
|
| 117 | - case ISearchBinaryOperator::OPERATOR_OR: |
|
| 118 | - return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments())); |
|
| 119 | - default: |
|
| 120 | - throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType()); |
|
| 121 | - } |
|
| 122 | - } elseif ($operator instanceof ISearchComparison) { |
|
| 123 | - return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap); |
|
| 124 | - } else { |
|
| 125 | - throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator)); |
|
| 126 | - } |
|
| 127 | - } |
|
| 128 | - |
|
| 129 | - private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) { |
|
| 130 | - $this->validateComparison($comparison); |
|
| 131 | - |
|
| 132 | - [$field, $value, $type] = $this->getOperatorFieldAndValue($comparison); |
|
| 133 | - if (isset($operatorMap[$type])) { |
|
| 134 | - $queryOperator = $operatorMap[$type]; |
|
| 135 | - return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value)); |
|
| 136 | - } else { |
|
| 137 | - throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType()); |
|
| 138 | - } |
|
| 139 | - } |
|
| 140 | - |
|
| 141 | - private function getOperatorFieldAndValue(ISearchComparison $operator) { |
|
| 142 | - $field = $operator->getField(); |
|
| 143 | - $value = $operator->getValue(); |
|
| 144 | - $type = $operator->getType(); |
|
| 145 | - if ($field === 'mimetype') { |
|
| 146 | - if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) { |
|
| 147 | - $value = (int)$this->mimetypeLoader->getId($value); |
|
| 148 | - } elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) { |
|
| 149 | - // transform "mimetype='foo/%'" to "mimepart='foo'" |
|
| 150 | - if (preg_match('|(.+)/%|', $value, $matches)) { |
|
| 151 | - $field = 'mimepart'; |
|
| 152 | - $value = (int)$this->mimetypeLoader->getId($matches[1]); |
|
| 153 | - $type = ISearchComparison::COMPARE_EQUAL; |
|
| 154 | - } elseif (strpos($value, '%') !== false) { |
|
| 155 | - throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported'); |
|
| 156 | - } else { |
|
| 157 | - $field = 'mimetype'; |
|
| 158 | - $value = (int)$this->mimetypeLoader->getId($value); |
|
| 159 | - $type = ISearchComparison::COMPARE_EQUAL; |
|
| 160 | - } |
|
| 161 | - } |
|
| 162 | - } elseif ($field === 'favorite') { |
|
| 163 | - $field = 'tag.category'; |
|
| 164 | - $value = self::TAG_FAVORITE; |
|
| 165 | - } elseif ($field === 'tagname') { |
|
| 166 | - $field = 'tag.category'; |
|
| 167 | - } elseif ($field === 'fileid') { |
|
| 168 | - $field = 'file.fileid'; |
|
| 169 | - } |
|
| 170 | - return [$field, $value, $type]; |
|
| 171 | - } |
|
| 172 | - |
|
| 173 | - private function validateComparison(ISearchComparison $operator) { |
|
| 174 | - $types = [ |
|
| 175 | - 'mimetype' => 'string', |
|
| 176 | - 'mtime' => 'integer', |
|
| 177 | - 'name' => 'string', |
|
| 178 | - 'size' => 'integer', |
|
| 179 | - 'tagname' => 'string', |
|
| 180 | - 'favorite' => 'boolean', |
|
| 181 | - 'fileid' => 'integer' |
|
| 182 | - ]; |
|
| 183 | - $comparisons = [ |
|
| 184 | - 'mimetype' => ['eq', 'like'], |
|
| 185 | - 'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'], |
|
| 186 | - 'name' => ['eq', 'like'], |
|
| 187 | - 'size' => ['eq', 'gt', 'lt', 'gte', 'lte'], |
|
| 188 | - 'tagname' => ['eq', 'like'], |
|
| 189 | - 'favorite' => ['eq'], |
|
| 190 | - 'fileid' => ['eq'] |
|
| 191 | - ]; |
|
| 192 | - |
|
| 193 | - if (!isset($types[$operator->getField()])) { |
|
| 194 | - throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField()); |
|
| 195 | - } |
|
| 196 | - $type = $types[$operator->getField()]; |
|
| 197 | - if (gettype($operator->getValue()) !== $type) { |
|
| 198 | - throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField()); |
|
| 199 | - } |
|
| 200 | - if (!in_array($operator->getType(), $comparisons[$operator->getField()])) { |
|
| 201 | - throw new \InvalidArgumentException('Unsupported comparison for field ' . $operator->getField() . ': ' . $operator->getType()); |
|
| 202 | - } |
|
| 203 | - } |
|
| 204 | - |
|
| 205 | - private function getParameterForValue(IQueryBuilder $builder, $value) { |
|
| 206 | - if ($value instanceof \DateTime) { |
|
| 207 | - $value = $value->getTimestamp(); |
|
| 208 | - } |
|
| 209 | - if (is_numeric($value)) { |
|
| 210 | - $type = IQueryBuilder::PARAM_INT; |
|
| 211 | - } else { |
|
| 212 | - $type = IQueryBuilder::PARAM_STR; |
|
| 213 | - } |
|
| 214 | - return $builder->createNamedParameter($value, $type); |
|
| 215 | - } |
|
| 216 | - |
|
| 217 | - /** |
|
| 218 | - * @param IQueryBuilder $query |
|
| 219 | - * @param ISearchOrder[] $orders |
|
| 220 | - */ |
|
| 221 | - public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders) { |
|
| 222 | - foreach ($orders as $order) { |
|
| 223 | - $query->addOrderBy($order->getField(), $order->getDirection()); |
|
| 224 | - } |
|
| 225 | - } |
|
| 40 | + protected static $searchOperatorMap = [ |
|
| 41 | + ISearchComparison::COMPARE_LIKE => 'iLike', |
|
| 42 | + ISearchComparison::COMPARE_EQUAL => 'eq', |
|
| 43 | + ISearchComparison::COMPARE_GREATER_THAN => 'gt', |
|
| 44 | + ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'gte', |
|
| 45 | + ISearchComparison::COMPARE_LESS_THAN => 'lt', |
|
| 46 | + ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lte' |
|
| 47 | + ]; |
|
| 48 | + |
|
| 49 | + protected static $searchOperatorNegativeMap = [ |
|
| 50 | + ISearchComparison::COMPARE_LIKE => 'notLike', |
|
| 51 | + ISearchComparison::COMPARE_EQUAL => 'neq', |
|
| 52 | + ISearchComparison::COMPARE_GREATER_THAN => 'lte', |
|
| 53 | + ISearchComparison::COMPARE_GREATER_THAN_EQUAL => 'lt', |
|
| 54 | + ISearchComparison::COMPARE_LESS_THAN => 'gte', |
|
| 55 | + ISearchComparison::COMPARE_LESS_THAN_EQUAL => 'lt' |
|
| 56 | + ]; |
|
| 57 | + |
|
| 58 | + public const TAG_FAVORITE = '_$!<Favorite>!$_'; |
|
| 59 | + |
|
| 60 | + /** @var IMimeTypeLoader */ |
|
| 61 | + private $mimetypeLoader; |
|
| 62 | + |
|
| 63 | + /** |
|
| 64 | + * QuerySearchUtil constructor. |
|
| 65 | + * |
|
| 66 | + * @param IMimeTypeLoader $mimetypeLoader |
|
| 67 | + */ |
|
| 68 | + public function __construct(IMimeTypeLoader $mimetypeLoader) { |
|
| 69 | + $this->mimetypeLoader = $mimetypeLoader; |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + /** |
|
| 73 | + * Whether or not the tag tables should be joined to complete the search |
|
| 74 | + * |
|
| 75 | + * @param ISearchOperator $operator |
|
| 76 | + * @return boolean |
|
| 77 | + */ |
|
| 78 | + public function shouldJoinTags(ISearchOperator $operator) { |
|
| 79 | + if ($operator instanceof ISearchBinaryOperator) { |
|
| 80 | + return array_reduce($operator->getArguments(), function ($shouldJoin, ISearchOperator $operator) { |
|
| 81 | + return $shouldJoin || $this->shouldJoinTags($operator); |
|
| 82 | + }, false); |
|
| 83 | + } elseif ($operator instanceof ISearchComparison) { |
|
| 84 | + return $operator->getField() === 'tagname' || $operator->getField() === 'favorite'; |
|
| 85 | + } |
|
| 86 | + return false; |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + /** |
|
| 90 | + * @param IQueryBuilder $builder |
|
| 91 | + * @param ISearchOperator $operator |
|
| 92 | + */ |
|
| 93 | + public function searchOperatorArrayToDBExprArray(IQueryBuilder $builder, array $operators) { |
|
| 94 | + return array_filter(array_map(function ($operator) use ($builder) { |
|
| 95 | + return $this->searchOperatorToDBExpr($builder, $operator); |
|
| 96 | + }, $operators)); |
|
| 97 | + } |
|
| 98 | + |
|
| 99 | + public function searchOperatorToDBExpr(IQueryBuilder $builder, ISearchOperator $operator) { |
|
| 100 | + $expr = $builder->expr(); |
|
| 101 | + if ($operator instanceof ISearchBinaryOperator) { |
|
| 102 | + if (count($operator->getArguments()) === 0) { |
|
| 103 | + return null; |
|
| 104 | + } |
|
| 105 | + |
|
| 106 | + switch ($operator->getType()) { |
|
| 107 | + case ISearchBinaryOperator::OPERATOR_NOT: |
|
| 108 | + $negativeOperator = $operator->getArguments()[0]; |
|
| 109 | + if ($negativeOperator instanceof ISearchComparison) { |
|
| 110 | + return $this->searchComparisonToDBExpr($builder, $negativeOperator, self::$searchOperatorNegativeMap); |
|
| 111 | + } else { |
|
| 112 | + throw new \InvalidArgumentException('Binary operators inside "not" is not supported'); |
|
| 113 | + } |
|
| 114 | + // no break |
|
| 115 | + case ISearchBinaryOperator::OPERATOR_AND: |
|
| 116 | + return call_user_func_array([$expr, 'andX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments())); |
|
| 117 | + case ISearchBinaryOperator::OPERATOR_OR: |
|
| 118 | + return call_user_func_array([$expr, 'orX'], $this->searchOperatorArrayToDBExprArray($builder, $operator->getArguments())); |
|
| 119 | + default: |
|
| 120 | + throw new \InvalidArgumentException('Invalid operator type: ' . $operator->getType()); |
|
| 121 | + } |
|
| 122 | + } elseif ($operator instanceof ISearchComparison) { |
|
| 123 | + return $this->searchComparisonToDBExpr($builder, $operator, self::$searchOperatorMap); |
|
| 124 | + } else { |
|
| 125 | + throw new \InvalidArgumentException('Invalid operator type: ' . get_class($operator)); |
|
| 126 | + } |
|
| 127 | + } |
|
| 128 | + |
|
| 129 | + private function searchComparisonToDBExpr(IQueryBuilder $builder, ISearchComparison $comparison, array $operatorMap) { |
|
| 130 | + $this->validateComparison($comparison); |
|
| 131 | + |
|
| 132 | + [$field, $value, $type] = $this->getOperatorFieldAndValue($comparison); |
|
| 133 | + if (isset($operatorMap[$type])) { |
|
| 134 | + $queryOperator = $operatorMap[$type]; |
|
| 135 | + return $builder->expr()->$queryOperator($field, $this->getParameterForValue($builder, $value)); |
|
| 136 | + } else { |
|
| 137 | + throw new \InvalidArgumentException('Invalid operator type: ' . $comparison->getType()); |
|
| 138 | + } |
|
| 139 | + } |
|
| 140 | + |
|
| 141 | + private function getOperatorFieldAndValue(ISearchComparison $operator) { |
|
| 142 | + $field = $operator->getField(); |
|
| 143 | + $value = $operator->getValue(); |
|
| 144 | + $type = $operator->getType(); |
|
| 145 | + if ($field === 'mimetype') { |
|
| 146 | + if ($operator->getType() === ISearchComparison::COMPARE_EQUAL) { |
|
| 147 | + $value = (int)$this->mimetypeLoader->getId($value); |
|
| 148 | + } elseif ($operator->getType() === ISearchComparison::COMPARE_LIKE) { |
|
| 149 | + // transform "mimetype='foo/%'" to "mimepart='foo'" |
|
| 150 | + if (preg_match('|(.+)/%|', $value, $matches)) { |
|
| 151 | + $field = 'mimepart'; |
|
| 152 | + $value = (int)$this->mimetypeLoader->getId($matches[1]); |
|
| 153 | + $type = ISearchComparison::COMPARE_EQUAL; |
|
| 154 | + } elseif (strpos($value, '%') !== false) { |
|
| 155 | + throw new \InvalidArgumentException('Unsupported query value for mimetype: ' . $value . ', only values in the format "mime/type" or "mime/%" are supported'); |
|
| 156 | + } else { |
|
| 157 | + $field = 'mimetype'; |
|
| 158 | + $value = (int)$this->mimetypeLoader->getId($value); |
|
| 159 | + $type = ISearchComparison::COMPARE_EQUAL; |
|
| 160 | + } |
|
| 161 | + } |
|
| 162 | + } elseif ($field === 'favorite') { |
|
| 163 | + $field = 'tag.category'; |
|
| 164 | + $value = self::TAG_FAVORITE; |
|
| 165 | + } elseif ($field === 'tagname') { |
|
| 166 | + $field = 'tag.category'; |
|
| 167 | + } elseif ($field === 'fileid') { |
|
| 168 | + $field = 'file.fileid'; |
|
| 169 | + } |
|
| 170 | + return [$field, $value, $type]; |
|
| 171 | + } |
|
| 172 | + |
|
| 173 | + private function validateComparison(ISearchComparison $operator) { |
|
| 174 | + $types = [ |
|
| 175 | + 'mimetype' => 'string', |
|
| 176 | + 'mtime' => 'integer', |
|
| 177 | + 'name' => 'string', |
|
| 178 | + 'size' => 'integer', |
|
| 179 | + 'tagname' => 'string', |
|
| 180 | + 'favorite' => 'boolean', |
|
| 181 | + 'fileid' => 'integer' |
|
| 182 | + ]; |
|
| 183 | + $comparisons = [ |
|
| 184 | + 'mimetype' => ['eq', 'like'], |
|
| 185 | + 'mtime' => ['eq', 'gt', 'lt', 'gte', 'lte'], |
|
| 186 | + 'name' => ['eq', 'like'], |
|
| 187 | + 'size' => ['eq', 'gt', 'lt', 'gte', 'lte'], |
|
| 188 | + 'tagname' => ['eq', 'like'], |
|
| 189 | + 'favorite' => ['eq'], |
|
| 190 | + 'fileid' => ['eq'] |
|
| 191 | + ]; |
|
| 192 | + |
|
| 193 | + if (!isset($types[$operator->getField()])) { |
|
| 194 | + throw new \InvalidArgumentException('Unsupported comparison field ' . $operator->getField()); |
|
| 195 | + } |
|
| 196 | + $type = $types[$operator->getField()]; |
|
| 197 | + if (gettype($operator->getValue()) !== $type) { |
|
| 198 | + throw new \InvalidArgumentException('Invalid type for field ' . $operator->getField()); |
|
| 199 | + } |
|
| 200 | + if (!in_array($operator->getType(), $comparisons[$operator->getField()])) { |
|
| 201 | + throw new \InvalidArgumentException('Unsupported comparison for field ' . $operator->getField() . ': ' . $operator->getType()); |
|
| 202 | + } |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | + private function getParameterForValue(IQueryBuilder $builder, $value) { |
|
| 206 | + if ($value instanceof \DateTime) { |
|
| 207 | + $value = $value->getTimestamp(); |
|
| 208 | + } |
|
| 209 | + if (is_numeric($value)) { |
|
| 210 | + $type = IQueryBuilder::PARAM_INT; |
|
| 211 | + } else { |
|
| 212 | + $type = IQueryBuilder::PARAM_STR; |
|
| 213 | + } |
|
| 214 | + return $builder->createNamedParameter($value, $type); |
|
| 215 | + } |
|
| 216 | + |
|
| 217 | + /** |
|
| 218 | + * @param IQueryBuilder $query |
|
| 219 | + * @param ISearchOrder[] $orders |
|
| 220 | + */ |
|
| 221 | + public function addSearchOrdersToQuery(IQueryBuilder $query, array $orders) { |
|
| 222 | + foreach ($orders as $order) { |
|
| 223 | + $query->addOrderBy($order->getField(), $order->getDirection()); |
|
| 224 | + } |
|
| 225 | + } |
|
| 226 | 226 | } |
@@ -32,66 +32,66 @@ |
||
| 32 | 32 | use OCP\Files\Cache\ICacheEntry; |
| 33 | 33 | |
| 34 | 34 | class HomeCache extends Cache { |
| 35 | - /** |
|
| 36 | - * get the size of a folder and set it in the cache |
|
| 37 | - * |
|
| 38 | - * @param string $path |
|
| 39 | - * @param array $entry (optional) meta data of the folder |
|
| 40 | - * @return int |
|
| 41 | - */ |
|
| 42 | - public function calculateFolderSize($path, $entry = null) { |
|
| 43 | - if ($path !== '/' and $path !== '' and $path !== 'files' and $path !== 'files_trashbin' and $path !== 'files_versions') { |
|
| 44 | - return parent::calculateFolderSize($path, $entry); |
|
| 45 | - } elseif ($path === '' or $path === '/') { |
|
| 46 | - // since the size of / isn't used (the size of /files is used instead) there is no use in calculating it |
|
| 47 | - return 0; |
|
| 48 | - } |
|
| 35 | + /** |
|
| 36 | + * get the size of a folder and set it in the cache |
|
| 37 | + * |
|
| 38 | + * @param string $path |
|
| 39 | + * @param array $entry (optional) meta data of the folder |
|
| 40 | + * @return int |
|
| 41 | + */ |
|
| 42 | + public function calculateFolderSize($path, $entry = null) { |
|
| 43 | + if ($path !== '/' and $path !== '' and $path !== 'files' and $path !== 'files_trashbin' and $path !== 'files_versions') { |
|
| 44 | + return parent::calculateFolderSize($path, $entry); |
|
| 45 | + } elseif ($path === '' or $path === '/') { |
|
| 46 | + // since the size of / isn't used (the size of /files is used instead) there is no use in calculating it |
|
| 47 | + return 0; |
|
| 48 | + } |
|
| 49 | 49 | |
| 50 | - $totalSize = 0; |
|
| 51 | - if (is_null($entry)) { |
|
| 52 | - $entry = $this->get($path); |
|
| 53 | - } |
|
| 54 | - if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { |
|
| 55 | - $id = $entry['fileid']; |
|
| 50 | + $totalSize = 0; |
|
| 51 | + if (is_null($entry)) { |
|
| 52 | + $entry = $this->get($path); |
|
| 53 | + } |
|
| 54 | + if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { |
|
| 55 | + $id = $entry['fileid']; |
|
| 56 | 56 | |
| 57 | - $query = $this->connection->getQueryBuilder(); |
|
| 58 | - $query->selectAlias($query->func()->sum('size'), 'f1') |
|
| 59 | - ->from('filecache') |
|
| 60 | - ->where($query->expr()->eq('parent', $query->createNamedParameter($id))) |
|
| 61 | - ->andWhere($query->expr()->eq('storage', $query->createNamedParameter($this->getNumericStorageId()))) |
|
| 62 | - ->andWhere($query->expr()->gte('size', $query->createNamedParameter(0))); |
|
| 57 | + $query = $this->connection->getQueryBuilder(); |
|
| 58 | + $query->selectAlias($query->func()->sum('size'), 'f1') |
|
| 59 | + ->from('filecache') |
|
| 60 | + ->where($query->expr()->eq('parent', $query->createNamedParameter($id))) |
|
| 61 | + ->andWhere($query->expr()->eq('storage', $query->createNamedParameter($this->getNumericStorageId()))) |
|
| 62 | + ->andWhere($query->expr()->gte('size', $query->createNamedParameter(0))); |
|
| 63 | 63 | |
| 64 | - $result = $query->execute(); |
|
| 65 | - $row = $result->fetch(); |
|
| 66 | - $result->closeCursor(); |
|
| 64 | + $result = $query->execute(); |
|
| 65 | + $row = $result->fetch(); |
|
| 66 | + $result->closeCursor(); |
|
| 67 | 67 | |
| 68 | - if ($row) { |
|
| 69 | - [$sum] = array_values($row); |
|
| 70 | - $totalSize = 0 + $sum; |
|
| 71 | - $entry['size'] += 0; |
|
| 72 | - if ($entry['size'] !== $totalSize) { |
|
| 73 | - $this->update($id, ['size' => $totalSize]); |
|
| 74 | - } |
|
| 75 | - } |
|
| 76 | - $result->closeCursor(); |
|
| 77 | - } |
|
| 78 | - return $totalSize; |
|
| 79 | - } |
|
| 68 | + if ($row) { |
|
| 69 | + [$sum] = array_values($row); |
|
| 70 | + $totalSize = 0 + $sum; |
|
| 71 | + $entry['size'] += 0; |
|
| 72 | + if ($entry['size'] !== $totalSize) { |
|
| 73 | + $this->update($id, ['size' => $totalSize]); |
|
| 74 | + } |
|
| 75 | + } |
|
| 76 | + $result->closeCursor(); |
|
| 77 | + } |
|
| 78 | + return $totalSize; |
|
| 79 | + } |
|
| 80 | 80 | |
| 81 | - /** |
|
| 82 | - * @param string $path |
|
| 83 | - * @return ICacheEntry |
|
| 84 | - */ |
|
| 85 | - public function get($path) { |
|
| 86 | - $data = parent::get($path); |
|
| 87 | - if ($path === '' or $path === '/') { |
|
| 88 | - // only the size of the "files" dir counts |
|
| 89 | - $filesData = parent::get('files'); |
|
| 81 | + /** |
|
| 82 | + * @param string $path |
|
| 83 | + * @return ICacheEntry |
|
| 84 | + */ |
|
| 85 | + public function get($path) { |
|
| 86 | + $data = parent::get($path); |
|
| 87 | + if ($path === '' or $path === '/') { |
|
| 88 | + // only the size of the "files" dir counts |
|
| 89 | + $filesData = parent::get('files'); |
|
| 90 | 90 | |
| 91 | - if (isset($filesData['size'])) { |
|
| 92 | - $data['size'] = $filesData['size']; |
|
| 93 | - } |
|
| 94 | - } |
|
| 95 | - return $data; |
|
| 96 | - } |
|
| 91 | + if (isset($filesData['size'])) { |
|
| 92 | + $data['size'] = $filesData['size']; |
|
| 93 | + } |
|
| 94 | + } |
|
| 95 | + return $data; |
|
| 96 | + } |
|
| 97 | 97 | } |
@@ -25,28 +25,28 @@ |
||
| 25 | 25 | use OCP\IDBConnection; |
| 26 | 26 | |
| 27 | 27 | class HomePropagator extends Propagator { |
| 28 | - private $ignoredBaseFolders; |
|
| 28 | + private $ignoredBaseFolders; |
|
| 29 | 29 | |
| 30 | - /** |
|
| 31 | - * @param \OC\Files\Storage\Storage $storage |
|
| 32 | - */ |
|
| 33 | - public function __construct(\OC\Files\Storage\Storage $storage, IDBConnection $connection) { |
|
| 34 | - parent::__construct($storage, $connection); |
|
| 35 | - $this->ignoredBaseFolders = ['files_encryption']; |
|
| 36 | - } |
|
| 30 | + /** |
|
| 31 | + * @param \OC\Files\Storage\Storage $storage |
|
| 32 | + */ |
|
| 33 | + public function __construct(\OC\Files\Storage\Storage $storage, IDBConnection $connection) { |
|
| 34 | + parent::__construct($storage, $connection); |
|
| 35 | + $this->ignoredBaseFolders = ['files_encryption']; |
|
| 36 | + } |
|
| 37 | 37 | |
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * @param string $internalPath |
|
| 41 | - * @param int $time |
|
| 42 | - * @param int $sizeDifference number of bytes the file has grown |
|
| 43 | - */ |
|
| 44 | - public function propagateChange($internalPath, $time, $sizeDifference = 0) { |
|
| 45 | - [$baseFolder] = explode('/', $internalPath, 2); |
|
| 46 | - if (in_array($baseFolder, $this->ignoredBaseFolders)) { |
|
| 47 | - return []; |
|
| 48 | - } else { |
|
| 49 | - parent::propagateChange($internalPath, $time, $sizeDifference); |
|
| 50 | - } |
|
| 51 | - } |
|
| 39 | + /** |
|
| 40 | + * @param string $internalPath |
|
| 41 | + * @param int $time |
|
| 42 | + * @param int $sizeDifference number of bytes the file has grown |
|
| 43 | + */ |
|
| 44 | + public function propagateChange($internalPath, $time, $sizeDifference = 0) { |
|
| 45 | + [$baseFolder] = explode('/', $internalPath, 2); |
|
| 46 | + if (in_array($baseFolder, $this->ignoredBaseFolders)) { |
|
| 47 | + return []; |
|
| 48 | + } else { |
|
| 49 | + parent::propagateChange($internalPath, $time, $sizeDifference); |
|
| 50 | + } |
|
| 51 | + } |
|
| 52 | 52 | } |
@@ -28,19 +28,19 @@ |
||
| 28 | 28 | use OC\Files\Storage\Wrapper\Jail; |
| 29 | 29 | |
| 30 | 30 | class JailPropagator extends Propagator { |
| 31 | - /** |
|
| 32 | - * @var Jail |
|
| 33 | - */ |
|
| 34 | - protected $storage; |
|
| 31 | + /** |
|
| 32 | + * @var Jail |
|
| 33 | + */ |
|
| 34 | + protected $storage; |
|
| 35 | 35 | |
| 36 | - /** |
|
| 37 | - * @param string $internalPath |
|
| 38 | - * @param int $time |
|
| 39 | - * @param int $sizeDifference |
|
| 40 | - */ |
|
| 41 | - public function propagateChange($internalPath, $time, $sizeDifference = 0) { |
|
| 42 | - /** @var \OC\Files\Storage\Storage $storage */ |
|
| 43 | - [$storage, $sourceInternalPath] = $this->storage->resolvePath($internalPath); |
|
| 44 | - $storage->getPropagator()->propagateChange($sourceInternalPath, $time, $sizeDifference); |
|
| 45 | - } |
|
| 36 | + /** |
|
| 37 | + * @param string $internalPath |
|
| 38 | + * @param int $time |
|
| 39 | + * @param int $sizeDifference |
|
| 40 | + */ |
|
| 41 | + public function propagateChange($internalPath, $time, $sizeDifference = 0) { |
|
| 42 | + /** @var \OC\Files\Storage\Storage $storage */ |
|
| 43 | + [$storage, $sourceInternalPath] = $this->storage->resolvePath($internalPath); |
|
| 44 | + $storage->getPropagator()->propagateChange($sourceInternalPath, $time, $sizeDifference); |
|
| 45 | + } |
|
| 46 | 46 | } |
@@ -39,608 +39,608 @@ |
||
| 39 | 39 | use OCP\Lock\ILockingProvider; |
| 40 | 40 | |
| 41 | 41 | class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStreamStorage { |
| 42 | - /** |
|
| 43 | - * @var \OC\Files\Storage\Storage $storage |
|
| 44 | - */ |
|
| 45 | - protected $storage; |
|
| 46 | - |
|
| 47 | - public $cache; |
|
| 48 | - public $scanner; |
|
| 49 | - public $watcher; |
|
| 50 | - public $propagator; |
|
| 51 | - public $updater; |
|
| 52 | - |
|
| 53 | - /** |
|
| 54 | - * @param array $parameters |
|
| 55 | - */ |
|
| 56 | - public function __construct($parameters) { |
|
| 57 | - $this->storage = $parameters['storage']; |
|
| 58 | - } |
|
| 59 | - |
|
| 60 | - /** |
|
| 61 | - * @return \OC\Files\Storage\Storage |
|
| 62 | - */ |
|
| 63 | - public function getWrapperStorage() { |
|
| 64 | - return $this->storage; |
|
| 65 | - } |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * Get the identifier for the storage, |
|
| 69 | - * the returned id should be the same for every storage object that is created with the same parameters |
|
| 70 | - * and two storage objects with the same id should refer to two storages that display the same files. |
|
| 71 | - * |
|
| 72 | - * @return string |
|
| 73 | - */ |
|
| 74 | - public function getId() { |
|
| 75 | - return $this->getWrapperStorage()->getId(); |
|
| 76 | - } |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * see https://www.php.net/manual/en/function.mkdir.php |
|
| 80 | - * |
|
| 81 | - * @param string $path |
|
| 82 | - * @return bool |
|
| 83 | - */ |
|
| 84 | - public function mkdir($path) { |
|
| 85 | - return $this->getWrapperStorage()->mkdir($path); |
|
| 86 | - } |
|
| 87 | - |
|
| 88 | - /** |
|
| 89 | - * see https://www.php.net/manual/en/function.rmdir.php |
|
| 90 | - * |
|
| 91 | - * @param string $path |
|
| 92 | - * @return bool |
|
| 93 | - */ |
|
| 94 | - public function rmdir($path) { |
|
| 95 | - return $this->getWrapperStorage()->rmdir($path); |
|
| 96 | - } |
|
| 97 | - |
|
| 98 | - /** |
|
| 99 | - * see https://www.php.net/manual/en/function.opendir.php |
|
| 100 | - * |
|
| 101 | - * @param string $path |
|
| 102 | - * @return resource|bool |
|
| 103 | - */ |
|
| 104 | - public function opendir($path) { |
|
| 105 | - return $this->getWrapperStorage()->opendir($path); |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * see https://www.php.net/manual/en/function.is_dir.php |
|
| 110 | - * |
|
| 111 | - * @param string $path |
|
| 112 | - * @return bool |
|
| 113 | - */ |
|
| 114 | - public function is_dir($path) { |
|
| 115 | - return $this->getWrapperStorage()->is_dir($path); |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - /** |
|
| 119 | - * see https://www.php.net/manual/en/function.is_file.php |
|
| 120 | - * |
|
| 121 | - * @param string $path |
|
| 122 | - * @return bool |
|
| 123 | - */ |
|
| 124 | - public function is_file($path) { |
|
| 125 | - return $this->getWrapperStorage()->is_file($path); |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * see https://www.php.net/manual/en/function.stat.php |
|
| 130 | - * only the following keys are required in the result: size and mtime |
|
| 131 | - * |
|
| 132 | - * @param string $path |
|
| 133 | - * @return array|bool |
|
| 134 | - */ |
|
| 135 | - public function stat($path) { |
|
| 136 | - return $this->getWrapperStorage()->stat($path); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * see https://www.php.net/manual/en/function.filetype.php |
|
| 141 | - * |
|
| 142 | - * @param string $path |
|
| 143 | - * @return string|bool |
|
| 144 | - */ |
|
| 145 | - public function filetype($path) { |
|
| 146 | - return $this->getWrapperStorage()->filetype($path); |
|
| 147 | - } |
|
| 148 | - |
|
| 149 | - /** |
|
| 150 | - * see https://www.php.net/manual/en/function.filesize.php |
|
| 151 | - * The result for filesize when called on a folder is required to be 0 |
|
| 152 | - * |
|
| 153 | - * @param string $path |
|
| 154 | - * @return int|bool |
|
| 155 | - */ |
|
| 156 | - public function filesize($path) { |
|
| 157 | - return $this->getWrapperStorage()->filesize($path); |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - /** |
|
| 161 | - * check if a file can be created in $path |
|
| 162 | - * |
|
| 163 | - * @param string $path |
|
| 164 | - * @return bool |
|
| 165 | - */ |
|
| 166 | - public function isCreatable($path) { |
|
| 167 | - return $this->getWrapperStorage()->isCreatable($path); |
|
| 168 | - } |
|
| 169 | - |
|
| 170 | - /** |
|
| 171 | - * check if a file can be read |
|
| 172 | - * |
|
| 173 | - * @param string $path |
|
| 174 | - * @return bool |
|
| 175 | - */ |
|
| 176 | - public function isReadable($path) { |
|
| 177 | - return $this->getWrapperStorage()->isReadable($path); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - /** |
|
| 181 | - * check if a file can be written to |
|
| 182 | - * |
|
| 183 | - * @param string $path |
|
| 184 | - * @return bool |
|
| 185 | - */ |
|
| 186 | - public function isUpdatable($path) { |
|
| 187 | - return $this->getWrapperStorage()->isUpdatable($path); |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - /** |
|
| 191 | - * check if a file can be deleted |
|
| 192 | - * |
|
| 193 | - * @param string $path |
|
| 194 | - * @return bool |
|
| 195 | - */ |
|
| 196 | - public function isDeletable($path) { |
|
| 197 | - return $this->getWrapperStorage()->isDeletable($path); |
|
| 198 | - } |
|
| 199 | - |
|
| 200 | - /** |
|
| 201 | - * check if a file can be shared |
|
| 202 | - * |
|
| 203 | - * @param string $path |
|
| 204 | - * @return bool |
|
| 205 | - */ |
|
| 206 | - public function isSharable($path) { |
|
| 207 | - return $this->getWrapperStorage()->isSharable($path); |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - /** |
|
| 211 | - * get the full permissions of a path. |
|
| 212 | - * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php |
|
| 213 | - * |
|
| 214 | - * @param string $path |
|
| 215 | - * @return int |
|
| 216 | - */ |
|
| 217 | - public function getPermissions($path) { |
|
| 218 | - return $this->getWrapperStorage()->getPermissions($path); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - /** |
|
| 222 | - * see https://www.php.net/manual/en/function.file_exists.php |
|
| 223 | - * |
|
| 224 | - * @param string $path |
|
| 225 | - * @return bool |
|
| 226 | - */ |
|
| 227 | - public function file_exists($path) { |
|
| 228 | - return $this->getWrapperStorage()->file_exists($path); |
|
| 229 | - } |
|
| 230 | - |
|
| 231 | - /** |
|
| 232 | - * see https://www.php.net/manual/en/function.filemtime.php |
|
| 233 | - * |
|
| 234 | - * @param string $path |
|
| 235 | - * @return int|bool |
|
| 236 | - */ |
|
| 237 | - public function filemtime($path) { |
|
| 238 | - return $this->getWrapperStorage()->filemtime($path); |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * see https://www.php.net/manual/en/function.file_get_contents.php |
|
| 243 | - * |
|
| 244 | - * @param string $path |
|
| 245 | - * @return string|bool |
|
| 246 | - */ |
|
| 247 | - public function file_get_contents($path) { |
|
| 248 | - return $this->getWrapperStorage()->file_get_contents($path); |
|
| 249 | - } |
|
| 250 | - |
|
| 251 | - /** |
|
| 252 | - * see https://www.php.net/manual/en/function.file_put_contents.php |
|
| 253 | - * |
|
| 254 | - * @param string $path |
|
| 255 | - * @param mixed $data |
|
| 256 | - * @return int|false |
|
| 257 | - */ |
|
| 258 | - public function file_put_contents($path, $data) { |
|
| 259 | - return $this->getWrapperStorage()->file_put_contents($path, $data); |
|
| 260 | - } |
|
| 261 | - |
|
| 262 | - /** |
|
| 263 | - * see https://www.php.net/manual/en/function.unlink.php |
|
| 264 | - * |
|
| 265 | - * @param string $path |
|
| 266 | - * @return bool |
|
| 267 | - */ |
|
| 268 | - public function unlink($path) { |
|
| 269 | - return $this->getWrapperStorage()->unlink($path); |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - /** |
|
| 273 | - * see https://www.php.net/manual/en/function.rename.php |
|
| 274 | - * |
|
| 275 | - * @param string $path1 |
|
| 276 | - * @param string $path2 |
|
| 277 | - * @return bool |
|
| 278 | - */ |
|
| 279 | - public function rename($path1, $path2) { |
|
| 280 | - return $this->getWrapperStorage()->rename($path1, $path2); |
|
| 281 | - } |
|
| 282 | - |
|
| 283 | - /** |
|
| 284 | - * see https://www.php.net/manual/en/function.copy.php |
|
| 285 | - * |
|
| 286 | - * @param string $path1 |
|
| 287 | - * @param string $path2 |
|
| 288 | - * @return bool |
|
| 289 | - */ |
|
| 290 | - public function copy($path1, $path2) { |
|
| 291 | - return $this->getWrapperStorage()->copy($path1, $path2); |
|
| 292 | - } |
|
| 293 | - |
|
| 294 | - /** |
|
| 295 | - * see https://www.php.net/manual/en/function.fopen.php |
|
| 296 | - * |
|
| 297 | - * @param string $path |
|
| 298 | - * @param string $mode |
|
| 299 | - * @return resource|bool |
|
| 300 | - */ |
|
| 301 | - public function fopen($path, $mode) { |
|
| 302 | - return $this->getWrapperStorage()->fopen($path, $mode); |
|
| 303 | - } |
|
| 304 | - |
|
| 305 | - /** |
|
| 306 | - * get the mimetype for a file or folder |
|
| 307 | - * The mimetype for a folder is required to be "httpd/unix-directory" |
|
| 308 | - * |
|
| 309 | - * @param string $path |
|
| 310 | - * @return string|bool |
|
| 311 | - */ |
|
| 312 | - public function getMimeType($path) { |
|
| 313 | - return $this->getWrapperStorage()->getMimeType($path); |
|
| 314 | - } |
|
| 315 | - |
|
| 316 | - /** |
|
| 317 | - * see https://www.php.net/manual/en/function.hash.php |
|
| 318 | - * |
|
| 319 | - * @param string $type |
|
| 320 | - * @param string $path |
|
| 321 | - * @param bool $raw |
|
| 322 | - * @return string|bool |
|
| 323 | - */ |
|
| 324 | - public function hash($type, $path, $raw = false) { |
|
| 325 | - return $this->getWrapperStorage()->hash($type, $path, $raw); |
|
| 326 | - } |
|
| 327 | - |
|
| 328 | - /** |
|
| 329 | - * see https://www.php.net/manual/en/function.free_space.php |
|
| 330 | - * |
|
| 331 | - * @param string $path |
|
| 332 | - * @return int|bool |
|
| 333 | - */ |
|
| 334 | - public function free_space($path) { |
|
| 335 | - return $this->getWrapperStorage()->free_space($path); |
|
| 336 | - } |
|
| 337 | - |
|
| 338 | - /** |
|
| 339 | - * search for occurrences of $query in file names |
|
| 340 | - * |
|
| 341 | - * @param string $query |
|
| 342 | - * @return array|bool |
|
| 343 | - */ |
|
| 344 | - public function search($query) { |
|
| 345 | - return $this->getWrapperStorage()->search($query); |
|
| 346 | - } |
|
| 347 | - |
|
| 348 | - /** |
|
| 349 | - * see https://www.php.net/manual/en/function.touch.php |
|
| 350 | - * If the backend does not support the operation, false should be returned |
|
| 351 | - * |
|
| 352 | - * @param string $path |
|
| 353 | - * @param int $mtime |
|
| 354 | - * @return bool |
|
| 355 | - */ |
|
| 356 | - public function touch($path, $mtime = null) { |
|
| 357 | - return $this->getWrapperStorage()->touch($path, $mtime); |
|
| 358 | - } |
|
| 359 | - |
|
| 360 | - /** |
|
| 361 | - * get the path to a local version of the file. |
|
| 362 | - * The local version of the file can be temporary and doesn't have to be persistent across requests |
|
| 363 | - * |
|
| 364 | - * @param string $path |
|
| 365 | - * @return string|bool |
|
| 366 | - */ |
|
| 367 | - public function getLocalFile($path) { |
|
| 368 | - return $this->getWrapperStorage()->getLocalFile($path); |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - /** |
|
| 372 | - * check if a file or folder has been updated since $time |
|
| 373 | - * |
|
| 374 | - * @param string $path |
|
| 375 | - * @param int $time |
|
| 376 | - * @return bool |
|
| 377 | - * |
|
| 378 | - * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. |
|
| 379 | - * returning true for other changes in the folder is optional |
|
| 380 | - */ |
|
| 381 | - public function hasUpdated($path, $time) { |
|
| 382 | - return $this->getWrapperStorage()->hasUpdated($path, $time); |
|
| 383 | - } |
|
| 384 | - |
|
| 385 | - /** |
|
| 386 | - * get a cache instance for the storage |
|
| 387 | - * |
|
| 388 | - * @param string $path |
|
| 389 | - * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache |
|
| 390 | - * @return \OC\Files\Cache\Cache |
|
| 391 | - */ |
|
| 392 | - public function getCache($path = '', $storage = null) { |
|
| 393 | - if (!$storage) { |
|
| 394 | - $storage = $this; |
|
| 395 | - } |
|
| 396 | - return $this->getWrapperStorage()->getCache($path, $storage); |
|
| 397 | - } |
|
| 398 | - |
|
| 399 | - /** |
|
| 400 | - * get a scanner instance for the storage |
|
| 401 | - * |
|
| 402 | - * @param string $path |
|
| 403 | - * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner |
|
| 404 | - * @return \OC\Files\Cache\Scanner |
|
| 405 | - */ |
|
| 406 | - public function getScanner($path = '', $storage = null) { |
|
| 407 | - if (!$storage) { |
|
| 408 | - $storage = $this; |
|
| 409 | - } |
|
| 410 | - return $this->getWrapperStorage()->getScanner($path, $storage); |
|
| 411 | - } |
|
| 412 | - |
|
| 413 | - |
|
| 414 | - /** |
|
| 415 | - * get the user id of the owner of a file or folder |
|
| 416 | - * |
|
| 417 | - * @param string $path |
|
| 418 | - * @return string |
|
| 419 | - */ |
|
| 420 | - public function getOwner($path) { |
|
| 421 | - return $this->getWrapperStorage()->getOwner($path); |
|
| 422 | - } |
|
| 423 | - |
|
| 424 | - /** |
|
| 425 | - * get a watcher instance for the cache |
|
| 426 | - * |
|
| 427 | - * @param string $path |
|
| 428 | - * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher |
|
| 429 | - * @return \OC\Files\Cache\Watcher |
|
| 430 | - */ |
|
| 431 | - public function getWatcher($path = '', $storage = null) { |
|
| 432 | - if (!$storage) { |
|
| 433 | - $storage = $this; |
|
| 434 | - } |
|
| 435 | - return $this->getWrapperStorage()->getWatcher($path, $storage); |
|
| 436 | - } |
|
| 437 | - |
|
| 438 | - public function getPropagator($storage = null) { |
|
| 439 | - if (!$storage) { |
|
| 440 | - $storage = $this; |
|
| 441 | - } |
|
| 442 | - return $this->getWrapperStorage()->getPropagator($storage); |
|
| 443 | - } |
|
| 444 | - |
|
| 445 | - public function getUpdater($storage = null) { |
|
| 446 | - if (!$storage) { |
|
| 447 | - $storage = $this; |
|
| 448 | - } |
|
| 449 | - return $this->getWrapperStorage()->getUpdater($storage); |
|
| 450 | - } |
|
| 451 | - |
|
| 452 | - /** |
|
| 453 | - * @return \OC\Files\Cache\Storage |
|
| 454 | - */ |
|
| 455 | - public function getStorageCache() { |
|
| 456 | - return $this->getWrapperStorage()->getStorageCache(); |
|
| 457 | - } |
|
| 458 | - |
|
| 459 | - /** |
|
| 460 | - * get the ETag for a file or folder |
|
| 461 | - * |
|
| 462 | - * @param string $path |
|
| 463 | - * @return string|bool |
|
| 464 | - */ |
|
| 465 | - public function getETag($path) { |
|
| 466 | - return $this->getWrapperStorage()->getETag($path); |
|
| 467 | - } |
|
| 468 | - |
|
| 469 | - /** |
|
| 470 | - * Returns true |
|
| 471 | - * |
|
| 472 | - * @return true |
|
| 473 | - */ |
|
| 474 | - public function test() { |
|
| 475 | - return $this->getWrapperStorage()->test(); |
|
| 476 | - } |
|
| 477 | - |
|
| 478 | - /** |
|
| 479 | - * Returns the wrapped storage's value for isLocal() |
|
| 480 | - * |
|
| 481 | - * @return bool wrapped storage's isLocal() value |
|
| 482 | - */ |
|
| 483 | - public function isLocal() { |
|
| 484 | - return $this->getWrapperStorage()->isLocal(); |
|
| 485 | - } |
|
| 486 | - |
|
| 487 | - /** |
|
| 488 | - * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class |
|
| 489 | - * |
|
| 490 | - * @param string $class |
|
| 491 | - * @return bool |
|
| 492 | - */ |
|
| 493 | - public function instanceOfStorage($class) { |
|
| 494 | - if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') { |
|
| 495 | - // FIXME Temporary fix to keep existing checks working |
|
| 496 | - $class = '\OCA\Files_Sharing\SharedStorage'; |
|
| 497 | - } |
|
| 498 | - return is_a($this, $class) or $this->getWrapperStorage()->instanceOfStorage($class); |
|
| 499 | - } |
|
| 500 | - |
|
| 501 | - /** |
|
| 502 | - * Pass any methods custom to specific storage implementations to the wrapped storage |
|
| 503 | - * |
|
| 504 | - * @param string $method |
|
| 505 | - * @param array $args |
|
| 506 | - * @return mixed |
|
| 507 | - */ |
|
| 508 | - public function __call($method, $args) { |
|
| 509 | - return call_user_func_array([$this->getWrapperStorage(), $method], $args); |
|
| 510 | - } |
|
| 511 | - |
|
| 512 | - /** |
|
| 513 | - * A custom storage implementation can return an url for direct download of a give file. |
|
| 514 | - * |
|
| 515 | - * For now the returned array can hold the parameter url - in future more attributes might follow. |
|
| 516 | - * |
|
| 517 | - * @param string $path |
|
| 518 | - * @return array|bool |
|
| 519 | - */ |
|
| 520 | - public function getDirectDownload($path) { |
|
| 521 | - return $this->getWrapperStorage()->getDirectDownload($path); |
|
| 522 | - } |
|
| 523 | - |
|
| 524 | - /** |
|
| 525 | - * Get availability of the storage |
|
| 526 | - * |
|
| 527 | - * @return array [ available, last_checked ] |
|
| 528 | - */ |
|
| 529 | - public function getAvailability() { |
|
| 530 | - return $this->getWrapperStorage()->getAvailability(); |
|
| 531 | - } |
|
| 532 | - |
|
| 533 | - /** |
|
| 534 | - * Set availability of the storage |
|
| 535 | - * |
|
| 536 | - * @param bool $isAvailable |
|
| 537 | - */ |
|
| 538 | - public function setAvailability($isAvailable) { |
|
| 539 | - $this->getWrapperStorage()->setAvailability($isAvailable); |
|
| 540 | - } |
|
| 541 | - |
|
| 542 | - /** |
|
| 543 | - * @param string $path the path of the target folder |
|
| 544 | - * @param string $fileName the name of the file itself |
|
| 545 | - * @return void |
|
| 546 | - * @throws InvalidPathException |
|
| 547 | - */ |
|
| 548 | - public function verifyPath($path, $fileName) { |
|
| 549 | - $this->getWrapperStorage()->verifyPath($path, $fileName); |
|
| 550 | - } |
|
| 551 | - |
|
| 552 | - /** |
|
| 553 | - * @param IStorage $sourceStorage |
|
| 554 | - * @param string $sourceInternalPath |
|
| 555 | - * @param string $targetInternalPath |
|
| 556 | - * @return bool |
|
| 557 | - */ |
|
| 558 | - public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { |
|
| 559 | - if ($sourceStorage === $this) { |
|
| 560 | - return $this->copy($sourceInternalPath, $targetInternalPath); |
|
| 561 | - } |
|
| 562 | - |
|
| 563 | - return $this->getWrapperStorage()->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); |
|
| 564 | - } |
|
| 565 | - |
|
| 566 | - /** |
|
| 567 | - * @param IStorage $sourceStorage |
|
| 568 | - * @param string $sourceInternalPath |
|
| 569 | - * @param string $targetInternalPath |
|
| 570 | - * @return bool |
|
| 571 | - */ |
|
| 572 | - public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { |
|
| 573 | - if ($sourceStorage === $this) { |
|
| 574 | - return $this->rename($sourceInternalPath, $targetInternalPath); |
|
| 575 | - } |
|
| 576 | - |
|
| 577 | - return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); |
|
| 578 | - } |
|
| 579 | - |
|
| 580 | - /** |
|
| 581 | - * @param string $path |
|
| 582 | - * @return array |
|
| 583 | - */ |
|
| 584 | - public function getMetaData($path) { |
|
| 585 | - return $this->getWrapperStorage()->getMetaData($path); |
|
| 586 | - } |
|
| 587 | - |
|
| 588 | - /** |
|
| 589 | - * @param string $path |
|
| 590 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 591 | - * @param \OCP\Lock\ILockingProvider $provider |
|
| 592 | - * @throws \OCP\Lock\LockedException |
|
| 593 | - */ |
|
| 594 | - public function acquireLock($path, $type, ILockingProvider $provider) { |
|
| 595 | - if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 596 | - $this->getWrapperStorage()->acquireLock($path, $type, $provider); |
|
| 597 | - } |
|
| 598 | - } |
|
| 599 | - |
|
| 600 | - /** |
|
| 601 | - * @param string $path |
|
| 602 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 603 | - * @param \OCP\Lock\ILockingProvider $provider |
|
| 604 | - */ |
|
| 605 | - public function releaseLock($path, $type, ILockingProvider $provider) { |
|
| 606 | - if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 607 | - $this->getWrapperStorage()->releaseLock($path, $type, $provider); |
|
| 608 | - } |
|
| 609 | - } |
|
| 610 | - |
|
| 611 | - /** |
|
| 612 | - * @param string $path |
|
| 613 | - * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 614 | - * @param \OCP\Lock\ILockingProvider $provider |
|
| 615 | - */ |
|
| 616 | - public function changeLock($path, $type, ILockingProvider $provider) { |
|
| 617 | - if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 618 | - $this->getWrapperStorage()->changeLock($path, $type, $provider); |
|
| 619 | - } |
|
| 620 | - } |
|
| 621 | - |
|
| 622 | - /** |
|
| 623 | - * @return bool |
|
| 624 | - */ |
|
| 625 | - public function needsPartFile() { |
|
| 626 | - return $this->getWrapperStorage()->needsPartFile(); |
|
| 627 | - } |
|
| 628 | - |
|
| 629 | - public function writeStream(string $path, $stream, int $size = null): int { |
|
| 630 | - $storage = $this->getWrapperStorage(); |
|
| 631 | - if ($storage->instanceOfStorage(IWriteStreamStorage::class)) { |
|
| 632 | - /** @var IWriteStreamStorage $storage */ |
|
| 633 | - return $storage->writeStream($path, $stream, $size); |
|
| 634 | - } else { |
|
| 635 | - $target = $this->fopen($path, 'w'); |
|
| 636 | - [$count, $result] = \OC_Helper::streamCopy($stream, $target); |
|
| 637 | - fclose($stream); |
|
| 638 | - fclose($target); |
|
| 639 | - return $count; |
|
| 640 | - } |
|
| 641 | - } |
|
| 642 | - |
|
| 643 | - public function getDirectoryContent($directory): \Traversable { |
|
| 644 | - return $this->getWrapperStorage()->getDirectoryContent($directory); |
|
| 645 | - } |
|
| 42 | + /** |
|
| 43 | + * @var \OC\Files\Storage\Storage $storage |
|
| 44 | + */ |
|
| 45 | + protected $storage; |
|
| 46 | + |
|
| 47 | + public $cache; |
|
| 48 | + public $scanner; |
|
| 49 | + public $watcher; |
|
| 50 | + public $propagator; |
|
| 51 | + public $updater; |
|
| 52 | + |
|
| 53 | + /** |
|
| 54 | + * @param array $parameters |
|
| 55 | + */ |
|
| 56 | + public function __construct($parameters) { |
|
| 57 | + $this->storage = $parameters['storage']; |
|
| 58 | + } |
|
| 59 | + |
|
| 60 | + /** |
|
| 61 | + * @return \OC\Files\Storage\Storage |
|
| 62 | + */ |
|
| 63 | + public function getWrapperStorage() { |
|
| 64 | + return $this->storage; |
|
| 65 | + } |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * Get the identifier for the storage, |
|
| 69 | + * the returned id should be the same for every storage object that is created with the same parameters |
|
| 70 | + * and two storage objects with the same id should refer to two storages that display the same files. |
|
| 71 | + * |
|
| 72 | + * @return string |
|
| 73 | + */ |
|
| 74 | + public function getId() { |
|
| 75 | + return $this->getWrapperStorage()->getId(); |
|
| 76 | + } |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * see https://www.php.net/manual/en/function.mkdir.php |
|
| 80 | + * |
|
| 81 | + * @param string $path |
|
| 82 | + * @return bool |
|
| 83 | + */ |
|
| 84 | + public function mkdir($path) { |
|
| 85 | + return $this->getWrapperStorage()->mkdir($path); |
|
| 86 | + } |
|
| 87 | + |
|
| 88 | + /** |
|
| 89 | + * see https://www.php.net/manual/en/function.rmdir.php |
|
| 90 | + * |
|
| 91 | + * @param string $path |
|
| 92 | + * @return bool |
|
| 93 | + */ |
|
| 94 | + public function rmdir($path) { |
|
| 95 | + return $this->getWrapperStorage()->rmdir($path); |
|
| 96 | + } |
|
| 97 | + |
|
| 98 | + /** |
|
| 99 | + * see https://www.php.net/manual/en/function.opendir.php |
|
| 100 | + * |
|
| 101 | + * @param string $path |
|
| 102 | + * @return resource|bool |
|
| 103 | + */ |
|
| 104 | + public function opendir($path) { |
|
| 105 | + return $this->getWrapperStorage()->opendir($path); |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * see https://www.php.net/manual/en/function.is_dir.php |
|
| 110 | + * |
|
| 111 | + * @param string $path |
|
| 112 | + * @return bool |
|
| 113 | + */ |
|
| 114 | + public function is_dir($path) { |
|
| 115 | + return $this->getWrapperStorage()->is_dir($path); |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + /** |
|
| 119 | + * see https://www.php.net/manual/en/function.is_file.php |
|
| 120 | + * |
|
| 121 | + * @param string $path |
|
| 122 | + * @return bool |
|
| 123 | + */ |
|
| 124 | + public function is_file($path) { |
|
| 125 | + return $this->getWrapperStorage()->is_file($path); |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * see https://www.php.net/manual/en/function.stat.php |
|
| 130 | + * only the following keys are required in the result: size and mtime |
|
| 131 | + * |
|
| 132 | + * @param string $path |
|
| 133 | + * @return array|bool |
|
| 134 | + */ |
|
| 135 | + public function stat($path) { |
|
| 136 | + return $this->getWrapperStorage()->stat($path); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * see https://www.php.net/manual/en/function.filetype.php |
|
| 141 | + * |
|
| 142 | + * @param string $path |
|
| 143 | + * @return string|bool |
|
| 144 | + */ |
|
| 145 | + public function filetype($path) { |
|
| 146 | + return $this->getWrapperStorage()->filetype($path); |
|
| 147 | + } |
|
| 148 | + |
|
| 149 | + /** |
|
| 150 | + * see https://www.php.net/manual/en/function.filesize.php |
|
| 151 | + * The result for filesize when called on a folder is required to be 0 |
|
| 152 | + * |
|
| 153 | + * @param string $path |
|
| 154 | + * @return int|bool |
|
| 155 | + */ |
|
| 156 | + public function filesize($path) { |
|
| 157 | + return $this->getWrapperStorage()->filesize($path); |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + /** |
|
| 161 | + * check if a file can be created in $path |
|
| 162 | + * |
|
| 163 | + * @param string $path |
|
| 164 | + * @return bool |
|
| 165 | + */ |
|
| 166 | + public function isCreatable($path) { |
|
| 167 | + return $this->getWrapperStorage()->isCreatable($path); |
|
| 168 | + } |
|
| 169 | + |
|
| 170 | + /** |
|
| 171 | + * check if a file can be read |
|
| 172 | + * |
|
| 173 | + * @param string $path |
|
| 174 | + * @return bool |
|
| 175 | + */ |
|
| 176 | + public function isReadable($path) { |
|
| 177 | + return $this->getWrapperStorage()->isReadable($path); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + /** |
|
| 181 | + * check if a file can be written to |
|
| 182 | + * |
|
| 183 | + * @param string $path |
|
| 184 | + * @return bool |
|
| 185 | + */ |
|
| 186 | + public function isUpdatable($path) { |
|
| 187 | + return $this->getWrapperStorage()->isUpdatable($path); |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + /** |
|
| 191 | + * check if a file can be deleted |
|
| 192 | + * |
|
| 193 | + * @param string $path |
|
| 194 | + * @return bool |
|
| 195 | + */ |
|
| 196 | + public function isDeletable($path) { |
|
| 197 | + return $this->getWrapperStorage()->isDeletable($path); |
|
| 198 | + } |
|
| 199 | + |
|
| 200 | + /** |
|
| 201 | + * check if a file can be shared |
|
| 202 | + * |
|
| 203 | + * @param string $path |
|
| 204 | + * @return bool |
|
| 205 | + */ |
|
| 206 | + public function isSharable($path) { |
|
| 207 | + return $this->getWrapperStorage()->isSharable($path); |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + /** |
|
| 211 | + * get the full permissions of a path. |
|
| 212 | + * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php |
|
| 213 | + * |
|
| 214 | + * @param string $path |
|
| 215 | + * @return int |
|
| 216 | + */ |
|
| 217 | + public function getPermissions($path) { |
|
| 218 | + return $this->getWrapperStorage()->getPermissions($path); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + /** |
|
| 222 | + * see https://www.php.net/manual/en/function.file_exists.php |
|
| 223 | + * |
|
| 224 | + * @param string $path |
|
| 225 | + * @return bool |
|
| 226 | + */ |
|
| 227 | + public function file_exists($path) { |
|
| 228 | + return $this->getWrapperStorage()->file_exists($path); |
|
| 229 | + } |
|
| 230 | + |
|
| 231 | + /** |
|
| 232 | + * see https://www.php.net/manual/en/function.filemtime.php |
|
| 233 | + * |
|
| 234 | + * @param string $path |
|
| 235 | + * @return int|bool |
|
| 236 | + */ |
|
| 237 | + public function filemtime($path) { |
|
| 238 | + return $this->getWrapperStorage()->filemtime($path); |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * see https://www.php.net/manual/en/function.file_get_contents.php |
|
| 243 | + * |
|
| 244 | + * @param string $path |
|
| 245 | + * @return string|bool |
|
| 246 | + */ |
|
| 247 | + public function file_get_contents($path) { |
|
| 248 | + return $this->getWrapperStorage()->file_get_contents($path); |
|
| 249 | + } |
|
| 250 | + |
|
| 251 | + /** |
|
| 252 | + * see https://www.php.net/manual/en/function.file_put_contents.php |
|
| 253 | + * |
|
| 254 | + * @param string $path |
|
| 255 | + * @param mixed $data |
|
| 256 | + * @return int|false |
|
| 257 | + */ |
|
| 258 | + public function file_put_contents($path, $data) { |
|
| 259 | + return $this->getWrapperStorage()->file_put_contents($path, $data); |
|
| 260 | + } |
|
| 261 | + |
|
| 262 | + /** |
|
| 263 | + * see https://www.php.net/manual/en/function.unlink.php |
|
| 264 | + * |
|
| 265 | + * @param string $path |
|
| 266 | + * @return bool |
|
| 267 | + */ |
|
| 268 | + public function unlink($path) { |
|
| 269 | + return $this->getWrapperStorage()->unlink($path); |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + /** |
|
| 273 | + * see https://www.php.net/manual/en/function.rename.php |
|
| 274 | + * |
|
| 275 | + * @param string $path1 |
|
| 276 | + * @param string $path2 |
|
| 277 | + * @return bool |
|
| 278 | + */ |
|
| 279 | + public function rename($path1, $path2) { |
|
| 280 | + return $this->getWrapperStorage()->rename($path1, $path2); |
|
| 281 | + } |
|
| 282 | + |
|
| 283 | + /** |
|
| 284 | + * see https://www.php.net/manual/en/function.copy.php |
|
| 285 | + * |
|
| 286 | + * @param string $path1 |
|
| 287 | + * @param string $path2 |
|
| 288 | + * @return bool |
|
| 289 | + */ |
|
| 290 | + public function copy($path1, $path2) { |
|
| 291 | + return $this->getWrapperStorage()->copy($path1, $path2); |
|
| 292 | + } |
|
| 293 | + |
|
| 294 | + /** |
|
| 295 | + * see https://www.php.net/manual/en/function.fopen.php |
|
| 296 | + * |
|
| 297 | + * @param string $path |
|
| 298 | + * @param string $mode |
|
| 299 | + * @return resource|bool |
|
| 300 | + */ |
|
| 301 | + public function fopen($path, $mode) { |
|
| 302 | + return $this->getWrapperStorage()->fopen($path, $mode); |
|
| 303 | + } |
|
| 304 | + |
|
| 305 | + /** |
|
| 306 | + * get the mimetype for a file or folder |
|
| 307 | + * The mimetype for a folder is required to be "httpd/unix-directory" |
|
| 308 | + * |
|
| 309 | + * @param string $path |
|
| 310 | + * @return string|bool |
|
| 311 | + */ |
|
| 312 | + public function getMimeType($path) { |
|
| 313 | + return $this->getWrapperStorage()->getMimeType($path); |
|
| 314 | + } |
|
| 315 | + |
|
| 316 | + /** |
|
| 317 | + * see https://www.php.net/manual/en/function.hash.php |
|
| 318 | + * |
|
| 319 | + * @param string $type |
|
| 320 | + * @param string $path |
|
| 321 | + * @param bool $raw |
|
| 322 | + * @return string|bool |
|
| 323 | + */ |
|
| 324 | + public function hash($type, $path, $raw = false) { |
|
| 325 | + return $this->getWrapperStorage()->hash($type, $path, $raw); |
|
| 326 | + } |
|
| 327 | + |
|
| 328 | + /** |
|
| 329 | + * see https://www.php.net/manual/en/function.free_space.php |
|
| 330 | + * |
|
| 331 | + * @param string $path |
|
| 332 | + * @return int|bool |
|
| 333 | + */ |
|
| 334 | + public function free_space($path) { |
|
| 335 | + return $this->getWrapperStorage()->free_space($path); |
|
| 336 | + } |
|
| 337 | + |
|
| 338 | + /** |
|
| 339 | + * search for occurrences of $query in file names |
|
| 340 | + * |
|
| 341 | + * @param string $query |
|
| 342 | + * @return array|bool |
|
| 343 | + */ |
|
| 344 | + public function search($query) { |
|
| 345 | + return $this->getWrapperStorage()->search($query); |
|
| 346 | + } |
|
| 347 | + |
|
| 348 | + /** |
|
| 349 | + * see https://www.php.net/manual/en/function.touch.php |
|
| 350 | + * If the backend does not support the operation, false should be returned |
|
| 351 | + * |
|
| 352 | + * @param string $path |
|
| 353 | + * @param int $mtime |
|
| 354 | + * @return bool |
|
| 355 | + */ |
|
| 356 | + public function touch($path, $mtime = null) { |
|
| 357 | + return $this->getWrapperStorage()->touch($path, $mtime); |
|
| 358 | + } |
|
| 359 | + |
|
| 360 | + /** |
|
| 361 | + * get the path to a local version of the file. |
|
| 362 | + * The local version of the file can be temporary and doesn't have to be persistent across requests |
|
| 363 | + * |
|
| 364 | + * @param string $path |
|
| 365 | + * @return string|bool |
|
| 366 | + */ |
|
| 367 | + public function getLocalFile($path) { |
|
| 368 | + return $this->getWrapperStorage()->getLocalFile($path); |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + /** |
|
| 372 | + * check if a file or folder has been updated since $time |
|
| 373 | + * |
|
| 374 | + * @param string $path |
|
| 375 | + * @param int $time |
|
| 376 | + * @return bool |
|
| 377 | + * |
|
| 378 | + * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. |
|
| 379 | + * returning true for other changes in the folder is optional |
|
| 380 | + */ |
|
| 381 | + public function hasUpdated($path, $time) { |
|
| 382 | + return $this->getWrapperStorage()->hasUpdated($path, $time); |
|
| 383 | + } |
|
| 384 | + |
|
| 385 | + /** |
|
| 386 | + * get a cache instance for the storage |
|
| 387 | + * |
|
| 388 | + * @param string $path |
|
| 389 | + * @param \OC\Files\Storage\Storage (optional) the storage to pass to the cache |
|
| 390 | + * @return \OC\Files\Cache\Cache |
|
| 391 | + */ |
|
| 392 | + public function getCache($path = '', $storage = null) { |
|
| 393 | + if (!$storage) { |
|
| 394 | + $storage = $this; |
|
| 395 | + } |
|
| 396 | + return $this->getWrapperStorage()->getCache($path, $storage); |
|
| 397 | + } |
|
| 398 | + |
|
| 399 | + /** |
|
| 400 | + * get a scanner instance for the storage |
|
| 401 | + * |
|
| 402 | + * @param string $path |
|
| 403 | + * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner |
|
| 404 | + * @return \OC\Files\Cache\Scanner |
|
| 405 | + */ |
|
| 406 | + public function getScanner($path = '', $storage = null) { |
|
| 407 | + if (!$storage) { |
|
| 408 | + $storage = $this; |
|
| 409 | + } |
|
| 410 | + return $this->getWrapperStorage()->getScanner($path, $storage); |
|
| 411 | + } |
|
| 412 | + |
|
| 413 | + |
|
| 414 | + /** |
|
| 415 | + * get the user id of the owner of a file or folder |
|
| 416 | + * |
|
| 417 | + * @param string $path |
|
| 418 | + * @return string |
|
| 419 | + */ |
|
| 420 | + public function getOwner($path) { |
|
| 421 | + return $this->getWrapperStorage()->getOwner($path); |
|
| 422 | + } |
|
| 423 | + |
|
| 424 | + /** |
|
| 425 | + * get a watcher instance for the cache |
|
| 426 | + * |
|
| 427 | + * @param string $path |
|
| 428 | + * @param \OC\Files\Storage\Storage (optional) the storage to pass to the watcher |
|
| 429 | + * @return \OC\Files\Cache\Watcher |
|
| 430 | + */ |
|
| 431 | + public function getWatcher($path = '', $storage = null) { |
|
| 432 | + if (!$storage) { |
|
| 433 | + $storage = $this; |
|
| 434 | + } |
|
| 435 | + return $this->getWrapperStorage()->getWatcher($path, $storage); |
|
| 436 | + } |
|
| 437 | + |
|
| 438 | + public function getPropagator($storage = null) { |
|
| 439 | + if (!$storage) { |
|
| 440 | + $storage = $this; |
|
| 441 | + } |
|
| 442 | + return $this->getWrapperStorage()->getPropagator($storage); |
|
| 443 | + } |
|
| 444 | + |
|
| 445 | + public function getUpdater($storage = null) { |
|
| 446 | + if (!$storage) { |
|
| 447 | + $storage = $this; |
|
| 448 | + } |
|
| 449 | + return $this->getWrapperStorage()->getUpdater($storage); |
|
| 450 | + } |
|
| 451 | + |
|
| 452 | + /** |
|
| 453 | + * @return \OC\Files\Cache\Storage |
|
| 454 | + */ |
|
| 455 | + public function getStorageCache() { |
|
| 456 | + return $this->getWrapperStorage()->getStorageCache(); |
|
| 457 | + } |
|
| 458 | + |
|
| 459 | + /** |
|
| 460 | + * get the ETag for a file or folder |
|
| 461 | + * |
|
| 462 | + * @param string $path |
|
| 463 | + * @return string|bool |
|
| 464 | + */ |
|
| 465 | + public function getETag($path) { |
|
| 466 | + return $this->getWrapperStorage()->getETag($path); |
|
| 467 | + } |
|
| 468 | + |
|
| 469 | + /** |
|
| 470 | + * Returns true |
|
| 471 | + * |
|
| 472 | + * @return true |
|
| 473 | + */ |
|
| 474 | + public function test() { |
|
| 475 | + return $this->getWrapperStorage()->test(); |
|
| 476 | + } |
|
| 477 | + |
|
| 478 | + /** |
|
| 479 | + * Returns the wrapped storage's value for isLocal() |
|
| 480 | + * |
|
| 481 | + * @return bool wrapped storage's isLocal() value |
|
| 482 | + */ |
|
| 483 | + public function isLocal() { |
|
| 484 | + return $this->getWrapperStorage()->isLocal(); |
|
| 485 | + } |
|
| 486 | + |
|
| 487 | + /** |
|
| 488 | + * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class |
|
| 489 | + * |
|
| 490 | + * @param string $class |
|
| 491 | + * @return bool |
|
| 492 | + */ |
|
| 493 | + public function instanceOfStorage($class) { |
|
| 494 | + if (ltrim($class, '\\') === 'OC\Files\Storage\Shared') { |
|
| 495 | + // FIXME Temporary fix to keep existing checks working |
|
| 496 | + $class = '\OCA\Files_Sharing\SharedStorage'; |
|
| 497 | + } |
|
| 498 | + return is_a($this, $class) or $this->getWrapperStorage()->instanceOfStorage($class); |
|
| 499 | + } |
|
| 500 | + |
|
| 501 | + /** |
|
| 502 | + * Pass any methods custom to specific storage implementations to the wrapped storage |
|
| 503 | + * |
|
| 504 | + * @param string $method |
|
| 505 | + * @param array $args |
|
| 506 | + * @return mixed |
|
| 507 | + */ |
|
| 508 | + public function __call($method, $args) { |
|
| 509 | + return call_user_func_array([$this->getWrapperStorage(), $method], $args); |
|
| 510 | + } |
|
| 511 | + |
|
| 512 | + /** |
|
| 513 | + * A custom storage implementation can return an url for direct download of a give file. |
|
| 514 | + * |
|
| 515 | + * For now the returned array can hold the parameter url - in future more attributes might follow. |
|
| 516 | + * |
|
| 517 | + * @param string $path |
|
| 518 | + * @return array|bool |
|
| 519 | + */ |
|
| 520 | + public function getDirectDownload($path) { |
|
| 521 | + return $this->getWrapperStorage()->getDirectDownload($path); |
|
| 522 | + } |
|
| 523 | + |
|
| 524 | + /** |
|
| 525 | + * Get availability of the storage |
|
| 526 | + * |
|
| 527 | + * @return array [ available, last_checked ] |
|
| 528 | + */ |
|
| 529 | + public function getAvailability() { |
|
| 530 | + return $this->getWrapperStorage()->getAvailability(); |
|
| 531 | + } |
|
| 532 | + |
|
| 533 | + /** |
|
| 534 | + * Set availability of the storage |
|
| 535 | + * |
|
| 536 | + * @param bool $isAvailable |
|
| 537 | + */ |
|
| 538 | + public function setAvailability($isAvailable) { |
|
| 539 | + $this->getWrapperStorage()->setAvailability($isAvailable); |
|
| 540 | + } |
|
| 541 | + |
|
| 542 | + /** |
|
| 543 | + * @param string $path the path of the target folder |
|
| 544 | + * @param string $fileName the name of the file itself |
|
| 545 | + * @return void |
|
| 546 | + * @throws InvalidPathException |
|
| 547 | + */ |
|
| 548 | + public function verifyPath($path, $fileName) { |
|
| 549 | + $this->getWrapperStorage()->verifyPath($path, $fileName); |
|
| 550 | + } |
|
| 551 | + |
|
| 552 | + /** |
|
| 553 | + * @param IStorage $sourceStorage |
|
| 554 | + * @param string $sourceInternalPath |
|
| 555 | + * @param string $targetInternalPath |
|
| 556 | + * @return bool |
|
| 557 | + */ |
|
| 558 | + public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { |
|
| 559 | + if ($sourceStorage === $this) { |
|
| 560 | + return $this->copy($sourceInternalPath, $targetInternalPath); |
|
| 561 | + } |
|
| 562 | + |
|
| 563 | + return $this->getWrapperStorage()->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); |
|
| 564 | + } |
|
| 565 | + |
|
| 566 | + /** |
|
| 567 | + * @param IStorage $sourceStorage |
|
| 568 | + * @param string $sourceInternalPath |
|
| 569 | + * @param string $targetInternalPath |
|
| 570 | + * @return bool |
|
| 571 | + */ |
|
| 572 | + public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { |
|
| 573 | + if ($sourceStorage === $this) { |
|
| 574 | + return $this->rename($sourceInternalPath, $targetInternalPath); |
|
| 575 | + } |
|
| 576 | + |
|
| 577 | + return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); |
|
| 578 | + } |
|
| 579 | + |
|
| 580 | + /** |
|
| 581 | + * @param string $path |
|
| 582 | + * @return array |
|
| 583 | + */ |
|
| 584 | + public function getMetaData($path) { |
|
| 585 | + return $this->getWrapperStorage()->getMetaData($path); |
|
| 586 | + } |
|
| 587 | + |
|
| 588 | + /** |
|
| 589 | + * @param string $path |
|
| 590 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 591 | + * @param \OCP\Lock\ILockingProvider $provider |
|
| 592 | + * @throws \OCP\Lock\LockedException |
|
| 593 | + */ |
|
| 594 | + public function acquireLock($path, $type, ILockingProvider $provider) { |
|
| 595 | + if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 596 | + $this->getWrapperStorage()->acquireLock($path, $type, $provider); |
|
| 597 | + } |
|
| 598 | + } |
|
| 599 | + |
|
| 600 | + /** |
|
| 601 | + * @param string $path |
|
| 602 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 603 | + * @param \OCP\Lock\ILockingProvider $provider |
|
| 604 | + */ |
|
| 605 | + public function releaseLock($path, $type, ILockingProvider $provider) { |
|
| 606 | + if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 607 | + $this->getWrapperStorage()->releaseLock($path, $type, $provider); |
|
| 608 | + } |
|
| 609 | + } |
|
| 610 | + |
|
| 611 | + /** |
|
| 612 | + * @param string $path |
|
| 613 | + * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE |
|
| 614 | + * @param \OCP\Lock\ILockingProvider $provider |
|
| 615 | + */ |
|
| 616 | + public function changeLock($path, $type, ILockingProvider $provider) { |
|
| 617 | + if ($this->getWrapperStorage()->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) { |
|
| 618 | + $this->getWrapperStorage()->changeLock($path, $type, $provider); |
|
| 619 | + } |
|
| 620 | + } |
|
| 621 | + |
|
| 622 | + /** |
|
| 623 | + * @return bool |
|
| 624 | + */ |
|
| 625 | + public function needsPartFile() { |
|
| 626 | + return $this->getWrapperStorage()->needsPartFile(); |
|
| 627 | + } |
|
| 628 | + |
|
| 629 | + public function writeStream(string $path, $stream, int $size = null): int { |
|
| 630 | + $storage = $this->getWrapperStorage(); |
|
| 631 | + if ($storage->instanceOfStorage(IWriteStreamStorage::class)) { |
|
| 632 | + /** @var IWriteStreamStorage $storage */ |
|
| 633 | + return $storage->writeStream($path, $stream, $size); |
|
| 634 | + } else { |
|
| 635 | + $target = $this->fopen($path, 'w'); |
|
| 636 | + [$count, $result] = \OC_Helper::streamCopy($stream, $target); |
|
| 637 | + fclose($stream); |
|
| 638 | + fclose($target); |
|
| 639 | + return $count; |
|
| 640 | + } |
|
| 641 | + } |
|
| 642 | + |
|
| 643 | + public function getDirectoryContent($directory): \Traversable { |
|
| 644 | + return $this->getWrapperStorage()->getDirectoryContent($directory); |
|
| 645 | + } |
|
| 646 | 646 | } |