@@ -32,368 +32,368 @@ |
||
| 32 | 32 | * } |
| 33 | 33 | */ |
| 34 | 34 | class OC_Helper { |
| 35 | - private static ?ICacheFactory $cacheFactory = null; |
|
| 36 | - private static ?bool $quotaIncludeExternalStorage = null; |
|
| 37 | - |
|
| 38 | - /** |
|
| 39 | - * Recursive copying of folders |
|
| 40 | - * @param string $src source folder |
|
| 41 | - * @param string $dest target folder |
|
| 42 | - * @return void |
|
| 43 | - * @deprecated 32.0.0 - use \OCP\Files\Folder::copy |
|
| 44 | - */ |
|
| 45 | - public static function copyr($src, $dest) { |
|
| 46 | - if (!file_exists($src)) { |
|
| 47 | - return; |
|
| 48 | - } |
|
| 49 | - |
|
| 50 | - if (is_dir($src)) { |
|
| 51 | - if (!is_dir($dest)) { |
|
| 52 | - mkdir($dest); |
|
| 53 | - } |
|
| 54 | - $files = scandir($src); |
|
| 55 | - foreach ($files as $file) { |
|
| 56 | - if ($file != '.' && $file != '..') { |
|
| 57 | - self::copyr("$src/$file", "$dest/$file"); |
|
| 58 | - } |
|
| 59 | - } |
|
| 60 | - } else { |
|
| 61 | - $validator = \OCP\Server::get(FilenameValidator::class); |
|
| 62 | - if (!$validator->isForbidden($src)) { |
|
| 63 | - copy($src, $dest); |
|
| 64 | - } |
|
| 65 | - } |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - /** |
|
| 69 | - * detect if a given program is found in the search PATH |
|
| 70 | - * |
|
| 71 | - * @param string $name |
|
| 72 | - * @param bool $path |
|
| 73 | - * @internal param string $program name |
|
| 74 | - * @internal param string $optional search path, defaults to $PATH |
|
| 75 | - * @return bool true if executable program found in path |
|
| 76 | - * @deprecated 32.0.0 use the \OCP\IBinaryFinder |
|
| 77 | - */ |
|
| 78 | - public static function canExecute($name, $path = false) { |
|
| 79 | - // path defaults to PATH from environment if not set |
|
| 80 | - if ($path === false) { |
|
| 81 | - $path = getenv('PATH'); |
|
| 82 | - } |
|
| 83 | - // we look for an executable file of that name |
|
| 84 | - $exts = ['']; |
|
| 85 | - $check_fn = 'is_executable'; |
|
| 86 | - // Default check will be done with $path directories : |
|
| 87 | - $dirs = explode(PATH_SEPARATOR, (string)$path); |
|
| 88 | - // WARNING : We have to check if open_basedir is enabled : |
|
| 89 | - $obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir'); |
|
| 90 | - if ($obd != 'none') { |
|
| 91 | - $obd_values = explode(PATH_SEPARATOR, $obd); |
|
| 92 | - if (count($obd_values) > 0 && $obd_values[0]) { |
|
| 93 | - // open_basedir is in effect ! |
|
| 94 | - // We need to check if the program is in one of these dirs : |
|
| 95 | - $dirs = $obd_values; |
|
| 96 | - } |
|
| 97 | - } |
|
| 98 | - foreach ($dirs as $dir) { |
|
| 99 | - foreach ($exts as $ext) { |
|
| 100 | - if ($check_fn("$dir/$name" . $ext)) { |
|
| 101 | - return true; |
|
| 102 | - } |
|
| 103 | - } |
|
| 104 | - } |
|
| 105 | - return false; |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * Adds a suffix to the name in case the file exists |
|
| 110 | - * |
|
| 111 | - * @param string $path |
|
| 112 | - * @param string $filename |
|
| 113 | - * @return string |
|
| 114 | - */ |
|
| 115 | - public static function buildNotExistingFileName($path, $filename) { |
|
| 116 | - $view = \OC\Files\Filesystem::getView(); |
|
| 117 | - return self::buildNotExistingFileNameForView($path, $filename, $view); |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - /** |
|
| 121 | - * Adds a suffix to the name in case the file exists |
|
| 122 | - * |
|
| 123 | - * @param string $path |
|
| 124 | - * @param string $filename |
|
| 125 | - * @return string |
|
| 126 | - */ |
|
| 127 | - public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) { |
|
| 128 | - if ($path === '/') { |
|
| 129 | - $path = ''; |
|
| 130 | - } |
|
| 131 | - if ($pos = strrpos($filename, '.')) { |
|
| 132 | - $name = substr($filename, 0, $pos); |
|
| 133 | - $ext = substr($filename, $pos); |
|
| 134 | - } else { |
|
| 135 | - $name = $filename; |
|
| 136 | - $ext = ''; |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - $newpath = $path . '/' . $filename; |
|
| 140 | - if ($view->file_exists($newpath)) { |
|
| 141 | - if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) { |
|
| 142 | - //Replace the last "(number)" with "(number+1)" |
|
| 143 | - $last_match = count($matches[0]) - 1; |
|
| 144 | - $counter = $matches[1][$last_match][0] + 1; |
|
| 145 | - $offset = $matches[0][$last_match][1]; |
|
| 146 | - $match_length = strlen($matches[0][$last_match][0]); |
|
| 147 | - } else { |
|
| 148 | - $counter = 2; |
|
| 149 | - $match_length = 0; |
|
| 150 | - $offset = false; |
|
| 151 | - } |
|
| 152 | - do { |
|
| 153 | - if ($offset) { |
|
| 154 | - //Replace the last "(number)" with "(number+1)" |
|
| 155 | - $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length); |
|
| 156 | - } else { |
|
| 157 | - $newname = $name . ' (' . $counter . ')'; |
|
| 158 | - } |
|
| 159 | - $newpath = $path . '/' . $newname . $ext; |
|
| 160 | - $counter++; |
|
| 161 | - } while ($view->file_exists($newpath)); |
|
| 162 | - } |
|
| 163 | - |
|
| 164 | - return $newpath; |
|
| 165 | - } |
|
| 166 | - |
|
| 167 | - /** |
|
| 168 | - * Checks if a function is available |
|
| 169 | - * |
|
| 170 | - * @deprecated 25.0.0 use \OCP\Util::isFunctionEnabled instead |
|
| 171 | - */ |
|
| 172 | - public static function is_function_enabled(string $function_name): bool { |
|
| 173 | - return Util::isFunctionEnabled($function_name); |
|
| 174 | - } |
|
| 175 | - |
|
| 176 | - /** |
|
| 177 | - * Try to find a program |
|
| 178 | - * @deprecated 25.0.0 Use \OCP\IBinaryFinder directly |
|
| 179 | - */ |
|
| 180 | - public static function findBinaryPath(string $program): ?string { |
|
| 181 | - $result = Server::get(IBinaryFinder::class)->findBinaryPath($program); |
|
| 182 | - return $result !== false ? $result : null; |
|
| 183 | - } |
|
| 184 | - |
|
| 185 | - /** |
|
| 186 | - * Calculate the disc space for the given path |
|
| 187 | - * |
|
| 188 | - * BEWARE: this requires that Util::setupFS() was called |
|
| 189 | - * already ! |
|
| 190 | - * |
|
| 191 | - * @param string $path |
|
| 192 | - * @param \OCP\Files\FileInfo $rootInfo (optional) |
|
| 193 | - * @param bool $includeMountPoints whether to include mount points in the size calculation |
|
| 194 | - * @param bool $useCache whether to use the cached quota values |
|
| 195 | - * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct |
|
| 196 | - * @return StorageInfo |
|
| 197 | - * @throws \OCP\Files\NotFoundException |
|
| 198 | - */ |
|
| 199 | - public static function getStorageInfo($path, $rootInfo = null, $includeMountPoints = true, $useCache = true) { |
|
| 200 | - if (!self::$cacheFactory) { |
|
| 201 | - self::$cacheFactory = Server::get(ICacheFactory::class); |
|
| 202 | - } |
|
| 203 | - $memcache = self::$cacheFactory->createLocal('storage_info'); |
|
| 204 | - |
|
| 205 | - // return storage info without adding mount points |
|
| 206 | - if (self::$quotaIncludeExternalStorage === null) { |
|
| 207 | - self::$quotaIncludeExternalStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false); |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - $view = Filesystem::getView(); |
|
| 211 | - if (!$view) { |
|
| 212 | - throw new \OCP\Files\NotFoundException(); |
|
| 213 | - } |
|
| 214 | - $fullPath = Filesystem::normalizePath($view->getAbsolutePath($path)); |
|
| 215 | - |
|
| 216 | - $cacheKey = $fullPath . '::' . ($includeMountPoints ? 'include' : 'exclude'); |
|
| 217 | - if ($useCache) { |
|
| 218 | - $cached = $memcache->get($cacheKey); |
|
| 219 | - if ($cached) { |
|
| 220 | - return $cached; |
|
| 221 | - } |
|
| 222 | - } |
|
| 223 | - |
|
| 224 | - if (!$rootInfo) { |
|
| 225 | - $rootInfo = \OC\Files\Filesystem::getFileInfo($path, self::$quotaIncludeExternalStorage ? 'ext' : false); |
|
| 226 | - } |
|
| 227 | - if (!$rootInfo instanceof \OCP\Files\FileInfo) { |
|
| 228 | - throw new \OCP\Files\NotFoundException('The root directory of the user\'s files is missing'); |
|
| 229 | - } |
|
| 230 | - $used = $rootInfo->getSize($includeMountPoints); |
|
| 231 | - if ($used < 0) { |
|
| 232 | - $used = 0.0; |
|
| 233 | - } |
|
| 234 | - /** @var int|float $quota */ |
|
| 235 | - $quota = \OCP\Files\FileInfo::SPACE_UNLIMITED; |
|
| 236 | - $mount = $rootInfo->getMountPoint(); |
|
| 237 | - $storage = $mount->getStorage(); |
|
| 238 | - $sourceStorage = $storage; |
|
| 239 | - if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) { |
|
| 240 | - self::$quotaIncludeExternalStorage = false; |
|
| 241 | - } |
|
| 242 | - if (self::$quotaIncludeExternalStorage) { |
|
| 243 | - if ($storage->instanceOfStorage('\OC\Files\Storage\Home') |
|
| 244 | - || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage') |
|
| 245 | - ) { |
|
| 246 | - /** @var \OC\Files\Storage\Home $storage */ |
|
| 247 | - $user = $storage->getUser(); |
|
| 248 | - } else { |
|
| 249 | - $user = \OC::$server->getUserSession()->getUser(); |
|
| 250 | - } |
|
| 251 | - $quota = $user?->getQuotaBytes() ?? \OCP\Files\FileInfo::SPACE_UNKNOWN; |
|
| 252 | - if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) { |
|
| 253 | - // always get free space / total space from root + mount points |
|
| 254 | - return self::getGlobalStorageInfo($quota, $user, $mount); |
|
| 255 | - } |
|
| 256 | - } |
|
| 257 | - |
|
| 258 | - // TODO: need a better way to get total space from storage |
|
| 259 | - if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) { |
|
| 260 | - /** @var \OC\Files\Storage\Wrapper\Quota $storage */ |
|
| 261 | - $quota = $sourceStorage->getQuota(); |
|
| 262 | - } |
|
| 263 | - try { |
|
| 264 | - $free = $sourceStorage->free_space($rootInfo->getInternalPath()); |
|
| 265 | - if (is_bool($free)) { |
|
| 266 | - $free = 0.0; |
|
| 267 | - } |
|
| 268 | - } catch (\Exception $e) { |
|
| 269 | - if ($path === '') { |
|
| 270 | - throw $e; |
|
| 271 | - } |
|
| 272 | - /** @var LoggerInterface $logger */ |
|
| 273 | - $logger = \OC::$server->get(LoggerInterface::class); |
|
| 274 | - $logger->warning('Error while getting quota info, using root quota', ['exception' => $e]); |
|
| 275 | - $rootInfo = self::getStorageInfo(''); |
|
| 276 | - $memcache->set($cacheKey, $rootInfo, 5 * 60); |
|
| 277 | - return $rootInfo; |
|
| 278 | - } |
|
| 279 | - if ($free >= 0) { |
|
| 280 | - $total = $free + $used; |
|
| 281 | - } else { |
|
| 282 | - $total = $free; //either unknown or unlimited |
|
| 283 | - } |
|
| 284 | - if ($total > 0) { |
|
| 285 | - if ($quota > 0 && $total > $quota) { |
|
| 286 | - $total = $quota; |
|
| 287 | - } |
|
| 288 | - // prevent division by zero or error codes (negative values) |
|
| 289 | - $relative = round(($used / $total) * 10000) / 100; |
|
| 290 | - } else { |
|
| 291 | - $relative = 0; |
|
| 292 | - } |
|
| 293 | - |
|
| 294 | - /* |
|
| 35 | + private static ?ICacheFactory $cacheFactory = null; |
|
| 36 | + private static ?bool $quotaIncludeExternalStorage = null; |
|
| 37 | + |
|
| 38 | + /** |
|
| 39 | + * Recursive copying of folders |
|
| 40 | + * @param string $src source folder |
|
| 41 | + * @param string $dest target folder |
|
| 42 | + * @return void |
|
| 43 | + * @deprecated 32.0.0 - use \OCP\Files\Folder::copy |
|
| 44 | + */ |
|
| 45 | + public static function copyr($src, $dest) { |
|
| 46 | + if (!file_exists($src)) { |
|
| 47 | + return; |
|
| 48 | + } |
|
| 49 | + |
|
| 50 | + if (is_dir($src)) { |
|
| 51 | + if (!is_dir($dest)) { |
|
| 52 | + mkdir($dest); |
|
| 53 | + } |
|
| 54 | + $files = scandir($src); |
|
| 55 | + foreach ($files as $file) { |
|
| 56 | + if ($file != '.' && $file != '..') { |
|
| 57 | + self::copyr("$src/$file", "$dest/$file"); |
|
| 58 | + } |
|
| 59 | + } |
|
| 60 | + } else { |
|
| 61 | + $validator = \OCP\Server::get(FilenameValidator::class); |
|
| 62 | + if (!$validator->isForbidden($src)) { |
|
| 63 | + copy($src, $dest); |
|
| 64 | + } |
|
| 65 | + } |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + /** |
|
| 69 | + * detect if a given program is found in the search PATH |
|
| 70 | + * |
|
| 71 | + * @param string $name |
|
| 72 | + * @param bool $path |
|
| 73 | + * @internal param string $program name |
|
| 74 | + * @internal param string $optional search path, defaults to $PATH |
|
| 75 | + * @return bool true if executable program found in path |
|
| 76 | + * @deprecated 32.0.0 use the \OCP\IBinaryFinder |
|
| 77 | + */ |
|
| 78 | + public static function canExecute($name, $path = false) { |
|
| 79 | + // path defaults to PATH from environment if not set |
|
| 80 | + if ($path === false) { |
|
| 81 | + $path = getenv('PATH'); |
|
| 82 | + } |
|
| 83 | + // we look for an executable file of that name |
|
| 84 | + $exts = ['']; |
|
| 85 | + $check_fn = 'is_executable'; |
|
| 86 | + // Default check will be done with $path directories : |
|
| 87 | + $dirs = explode(PATH_SEPARATOR, (string)$path); |
|
| 88 | + // WARNING : We have to check if open_basedir is enabled : |
|
| 89 | + $obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir'); |
|
| 90 | + if ($obd != 'none') { |
|
| 91 | + $obd_values = explode(PATH_SEPARATOR, $obd); |
|
| 92 | + if (count($obd_values) > 0 && $obd_values[0]) { |
|
| 93 | + // open_basedir is in effect ! |
|
| 94 | + // We need to check if the program is in one of these dirs : |
|
| 95 | + $dirs = $obd_values; |
|
| 96 | + } |
|
| 97 | + } |
|
| 98 | + foreach ($dirs as $dir) { |
|
| 99 | + foreach ($exts as $ext) { |
|
| 100 | + if ($check_fn("$dir/$name" . $ext)) { |
|
| 101 | + return true; |
|
| 102 | + } |
|
| 103 | + } |
|
| 104 | + } |
|
| 105 | + return false; |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * Adds a suffix to the name in case the file exists |
|
| 110 | + * |
|
| 111 | + * @param string $path |
|
| 112 | + * @param string $filename |
|
| 113 | + * @return string |
|
| 114 | + */ |
|
| 115 | + public static function buildNotExistingFileName($path, $filename) { |
|
| 116 | + $view = \OC\Files\Filesystem::getView(); |
|
| 117 | + return self::buildNotExistingFileNameForView($path, $filename, $view); |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + /** |
|
| 121 | + * Adds a suffix to the name in case the file exists |
|
| 122 | + * |
|
| 123 | + * @param string $path |
|
| 124 | + * @param string $filename |
|
| 125 | + * @return string |
|
| 126 | + */ |
|
| 127 | + public static function buildNotExistingFileNameForView($path, $filename, \OC\Files\View $view) { |
|
| 128 | + if ($path === '/') { |
|
| 129 | + $path = ''; |
|
| 130 | + } |
|
| 131 | + if ($pos = strrpos($filename, '.')) { |
|
| 132 | + $name = substr($filename, 0, $pos); |
|
| 133 | + $ext = substr($filename, $pos); |
|
| 134 | + } else { |
|
| 135 | + $name = $filename; |
|
| 136 | + $ext = ''; |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + $newpath = $path . '/' . $filename; |
|
| 140 | + if ($view->file_exists($newpath)) { |
|
| 141 | + if (preg_match_all('/\((\d+)\)/', $name, $matches, PREG_OFFSET_CAPTURE)) { |
|
| 142 | + //Replace the last "(number)" with "(number+1)" |
|
| 143 | + $last_match = count($matches[0]) - 1; |
|
| 144 | + $counter = $matches[1][$last_match][0] + 1; |
|
| 145 | + $offset = $matches[0][$last_match][1]; |
|
| 146 | + $match_length = strlen($matches[0][$last_match][0]); |
|
| 147 | + } else { |
|
| 148 | + $counter = 2; |
|
| 149 | + $match_length = 0; |
|
| 150 | + $offset = false; |
|
| 151 | + } |
|
| 152 | + do { |
|
| 153 | + if ($offset) { |
|
| 154 | + //Replace the last "(number)" with "(number+1)" |
|
| 155 | + $newname = substr_replace($name, '(' . $counter . ')', $offset, $match_length); |
|
| 156 | + } else { |
|
| 157 | + $newname = $name . ' (' . $counter . ')'; |
|
| 158 | + } |
|
| 159 | + $newpath = $path . '/' . $newname . $ext; |
|
| 160 | + $counter++; |
|
| 161 | + } while ($view->file_exists($newpath)); |
|
| 162 | + } |
|
| 163 | + |
|
| 164 | + return $newpath; |
|
| 165 | + } |
|
| 166 | + |
|
| 167 | + /** |
|
| 168 | + * Checks if a function is available |
|
| 169 | + * |
|
| 170 | + * @deprecated 25.0.0 use \OCP\Util::isFunctionEnabled instead |
|
| 171 | + */ |
|
| 172 | + public static function is_function_enabled(string $function_name): bool { |
|
| 173 | + return Util::isFunctionEnabled($function_name); |
|
| 174 | + } |
|
| 175 | + |
|
| 176 | + /** |
|
| 177 | + * Try to find a program |
|
| 178 | + * @deprecated 25.0.0 Use \OCP\IBinaryFinder directly |
|
| 179 | + */ |
|
| 180 | + public static function findBinaryPath(string $program): ?string { |
|
| 181 | + $result = Server::get(IBinaryFinder::class)->findBinaryPath($program); |
|
| 182 | + return $result !== false ? $result : null; |
|
| 183 | + } |
|
| 184 | + |
|
| 185 | + /** |
|
| 186 | + * Calculate the disc space for the given path |
|
| 187 | + * |
|
| 188 | + * BEWARE: this requires that Util::setupFS() was called |
|
| 189 | + * already ! |
|
| 190 | + * |
|
| 191 | + * @param string $path |
|
| 192 | + * @param \OCP\Files\FileInfo $rootInfo (optional) |
|
| 193 | + * @param bool $includeMountPoints whether to include mount points in the size calculation |
|
| 194 | + * @param bool $useCache whether to use the cached quota values |
|
| 195 | + * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct |
|
| 196 | + * @return StorageInfo |
|
| 197 | + * @throws \OCP\Files\NotFoundException |
|
| 198 | + */ |
|
| 199 | + public static function getStorageInfo($path, $rootInfo = null, $includeMountPoints = true, $useCache = true) { |
|
| 200 | + if (!self::$cacheFactory) { |
|
| 201 | + self::$cacheFactory = Server::get(ICacheFactory::class); |
|
| 202 | + } |
|
| 203 | + $memcache = self::$cacheFactory->createLocal('storage_info'); |
|
| 204 | + |
|
| 205 | + // return storage info without adding mount points |
|
| 206 | + if (self::$quotaIncludeExternalStorage === null) { |
|
| 207 | + self::$quotaIncludeExternalStorage = \OC::$server->getSystemConfig()->getValue('quota_include_external_storage', false); |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + $view = Filesystem::getView(); |
|
| 211 | + if (!$view) { |
|
| 212 | + throw new \OCP\Files\NotFoundException(); |
|
| 213 | + } |
|
| 214 | + $fullPath = Filesystem::normalizePath($view->getAbsolutePath($path)); |
|
| 215 | + |
|
| 216 | + $cacheKey = $fullPath . '::' . ($includeMountPoints ? 'include' : 'exclude'); |
|
| 217 | + if ($useCache) { |
|
| 218 | + $cached = $memcache->get($cacheKey); |
|
| 219 | + if ($cached) { |
|
| 220 | + return $cached; |
|
| 221 | + } |
|
| 222 | + } |
|
| 223 | + |
|
| 224 | + if (!$rootInfo) { |
|
| 225 | + $rootInfo = \OC\Files\Filesystem::getFileInfo($path, self::$quotaIncludeExternalStorage ? 'ext' : false); |
|
| 226 | + } |
|
| 227 | + if (!$rootInfo instanceof \OCP\Files\FileInfo) { |
|
| 228 | + throw new \OCP\Files\NotFoundException('The root directory of the user\'s files is missing'); |
|
| 229 | + } |
|
| 230 | + $used = $rootInfo->getSize($includeMountPoints); |
|
| 231 | + if ($used < 0) { |
|
| 232 | + $used = 0.0; |
|
| 233 | + } |
|
| 234 | + /** @var int|float $quota */ |
|
| 235 | + $quota = \OCP\Files\FileInfo::SPACE_UNLIMITED; |
|
| 236 | + $mount = $rootInfo->getMountPoint(); |
|
| 237 | + $storage = $mount->getStorage(); |
|
| 238 | + $sourceStorage = $storage; |
|
| 239 | + if ($storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) { |
|
| 240 | + self::$quotaIncludeExternalStorage = false; |
|
| 241 | + } |
|
| 242 | + if (self::$quotaIncludeExternalStorage) { |
|
| 243 | + if ($storage->instanceOfStorage('\OC\Files\Storage\Home') |
|
| 244 | + || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage') |
|
| 245 | + ) { |
|
| 246 | + /** @var \OC\Files\Storage\Home $storage */ |
|
| 247 | + $user = $storage->getUser(); |
|
| 248 | + } else { |
|
| 249 | + $user = \OC::$server->getUserSession()->getUser(); |
|
| 250 | + } |
|
| 251 | + $quota = $user?->getQuotaBytes() ?? \OCP\Files\FileInfo::SPACE_UNKNOWN; |
|
| 252 | + if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) { |
|
| 253 | + // always get free space / total space from root + mount points |
|
| 254 | + return self::getGlobalStorageInfo($quota, $user, $mount); |
|
| 255 | + } |
|
| 256 | + } |
|
| 257 | + |
|
| 258 | + // TODO: need a better way to get total space from storage |
|
| 259 | + if ($sourceStorage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) { |
|
| 260 | + /** @var \OC\Files\Storage\Wrapper\Quota $storage */ |
|
| 261 | + $quota = $sourceStorage->getQuota(); |
|
| 262 | + } |
|
| 263 | + try { |
|
| 264 | + $free = $sourceStorage->free_space($rootInfo->getInternalPath()); |
|
| 265 | + if (is_bool($free)) { |
|
| 266 | + $free = 0.0; |
|
| 267 | + } |
|
| 268 | + } catch (\Exception $e) { |
|
| 269 | + if ($path === '') { |
|
| 270 | + throw $e; |
|
| 271 | + } |
|
| 272 | + /** @var LoggerInterface $logger */ |
|
| 273 | + $logger = \OC::$server->get(LoggerInterface::class); |
|
| 274 | + $logger->warning('Error while getting quota info, using root quota', ['exception' => $e]); |
|
| 275 | + $rootInfo = self::getStorageInfo(''); |
|
| 276 | + $memcache->set($cacheKey, $rootInfo, 5 * 60); |
|
| 277 | + return $rootInfo; |
|
| 278 | + } |
|
| 279 | + if ($free >= 0) { |
|
| 280 | + $total = $free + $used; |
|
| 281 | + } else { |
|
| 282 | + $total = $free; //either unknown or unlimited |
|
| 283 | + } |
|
| 284 | + if ($total > 0) { |
|
| 285 | + if ($quota > 0 && $total > $quota) { |
|
| 286 | + $total = $quota; |
|
| 287 | + } |
|
| 288 | + // prevent division by zero or error codes (negative values) |
|
| 289 | + $relative = round(($used / $total) * 10000) / 100; |
|
| 290 | + } else { |
|
| 291 | + $relative = 0; |
|
| 292 | + } |
|
| 293 | + |
|
| 294 | + /* |
|
| 295 | 295 | * \OCA\Files_Sharing\External\Storage returns the cloud ID as the owner for the storage. |
| 296 | 296 | * It is unnecessary to query the user manager for the display name, as it won't have this information. |
| 297 | 297 | */ |
| 298 | - $isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class); |
|
| 299 | - |
|
| 300 | - $ownerId = $storage->getOwner($path); |
|
| 301 | - $ownerDisplayName = ''; |
|
| 302 | - |
|
| 303 | - if ($isRemoteShare === false && $ownerId !== false) { |
|
| 304 | - $ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? ''; |
|
| 305 | - } |
|
| 306 | - |
|
| 307 | - if (substr_count($mount->getMountPoint(), '/') < 3) { |
|
| 308 | - $mountPoint = ''; |
|
| 309 | - } else { |
|
| 310 | - [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4); |
|
| 311 | - } |
|
| 312 | - |
|
| 313 | - $info = [ |
|
| 314 | - 'free' => $free, |
|
| 315 | - 'used' => $used, |
|
| 316 | - 'quota' => $quota, |
|
| 317 | - 'total' => $total, |
|
| 318 | - 'relative' => $relative, |
|
| 319 | - 'owner' => $ownerId, |
|
| 320 | - 'ownerDisplayName' => $ownerDisplayName, |
|
| 321 | - 'mountType' => $mount->getMountType(), |
|
| 322 | - 'mountPoint' => trim($mountPoint, '/'), |
|
| 323 | - ]; |
|
| 324 | - |
|
| 325 | - if ($isRemoteShare === false && $ownerId !== false && $path === '/') { |
|
| 326 | - // If path is root, store this as last known quota usage for this user |
|
| 327 | - \OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative); |
|
| 328 | - } |
|
| 329 | - |
|
| 330 | - $memcache->set($cacheKey, $info, 5 * 60); |
|
| 331 | - |
|
| 332 | - return $info; |
|
| 333 | - } |
|
| 334 | - |
|
| 335 | - /** |
|
| 336 | - * Get storage info including all mount points and quota |
|
| 337 | - * |
|
| 338 | - * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct |
|
| 339 | - * @return StorageInfo |
|
| 340 | - */ |
|
| 341 | - private static function getGlobalStorageInfo(int|float $quota, IUser $user, IMountPoint $mount): array { |
|
| 342 | - $rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext'); |
|
| 343 | - /** @var int|float $used */ |
|
| 344 | - $used = $rootInfo['size']; |
|
| 345 | - if ($used < 0) { |
|
| 346 | - $used = 0.0; |
|
| 347 | - } |
|
| 348 | - |
|
| 349 | - $total = $quota; |
|
| 350 | - /** @var int|float $free */ |
|
| 351 | - $free = $quota - $used; |
|
| 352 | - |
|
| 353 | - if ($total > 0) { |
|
| 354 | - if ($quota > 0 && $total > $quota) { |
|
| 355 | - $total = $quota; |
|
| 356 | - } |
|
| 357 | - // prevent division by zero or error codes (negative values) |
|
| 358 | - $relative = round(($used / $total) * 10000) / 100; |
|
| 359 | - } else { |
|
| 360 | - $relative = 0.0; |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - if (substr_count($mount->getMountPoint(), '/') < 3) { |
|
| 364 | - $mountPoint = ''; |
|
| 365 | - } else { |
|
| 366 | - [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4); |
|
| 367 | - } |
|
| 368 | - |
|
| 369 | - return [ |
|
| 370 | - 'free' => $free, |
|
| 371 | - 'used' => $used, |
|
| 372 | - 'total' => $total, |
|
| 373 | - 'relative' => $relative, |
|
| 374 | - 'quota' => $quota, |
|
| 375 | - 'owner' => $user->getUID(), |
|
| 376 | - 'ownerDisplayName' => $user->getDisplayName(), |
|
| 377 | - 'mountType' => $mount->getMountType(), |
|
| 378 | - 'mountPoint' => trim($mountPoint, '/'), |
|
| 379 | - ]; |
|
| 380 | - } |
|
| 381 | - |
|
| 382 | - public static function clearStorageInfo(string $absolutePath): void { |
|
| 383 | - /** @var ICacheFactory $cacheFactory */ |
|
| 384 | - $cacheFactory = \OC::$server->get(ICacheFactory::class); |
|
| 385 | - $memcache = $cacheFactory->createLocal('storage_info'); |
|
| 386 | - $cacheKeyPrefix = Filesystem::normalizePath($absolutePath) . '::'; |
|
| 387 | - $memcache->remove($cacheKeyPrefix . 'include'); |
|
| 388 | - $memcache->remove($cacheKeyPrefix . 'exclude'); |
|
| 389 | - } |
|
| 390 | - |
|
| 391 | - /** |
|
| 392 | - * Returns whether the config file is set manually to read-only |
|
| 393 | - * @return bool |
|
| 394 | - * @deprecated 32.0.0 use the `config_is_read_only` system config directly |
|
| 395 | - */ |
|
| 396 | - public static function isReadOnlyConfigEnabled() { |
|
| 397 | - return \OC::$server->getConfig()->getSystemValueBool('config_is_read_only', false); |
|
| 398 | - } |
|
| 298 | + $isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class); |
|
| 299 | + |
|
| 300 | + $ownerId = $storage->getOwner($path); |
|
| 301 | + $ownerDisplayName = ''; |
|
| 302 | + |
|
| 303 | + if ($isRemoteShare === false && $ownerId !== false) { |
|
| 304 | + $ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? ''; |
|
| 305 | + } |
|
| 306 | + |
|
| 307 | + if (substr_count($mount->getMountPoint(), '/') < 3) { |
|
| 308 | + $mountPoint = ''; |
|
| 309 | + } else { |
|
| 310 | + [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4); |
|
| 311 | + } |
|
| 312 | + |
|
| 313 | + $info = [ |
|
| 314 | + 'free' => $free, |
|
| 315 | + 'used' => $used, |
|
| 316 | + 'quota' => $quota, |
|
| 317 | + 'total' => $total, |
|
| 318 | + 'relative' => $relative, |
|
| 319 | + 'owner' => $ownerId, |
|
| 320 | + 'ownerDisplayName' => $ownerDisplayName, |
|
| 321 | + 'mountType' => $mount->getMountType(), |
|
| 322 | + 'mountPoint' => trim($mountPoint, '/'), |
|
| 323 | + ]; |
|
| 324 | + |
|
| 325 | + if ($isRemoteShare === false && $ownerId !== false && $path === '/') { |
|
| 326 | + // If path is root, store this as last known quota usage for this user |
|
| 327 | + \OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative); |
|
| 328 | + } |
|
| 329 | + |
|
| 330 | + $memcache->set($cacheKey, $info, 5 * 60); |
|
| 331 | + |
|
| 332 | + return $info; |
|
| 333 | + } |
|
| 334 | + |
|
| 335 | + /** |
|
| 336 | + * Get storage info including all mount points and quota |
|
| 337 | + * |
|
| 338 | + * @psalm-suppress LessSpecificReturnStatement Legacy code outputs weird types - manually validated that they are correct |
|
| 339 | + * @return StorageInfo |
|
| 340 | + */ |
|
| 341 | + private static function getGlobalStorageInfo(int|float $quota, IUser $user, IMountPoint $mount): array { |
|
| 342 | + $rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext'); |
|
| 343 | + /** @var int|float $used */ |
|
| 344 | + $used = $rootInfo['size']; |
|
| 345 | + if ($used < 0) { |
|
| 346 | + $used = 0.0; |
|
| 347 | + } |
|
| 348 | + |
|
| 349 | + $total = $quota; |
|
| 350 | + /** @var int|float $free */ |
|
| 351 | + $free = $quota - $used; |
|
| 352 | + |
|
| 353 | + if ($total > 0) { |
|
| 354 | + if ($quota > 0 && $total > $quota) { |
|
| 355 | + $total = $quota; |
|
| 356 | + } |
|
| 357 | + // prevent division by zero or error codes (negative values) |
|
| 358 | + $relative = round(($used / $total) * 10000) / 100; |
|
| 359 | + } else { |
|
| 360 | + $relative = 0.0; |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + if (substr_count($mount->getMountPoint(), '/') < 3) { |
|
| 364 | + $mountPoint = ''; |
|
| 365 | + } else { |
|
| 366 | + [,,,$mountPoint] = explode('/', $mount->getMountPoint(), 4); |
|
| 367 | + } |
|
| 368 | + |
|
| 369 | + return [ |
|
| 370 | + 'free' => $free, |
|
| 371 | + 'used' => $used, |
|
| 372 | + 'total' => $total, |
|
| 373 | + 'relative' => $relative, |
|
| 374 | + 'quota' => $quota, |
|
| 375 | + 'owner' => $user->getUID(), |
|
| 376 | + 'ownerDisplayName' => $user->getDisplayName(), |
|
| 377 | + 'mountType' => $mount->getMountType(), |
|
| 378 | + 'mountPoint' => trim($mountPoint, '/'), |
|
| 379 | + ]; |
|
| 380 | + } |
|
| 381 | + |
|
| 382 | + public static function clearStorageInfo(string $absolutePath): void { |
|
| 383 | + /** @var ICacheFactory $cacheFactory */ |
|
| 384 | + $cacheFactory = \OC::$server->get(ICacheFactory::class); |
|
| 385 | + $memcache = $cacheFactory->createLocal('storage_info'); |
|
| 386 | + $cacheKeyPrefix = Filesystem::normalizePath($absolutePath) . '::'; |
|
| 387 | + $memcache->remove($cacheKeyPrefix . 'include'); |
|
| 388 | + $memcache->remove($cacheKeyPrefix . 'exclude'); |
|
| 389 | + } |
|
| 390 | + |
|
| 391 | + /** |
|
| 392 | + * Returns whether the config file is set manually to read-only |
|
| 393 | + * @return bool |
|
| 394 | + * @deprecated 32.0.0 use the `config_is_read_only` system config directly |
|
| 395 | + */ |
|
| 396 | + public static function isReadOnlyConfigEnabled() { |
|
| 397 | + return \OC::$server->getConfig()->getSystemValueBool('config_is_read_only', false); |
|
| 398 | + } |
|
| 399 | 399 | } |
@@ -12,95 +12,95 @@ |
||
| 12 | 12 | use OC_Helper; |
| 13 | 13 | |
| 14 | 14 | class LegacyHelperTest extends \Test\TestCase { |
| 15 | - public function testBuildNotExistingFileNameForView(): void { |
|
| 16 | - $viewMock = $this->createMock(View::class); |
|
| 17 | - $this->assertEquals('/filename', OC_Helper::buildNotExistingFileNameForView('/', 'filename', $viewMock)); |
|
| 18 | - $this->assertEquals('dir/filename.ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 15 | + public function testBuildNotExistingFileNameForView(): void { |
|
| 16 | + $viewMock = $this->createMock(View::class); |
|
| 17 | + $this->assertEquals('/filename', OC_Helper::buildNotExistingFileNameForView('/', 'filename', $viewMock)); |
|
| 18 | + $this->assertEquals('dir/filename.ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 19 | 19 | |
| 20 | - $viewMock = $this->createMock(View::class); |
|
| 21 | - $viewMock->expects($this->exactly(2)) |
|
| 22 | - ->method('file_exists') |
|
| 23 | - ->willReturnMap([ |
|
| 24 | - // Conflict on filename.ext |
|
| 25 | - ['dir/filename.ext', true], |
|
| 26 | - ['dir/filename (2).ext', false], |
|
| 27 | - ]); |
|
| 28 | - $this->assertEquals('dir/filename (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 20 | + $viewMock = $this->createMock(View::class); |
|
| 21 | + $viewMock->expects($this->exactly(2)) |
|
| 22 | + ->method('file_exists') |
|
| 23 | + ->willReturnMap([ |
|
| 24 | + // Conflict on filename.ext |
|
| 25 | + ['dir/filename.ext', true], |
|
| 26 | + ['dir/filename (2).ext', false], |
|
| 27 | + ]); |
|
| 28 | + $this->assertEquals('dir/filename (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 29 | 29 | |
| 30 | - $viewMock = $this->createMock(View::class); |
|
| 31 | - $viewMock->expects($this->exactly(3)) |
|
| 32 | - ->method('file_exists') |
|
| 33 | - ->willReturnMap([ |
|
| 34 | - // Conflict on filename.ext |
|
| 35 | - ['dir/filename.ext', true], |
|
| 36 | - ['dir/filename (2).ext', true], |
|
| 37 | - ['dir/filename (3).ext', false], |
|
| 38 | - ]); |
|
| 39 | - $this->assertEquals('dir/filename (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 30 | + $viewMock = $this->createMock(View::class); |
|
| 31 | + $viewMock->expects($this->exactly(3)) |
|
| 32 | + ->method('file_exists') |
|
| 33 | + ->willReturnMap([ |
|
| 34 | + // Conflict on filename.ext |
|
| 35 | + ['dir/filename.ext', true], |
|
| 36 | + ['dir/filename (2).ext', true], |
|
| 37 | + ['dir/filename (3).ext', false], |
|
| 38 | + ]); |
|
| 39 | + $this->assertEquals('dir/filename (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename.ext', $viewMock)); |
|
| 40 | 40 | |
| 41 | - $viewMock = $this->createMock(View::class); |
|
| 42 | - $viewMock->expects($this->exactly(2)) |
|
| 43 | - ->method('file_exists') |
|
| 44 | - ->willReturnMap([ |
|
| 45 | - ['dir/filename (1).ext', true], |
|
| 46 | - ['dir/filename (2).ext', false], |
|
| 47 | - ]); |
|
| 48 | - $this->assertEquals('dir/filename (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (1).ext', $viewMock)); |
|
| 41 | + $viewMock = $this->createMock(View::class); |
|
| 42 | + $viewMock->expects($this->exactly(2)) |
|
| 43 | + ->method('file_exists') |
|
| 44 | + ->willReturnMap([ |
|
| 45 | + ['dir/filename (1).ext', true], |
|
| 46 | + ['dir/filename (2).ext', false], |
|
| 47 | + ]); |
|
| 48 | + $this->assertEquals('dir/filename (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (1).ext', $viewMock)); |
|
| 49 | 49 | |
| 50 | - $viewMock = $this->createMock(View::class); |
|
| 51 | - $viewMock->expects($this->exactly(2)) |
|
| 52 | - ->method('file_exists') |
|
| 53 | - ->willReturnMap([ |
|
| 54 | - ['dir/filename (2).ext', true], |
|
| 55 | - ['dir/filename (3).ext', false], |
|
| 56 | - ]); |
|
| 57 | - $this->assertEquals('dir/filename (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (2).ext', $viewMock)); |
|
| 50 | + $viewMock = $this->createMock(View::class); |
|
| 51 | + $viewMock->expects($this->exactly(2)) |
|
| 52 | + ->method('file_exists') |
|
| 53 | + ->willReturnMap([ |
|
| 54 | + ['dir/filename (2).ext', true], |
|
| 55 | + ['dir/filename (3).ext', false], |
|
| 56 | + ]); |
|
| 57 | + $this->assertEquals('dir/filename (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (2).ext', $viewMock)); |
|
| 58 | 58 | |
| 59 | - $viewMock = $this->createMock(View::class); |
|
| 60 | - $viewMock->expects($this->exactly(3)) |
|
| 61 | - ->method('file_exists') |
|
| 62 | - ->willReturnMap([ |
|
| 63 | - ['dir/filename (2).ext', true], |
|
| 64 | - ['dir/filename (3).ext', true], |
|
| 65 | - ['dir/filename (4).ext', false], |
|
| 66 | - ]); |
|
| 67 | - $this->assertEquals('dir/filename (4).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (2).ext', $viewMock)); |
|
| 59 | + $viewMock = $this->createMock(View::class); |
|
| 60 | + $viewMock->expects($this->exactly(3)) |
|
| 61 | + ->method('file_exists') |
|
| 62 | + ->willReturnMap([ |
|
| 63 | + ['dir/filename (2).ext', true], |
|
| 64 | + ['dir/filename (3).ext', true], |
|
| 65 | + ['dir/filename (4).ext', false], |
|
| 66 | + ]); |
|
| 67 | + $this->assertEquals('dir/filename (4).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename (2).ext', $viewMock)); |
|
| 68 | 68 | |
| 69 | - $viewMock = $this->createMock(View::class); |
|
| 70 | - $viewMock->expects($this->exactly(2)) |
|
| 71 | - ->method('file_exists') |
|
| 72 | - ->willReturnMap([ |
|
| 73 | - ['dir/filename(1).ext', true], |
|
| 74 | - ['dir/filename(2).ext', false], |
|
| 75 | - ]); |
|
| 76 | - $this->assertEquals('dir/filename(2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1).ext', $viewMock)); |
|
| 69 | + $viewMock = $this->createMock(View::class); |
|
| 70 | + $viewMock->expects($this->exactly(2)) |
|
| 71 | + ->method('file_exists') |
|
| 72 | + ->willReturnMap([ |
|
| 73 | + ['dir/filename(1).ext', true], |
|
| 74 | + ['dir/filename(2).ext', false], |
|
| 75 | + ]); |
|
| 76 | + $this->assertEquals('dir/filename(2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1).ext', $viewMock)); |
|
| 77 | 77 | |
| 78 | - $viewMock = $this->createMock(View::class); |
|
| 79 | - $viewMock->expects($this->exactly(2)) |
|
| 80 | - ->method('file_exists') |
|
| 81 | - ->willReturnMap([ |
|
| 82 | - ['dir/filename(1) (1).ext', true], |
|
| 83 | - ['dir/filename(1) (2).ext', false], |
|
| 84 | - ]); |
|
| 85 | - $this->assertEquals('dir/filename(1) (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (1).ext', $viewMock)); |
|
| 78 | + $viewMock = $this->createMock(View::class); |
|
| 79 | + $viewMock->expects($this->exactly(2)) |
|
| 80 | + ->method('file_exists') |
|
| 81 | + ->willReturnMap([ |
|
| 82 | + ['dir/filename(1) (1).ext', true], |
|
| 83 | + ['dir/filename(1) (2).ext', false], |
|
| 84 | + ]); |
|
| 85 | + $this->assertEquals('dir/filename(1) (2).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (1).ext', $viewMock)); |
|
| 86 | 86 | |
| 87 | - $viewMock = $this->createMock(View::class); |
|
| 88 | - $viewMock->expects($this->exactly(3)) |
|
| 89 | - ->method('file_exists') |
|
| 90 | - ->willReturnMap([ |
|
| 91 | - ['dir/filename(1) (1).ext', true], |
|
| 92 | - ['dir/filename(1) (2).ext', true], |
|
| 93 | - ['dir/filename(1) (3).ext', false], |
|
| 94 | - ]); |
|
| 95 | - $this->assertEquals('dir/filename(1) (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (1).ext', $viewMock)); |
|
| 87 | + $viewMock = $this->createMock(View::class); |
|
| 88 | + $viewMock->expects($this->exactly(3)) |
|
| 89 | + ->method('file_exists') |
|
| 90 | + ->willReturnMap([ |
|
| 91 | + ['dir/filename(1) (1).ext', true], |
|
| 92 | + ['dir/filename(1) (2).ext', true], |
|
| 93 | + ['dir/filename(1) (3).ext', false], |
|
| 94 | + ]); |
|
| 95 | + $this->assertEquals('dir/filename(1) (3).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (1).ext', $viewMock)); |
|
| 96 | 96 | |
| 97 | - $viewMock = $this->createMock(View::class); |
|
| 98 | - $viewMock->expects($this->exactly(2)) |
|
| 99 | - ->method('file_exists') |
|
| 100 | - ->willReturnMap([ |
|
| 101 | - ['dir/filename(1) (2) (3).ext', true], |
|
| 102 | - ['dir/filename(1) (2) (4).ext', false], |
|
| 103 | - ]); |
|
| 104 | - $this->assertEquals('dir/filename(1) (2) (4).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (2) (3).ext', $viewMock)); |
|
| 105 | - } |
|
| 97 | + $viewMock = $this->createMock(View::class); |
|
| 98 | + $viewMock->expects($this->exactly(2)) |
|
| 99 | + ->method('file_exists') |
|
| 100 | + ->willReturnMap([ |
|
| 101 | + ['dir/filename(1) (2) (3).ext', true], |
|
| 102 | + ['dir/filename(1) (2) (4).ext', false], |
|
| 103 | + ]); |
|
| 104 | + $this->assertEquals('dir/filename(1) (2) (4).ext', OC_Helper::buildNotExistingFileNameForView('dir', 'filename(1) (2) (3).ext', $viewMock)); |
|
| 105 | + } |
|
| 106 | 106 | } |
@@ -15,60 +15,60 @@ |
||
| 15 | 15 | |
| 16 | 16 | class FilesTest extends TestCase { |
| 17 | 17 | |
| 18 | - /** |
|
| 19 | - * Tests recursive folder deletion with rmdirr() |
|
| 20 | - */ |
|
| 21 | - public function testRecursiveFolderDeletion(): void { |
|
| 22 | - $baseDir = Server::get(ITempManager::class)->getTemporaryFolder() . '/'; |
|
| 23 | - mkdir($baseDir . 'a/b/c/d/e', 0777, true); |
|
| 24 | - mkdir($baseDir . 'a/b/c1/d/e', 0777, true); |
|
| 25 | - mkdir($baseDir . 'a/b/c2/d/e', 0777, true); |
|
| 26 | - mkdir($baseDir . 'a/b1/c1/d/e', 0777, true); |
|
| 27 | - mkdir($baseDir . 'a/b2/c1/d/e', 0777, true); |
|
| 28 | - mkdir($baseDir . 'a/b3/c1/d/e', 0777, true); |
|
| 29 | - mkdir($baseDir . 'a1/b', 0777, true); |
|
| 30 | - mkdir($baseDir . 'a1/c', 0777, true); |
|
| 31 | - file_put_contents($baseDir . 'a/test.txt', 'Hello file!'); |
|
| 32 | - file_put_contents($baseDir . 'a/b1/c1/test one.txt', 'Hello file one!'); |
|
| 33 | - file_put_contents($baseDir . 'a1/b/test two.txt', 'Hello file two!'); |
|
| 34 | - Files::rmdirr($baseDir . 'a'); |
|
| 18 | + /** |
|
| 19 | + * Tests recursive folder deletion with rmdirr() |
|
| 20 | + */ |
|
| 21 | + public function testRecursiveFolderDeletion(): void { |
|
| 22 | + $baseDir = Server::get(ITempManager::class)->getTemporaryFolder() . '/'; |
|
| 23 | + mkdir($baseDir . 'a/b/c/d/e', 0777, true); |
|
| 24 | + mkdir($baseDir . 'a/b/c1/d/e', 0777, true); |
|
| 25 | + mkdir($baseDir . 'a/b/c2/d/e', 0777, true); |
|
| 26 | + mkdir($baseDir . 'a/b1/c1/d/e', 0777, true); |
|
| 27 | + mkdir($baseDir . 'a/b2/c1/d/e', 0777, true); |
|
| 28 | + mkdir($baseDir . 'a/b3/c1/d/e', 0777, true); |
|
| 29 | + mkdir($baseDir . 'a1/b', 0777, true); |
|
| 30 | + mkdir($baseDir . 'a1/c', 0777, true); |
|
| 31 | + file_put_contents($baseDir . 'a/test.txt', 'Hello file!'); |
|
| 32 | + file_put_contents($baseDir . 'a/b1/c1/test one.txt', 'Hello file one!'); |
|
| 33 | + file_put_contents($baseDir . 'a1/b/test two.txt', 'Hello file two!'); |
|
| 34 | + Files::rmdirr($baseDir . 'a'); |
|
| 35 | 35 | |
| 36 | - $this->assertFalse(file_exists($baseDir . 'a')); |
|
| 37 | - $this->assertTrue(file_exists($baseDir . 'a1')); |
|
| 36 | + $this->assertFalse(file_exists($baseDir . 'a')); |
|
| 37 | + $this->assertTrue(file_exists($baseDir . 'a1')); |
|
| 38 | 38 | |
| 39 | - Files::rmdirr($baseDir); |
|
| 40 | - $this->assertFalse(file_exists($baseDir)); |
|
| 41 | - } |
|
| 39 | + Files::rmdirr($baseDir); |
|
| 40 | + $this->assertFalse(file_exists($baseDir)); |
|
| 41 | + } |
|
| 42 | 42 | |
| 43 | - #[\PHPUnit\Framework\Attributes\DataProvider('streamCopyDataProvider')] |
|
| 44 | - public function testStreamCopy($expectedCount, $expectedResult, $source, $target): void { |
|
| 45 | - if (is_string($source)) { |
|
| 46 | - $source = fopen($source, 'r'); |
|
| 47 | - } |
|
| 48 | - if (is_string($target)) { |
|
| 49 | - $target = fopen($target, 'w'); |
|
| 50 | - } |
|
| 43 | + #[\PHPUnit\Framework\Attributes\DataProvider('streamCopyDataProvider')] |
|
| 44 | + public function testStreamCopy($expectedCount, $expectedResult, $source, $target): void { |
|
| 45 | + if (is_string($source)) { |
|
| 46 | + $source = fopen($source, 'r'); |
|
| 47 | + } |
|
| 48 | + if (is_string($target)) { |
|
| 49 | + $target = fopen($target, 'w'); |
|
| 50 | + } |
|
| 51 | 51 | |
| 52 | - [$count, $result] = Files::streamCopy($source, $target, true); |
|
| 52 | + [$count, $result] = Files::streamCopy($source, $target, true); |
|
| 53 | 53 | |
| 54 | - if (is_resource($source)) { |
|
| 55 | - fclose($source); |
|
| 56 | - } |
|
| 57 | - if (is_resource($target)) { |
|
| 58 | - fclose($target); |
|
| 59 | - } |
|
| 54 | + if (is_resource($source)) { |
|
| 55 | + fclose($source); |
|
| 56 | + } |
|
| 57 | + if (is_resource($target)) { |
|
| 58 | + fclose($target); |
|
| 59 | + } |
|
| 60 | 60 | |
| 61 | - $this->assertSame($expectedCount, $count); |
|
| 62 | - $this->assertSame($expectedResult, $result); |
|
| 63 | - } |
|
| 61 | + $this->assertSame($expectedCount, $count); |
|
| 62 | + $this->assertSame($expectedResult, $result); |
|
| 63 | + } |
|
| 64 | 64 | |
| 65 | 65 | |
| 66 | - public static function streamCopyDataProvider(): array { |
|
| 67 | - return [ |
|
| 68 | - [0, false, false, false], |
|
| 69 | - [0, false, \OC::$SERVERROOT . '/tests/data/lorem.txt', false], |
|
| 70 | - [filesize(\OC::$SERVERROOT . '/tests/data/lorem.txt'), true, \OC::$SERVERROOT . '/tests/data/lorem.txt', \OC::$SERVERROOT . '/tests/data/lorem-copy.txt'], |
|
| 71 | - [3670, true, \OC::$SERVERROOT . '/tests/data/testimage.png', \OC::$SERVERROOT . '/tests/data/testimage-copy.png'], |
|
| 72 | - ]; |
|
| 73 | - } |
|
| 66 | + public static function streamCopyDataProvider(): array { |
|
| 67 | + return [ |
|
| 68 | + [0, false, false, false], |
|
| 69 | + [0, false, \OC::$SERVERROOT . '/tests/data/lorem.txt', false], |
|
| 70 | + [filesize(\OC::$SERVERROOT . '/tests/data/lorem.txt'), true, \OC::$SERVERROOT . '/tests/data/lorem.txt', \OC::$SERVERROOT . '/tests/data/lorem-copy.txt'], |
|
| 71 | + [3670, true, \OC::$SERVERROOT . '/tests/data/testimage.png', \OC::$SERVERROOT . '/tests/data/testimage-copy.png'], |
|
| 72 | + ]; |
|
| 73 | + } |
|
| 74 | 74 | } |
@@ -19,22 +19,22 @@ discard block |
||
| 19 | 19 | * Tests recursive folder deletion with rmdirr() |
| 20 | 20 | */ |
| 21 | 21 | public function testRecursiveFolderDeletion(): void { |
| 22 | - $baseDir = Server::get(ITempManager::class)->getTemporaryFolder() . '/'; |
|
| 23 | - mkdir($baseDir . 'a/b/c/d/e', 0777, true); |
|
| 24 | - mkdir($baseDir . 'a/b/c1/d/e', 0777, true); |
|
| 25 | - mkdir($baseDir . 'a/b/c2/d/e', 0777, true); |
|
| 26 | - mkdir($baseDir . 'a/b1/c1/d/e', 0777, true); |
|
| 27 | - mkdir($baseDir . 'a/b2/c1/d/e', 0777, true); |
|
| 28 | - mkdir($baseDir . 'a/b3/c1/d/e', 0777, true); |
|
| 29 | - mkdir($baseDir . 'a1/b', 0777, true); |
|
| 30 | - mkdir($baseDir . 'a1/c', 0777, true); |
|
| 31 | - file_put_contents($baseDir . 'a/test.txt', 'Hello file!'); |
|
| 32 | - file_put_contents($baseDir . 'a/b1/c1/test one.txt', 'Hello file one!'); |
|
| 33 | - file_put_contents($baseDir . 'a1/b/test two.txt', 'Hello file two!'); |
|
| 34 | - Files::rmdirr($baseDir . 'a'); |
|
| 22 | + $baseDir = Server::get(ITempManager::class)->getTemporaryFolder().'/'; |
|
| 23 | + mkdir($baseDir.'a/b/c/d/e', 0777, true); |
|
| 24 | + mkdir($baseDir.'a/b/c1/d/e', 0777, true); |
|
| 25 | + mkdir($baseDir.'a/b/c2/d/e', 0777, true); |
|
| 26 | + mkdir($baseDir.'a/b1/c1/d/e', 0777, true); |
|
| 27 | + mkdir($baseDir.'a/b2/c1/d/e', 0777, true); |
|
| 28 | + mkdir($baseDir.'a/b3/c1/d/e', 0777, true); |
|
| 29 | + mkdir($baseDir.'a1/b', 0777, true); |
|
| 30 | + mkdir($baseDir.'a1/c', 0777, true); |
|
| 31 | + file_put_contents($baseDir.'a/test.txt', 'Hello file!'); |
|
| 32 | + file_put_contents($baseDir.'a/b1/c1/test one.txt', 'Hello file one!'); |
|
| 33 | + file_put_contents($baseDir.'a1/b/test two.txt', 'Hello file two!'); |
|
| 34 | + Files::rmdirr($baseDir.'a'); |
|
| 35 | 35 | |
| 36 | - $this->assertFalse(file_exists($baseDir . 'a')); |
|
| 37 | - $this->assertTrue(file_exists($baseDir . 'a1')); |
|
| 36 | + $this->assertFalse(file_exists($baseDir.'a')); |
|
| 37 | + $this->assertTrue(file_exists($baseDir.'a1')); |
|
| 38 | 38 | |
| 39 | 39 | Files::rmdirr($baseDir); |
| 40 | 40 | $this->assertFalse(file_exists($baseDir)); |
@@ -66,9 +66,9 @@ discard block |
||
| 66 | 66 | public static function streamCopyDataProvider(): array { |
| 67 | 67 | return [ |
| 68 | 68 | [0, false, false, false], |
| 69 | - [0, false, \OC::$SERVERROOT . '/tests/data/lorem.txt', false], |
|
| 70 | - [filesize(\OC::$SERVERROOT . '/tests/data/lorem.txt'), true, \OC::$SERVERROOT . '/tests/data/lorem.txt', \OC::$SERVERROOT . '/tests/data/lorem-copy.txt'], |
|
| 71 | - [3670, true, \OC::$SERVERROOT . '/tests/data/testimage.png', \OC::$SERVERROOT . '/tests/data/testimage-copy.png'], |
|
| 69 | + [0, false, \OC::$SERVERROOT.'/tests/data/lorem.txt', false], |
|
| 70 | + [filesize(\OC::$SERVERROOT.'/tests/data/lorem.txt'), true, \OC::$SERVERROOT.'/tests/data/lorem.txt', \OC::$SERVERROOT.'/tests/data/lorem-copy.txt'], |
|
| 71 | + [3670, true, \OC::$SERVERROOT.'/tests/data/testimage.png', \OC::$SERVERROOT.'/tests/data/testimage-copy.png'], |
|
| 72 | 72 | ]; |
| 73 | 73 | } |
| 74 | 74 | } |
@@ -24,209 +24,209 @@ |
||
| 24 | 24 | * @package Test\Files\Storage\Wrapper |
| 25 | 25 | */ |
| 26 | 26 | class QuotaTest extends \Test\Files\Storage\Storage { |
| 27 | - /** |
|
| 28 | - * @var string tmpDir |
|
| 29 | - */ |
|
| 30 | - private $tmpDir; |
|
| 31 | - |
|
| 32 | - protected function setUp(): void { |
|
| 33 | - parent::setUp(); |
|
| 34 | - |
|
| 35 | - $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); |
|
| 36 | - $storage = new Local(['datadir' => $this->tmpDir]); |
|
| 37 | - $this->instance = new Quota(['storage' => $storage, 'quota' => 10000000]); |
|
| 38 | - } |
|
| 39 | - |
|
| 40 | - protected function tearDown(): void { |
|
| 41 | - Files::rmdirr($this->tmpDir); |
|
| 42 | - parent::tearDown(); |
|
| 43 | - } |
|
| 44 | - |
|
| 45 | - /** |
|
| 46 | - * @param integer $limit |
|
| 47 | - */ |
|
| 48 | - protected function getLimitedStorage($limit) { |
|
| 49 | - $storage = new Local(['datadir' => $this->tmpDir]); |
|
| 50 | - $storage->mkdir('files'); |
|
| 51 | - $storage->getScanner()->scan(''); |
|
| 52 | - return new Quota(['storage' => $storage, 'quota' => $limit]); |
|
| 53 | - } |
|
| 54 | - |
|
| 55 | - public function testFilePutContentsNotEnoughSpace(): void { |
|
| 56 | - $instance = $this->getLimitedStorage(3); |
|
| 57 | - $this->assertFalse($instance->file_put_contents('files/foo', 'foobar')); |
|
| 58 | - } |
|
| 59 | - |
|
| 60 | - public function testCopyNotEnoughSpace(): void { |
|
| 61 | - $instance = $this->getLimitedStorage(9); |
|
| 62 | - $this->assertEquals(6, $instance->file_put_contents('files/foo', 'foobar')); |
|
| 63 | - $instance->getScanner()->scan(''); |
|
| 64 | - $this->assertFalse($instance->copy('files/foo', 'files/bar')); |
|
| 65 | - } |
|
| 66 | - |
|
| 67 | - public function testFreeSpace(): void { |
|
| 68 | - $instance = $this->getLimitedStorage(9); |
|
| 69 | - $this->assertEquals(9, $instance->free_space('')); |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - public function testFreeSpaceWithUsedSpace(): void { |
|
| 73 | - $instance = $this->getLimitedStorage(9); |
|
| 74 | - $instance->getCache()->put( |
|
| 75 | - '', ['size' => 3] |
|
| 76 | - ); |
|
| 77 | - $this->assertEquals(6, $instance->free_space('')); |
|
| 78 | - } |
|
| 79 | - |
|
| 80 | - public function testFreeSpaceWithUnknownDiskSpace(): void { |
|
| 81 | - $storage = $this->getMockBuilder(Local::class) |
|
| 82 | - ->onlyMethods(['free_space']) |
|
| 83 | - ->setConstructorArgs([['datadir' => $this->tmpDir]]) |
|
| 84 | - ->getMock(); |
|
| 85 | - $storage->expects($this->any()) |
|
| 86 | - ->method('free_space') |
|
| 87 | - ->willReturn(-2); |
|
| 88 | - $storage->getScanner()->scan(''); |
|
| 89 | - |
|
| 90 | - $instance = new Quota(['storage' => $storage, 'quota' => 9]); |
|
| 91 | - $instance->getCache()->put( |
|
| 92 | - '', ['size' => 3] |
|
| 93 | - ); |
|
| 94 | - $this->assertEquals(6, $instance->free_space('')); |
|
| 95 | - } |
|
| 96 | - |
|
| 97 | - public function testFreeSpaceWithUsedSpaceAndEncryption(): void { |
|
| 98 | - $instance = $this->getLimitedStorage(9); |
|
| 99 | - $instance->getCache()->put( |
|
| 100 | - '', ['size' => 7] |
|
| 101 | - ); |
|
| 102 | - $this->assertEquals(2, $instance->free_space('')); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - public function testFWriteNotEnoughSpace(): void { |
|
| 106 | - $instance = $this->getLimitedStorage(9); |
|
| 107 | - $stream = $instance->fopen('files/foo', 'w+'); |
|
| 108 | - $this->assertEquals(6, fwrite($stream, 'foobar')); |
|
| 109 | - $this->assertEquals(3, fwrite($stream, 'qwerty')); |
|
| 110 | - fclose($stream); |
|
| 111 | - $this->assertEquals('foobarqwe', $instance->file_get_contents('files/foo')); |
|
| 112 | - } |
|
| 113 | - |
|
| 114 | - public function testStreamCopyWithEnoughSpace(): void { |
|
| 115 | - $instance = $this->getLimitedStorage(16); |
|
| 116 | - $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); |
|
| 117 | - $outputStream = $instance->fopen('files/foo', 'w+'); |
|
| 118 | - [$count, $result] = Files::streamCopy($inputStream, $outputStream, true); |
|
| 119 | - $this->assertEquals(12, $count); |
|
| 120 | - $this->assertTrue($result); |
|
| 121 | - fclose($inputStream); |
|
| 122 | - fclose($outputStream); |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - public function testStreamCopyNotEnoughSpace(): void { |
|
| 126 | - $instance = $this->getLimitedStorage(9); |
|
| 127 | - $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); |
|
| 128 | - $outputStream = $instance->fopen('files/foo', 'w+'); |
|
| 129 | - [$count, $result] = Files::streamCopy($inputStream, $outputStream, true); |
|
| 130 | - $this->assertEquals(9, $count); |
|
| 131 | - $this->assertFalse($result); |
|
| 132 | - fclose($inputStream); |
|
| 133 | - fclose($outputStream); |
|
| 134 | - } |
|
| 135 | - |
|
| 136 | - public function testReturnFalseWhenFopenFailed(): void { |
|
| 137 | - $failStorage = $this->getMockBuilder(Local::class) |
|
| 138 | - ->onlyMethods(['fopen']) |
|
| 139 | - ->setConstructorArgs([['datadir' => $this->tmpDir]]) |
|
| 140 | - ->getMock(); |
|
| 141 | - $failStorage->expects($this->any()) |
|
| 142 | - ->method('fopen') |
|
| 143 | - ->willReturn(false); |
|
| 144 | - |
|
| 145 | - $instance = new Quota(['storage' => $failStorage, 'quota' => 1000]); |
|
| 146 | - |
|
| 147 | - $this->assertFalse($instance->fopen('failedfopen', 'r')); |
|
| 148 | - } |
|
| 149 | - |
|
| 150 | - public function testReturnRegularStreamOnRead(): void { |
|
| 151 | - $instance = $this->getLimitedStorage(9); |
|
| 152 | - |
|
| 153 | - // create test file first |
|
| 154 | - $stream = $instance->fopen('files/foo', 'w+'); |
|
| 155 | - fwrite($stream, 'blablacontent'); |
|
| 156 | - fclose($stream); |
|
| 157 | - |
|
| 158 | - $stream = $instance->fopen('files/foo', 'r'); |
|
| 159 | - $meta = stream_get_meta_data($stream); |
|
| 160 | - $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 161 | - fclose($stream); |
|
| 162 | - |
|
| 163 | - $stream = $instance->fopen('files/foo', 'rb'); |
|
| 164 | - $meta = stream_get_meta_data($stream); |
|
| 165 | - $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 166 | - fclose($stream); |
|
| 167 | - } |
|
| 168 | - |
|
| 169 | - public function testReturnRegularStreamWhenOutsideFiles(): void { |
|
| 170 | - $instance = $this->getLimitedStorage(9); |
|
| 171 | - $instance->mkdir('files_other'); |
|
| 172 | - |
|
| 173 | - // create test file first |
|
| 174 | - $stream = $instance->fopen('files_other/foo', 'w+'); |
|
| 175 | - $meta = stream_get_meta_data($stream); |
|
| 176 | - $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 177 | - fclose($stream); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - public function testReturnQuotaStreamOnWrite(): void { |
|
| 181 | - $instance = $this->getLimitedStorage(9); |
|
| 182 | - $stream = $instance->fopen('files/foo', 'w+'); |
|
| 183 | - $meta = stream_get_meta_data($stream); |
|
| 184 | - $expected_type = 'user-space'; |
|
| 185 | - $this->assertEquals($expected_type, $meta['wrapper_type']); |
|
| 186 | - fclose($stream); |
|
| 187 | - } |
|
| 188 | - |
|
| 189 | - public function testSpaceRoot(): void { |
|
| 190 | - $storage = $this->getMockBuilder(Local::class)->disableOriginalConstructor()->getMock(); |
|
| 191 | - $cache = $this->getMockBuilder('\OC\Files\Cache\Cache')->disableOriginalConstructor()->getMock(); |
|
| 192 | - $storage->expects($this->once()) |
|
| 193 | - ->method('getCache') |
|
| 194 | - ->willReturn($cache); |
|
| 195 | - $storage->expects($this->once()) |
|
| 196 | - ->method('free_space') |
|
| 197 | - ->willReturn(2048); |
|
| 198 | - $cache->expects($this->once()) |
|
| 199 | - ->method('get') |
|
| 200 | - ->with('files') |
|
| 201 | - ->willReturn(new CacheEntry(['size' => 50])); |
|
| 202 | - |
|
| 203 | - $instance = new Quota(['storage' => $storage, 'quota' => 1024, 'root' => 'files']); |
|
| 204 | - |
|
| 205 | - $this->assertEquals(1024 - 50, $instance->free_space('')); |
|
| 206 | - } |
|
| 207 | - |
|
| 208 | - public function testInstanceOfStorageWrapper(): void { |
|
| 209 | - $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Local')); |
|
| 210 | - $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Wrapper')); |
|
| 211 | - $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')); |
|
| 212 | - } |
|
| 213 | - |
|
| 214 | - public function testNoMkdirQuotaZero(): void { |
|
| 215 | - $instance = $this->getLimitedStorage(0.0); |
|
| 216 | - $this->assertFalse($instance->mkdir('files')); |
|
| 217 | - $this->assertFalse($instance->mkdir('files/foobar')); |
|
| 218 | - } |
|
| 219 | - |
|
| 220 | - public function testMkdirQuotaZeroTrashbin(): void { |
|
| 221 | - $instance = $this->getLimitedStorage(0.0); |
|
| 222 | - $this->assertTrue($instance->mkdir('files_trashbin')); |
|
| 223 | - $this->assertTrue($instance->mkdir('files_trashbin/files')); |
|
| 224 | - $this->assertTrue($instance->mkdir('files_versions')); |
|
| 225 | - $this->assertTrue($instance->mkdir('cache')); |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - public function testNoTouchQuotaZero(): void { |
|
| 229 | - $instance = $this->getLimitedStorage(0.0); |
|
| 230 | - $this->assertFalse($instance->touch('foobar')); |
|
| 231 | - } |
|
| 27 | + /** |
|
| 28 | + * @var string tmpDir |
|
| 29 | + */ |
|
| 30 | + private $tmpDir; |
|
| 31 | + |
|
| 32 | + protected function setUp(): void { |
|
| 33 | + parent::setUp(); |
|
| 34 | + |
|
| 35 | + $this->tmpDir = Server::get(ITempManager::class)->getTemporaryFolder(); |
|
| 36 | + $storage = new Local(['datadir' => $this->tmpDir]); |
|
| 37 | + $this->instance = new Quota(['storage' => $storage, 'quota' => 10000000]); |
|
| 38 | + } |
|
| 39 | + |
|
| 40 | + protected function tearDown(): void { |
|
| 41 | + Files::rmdirr($this->tmpDir); |
|
| 42 | + parent::tearDown(); |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + /** |
|
| 46 | + * @param integer $limit |
|
| 47 | + */ |
|
| 48 | + protected function getLimitedStorage($limit) { |
|
| 49 | + $storage = new Local(['datadir' => $this->tmpDir]); |
|
| 50 | + $storage->mkdir('files'); |
|
| 51 | + $storage->getScanner()->scan(''); |
|
| 52 | + return new Quota(['storage' => $storage, 'quota' => $limit]); |
|
| 53 | + } |
|
| 54 | + |
|
| 55 | + public function testFilePutContentsNotEnoughSpace(): void { |
|
| 56 | + $instance = $this->getLimitedStorage(3); |
|
| 57 | + $this->assertFalse($instance->file_put_contents('files/foo', 'foobar')); |
|
| 58 | + } |
|
| 59 | + |
|
| 60 | + public function testCopyNotEnoughSpace(): void { |
|
| 61 | + $instance = $this->getLimitedStorage(9); |
|
| 62 | + $this->assertEquals(6, $instance->file_put_contents('files/foo', 'foobar')); |
|
| 63 | + $instance->getScanner()->scan(''); |
|
| 64 | + $this->assertFalse($instance->copy('files/foo', 'files/bar')); |
|
| 65 | + } |
|
| 66 | + |
|
| 67 | + public function testFreeSpace(): void { |
|
| 68 | + $instance = $this->getLimitedStorage(9); |
|
| 69 | + $this->assertEquals(9, $instance->free_space('')); |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + public function testFreeSpaceWithUsedSpace(): void { |
|
| 73 | + $instance = $this->getLimitedStorage(9); |
|
| 74 | + $instance->getCache()->put( |
|
| 75 | + '', ['size' => 3] |
|
| 76 | + ); |
|
| 77 | + $this->assertEquals(6, $instance->free_space('')); |
|
| 78 | + } |
|
| 79 | + |
|
| 80 | + public function testFreeSpaceWithUnknownDiskSpace(): void { |
|
| 81 | + $storage = $this->getMockBuilder(Local::class) |
|
| 82 | + ->onlyMethods(['free_space']) |
|
| 83 | + ->setConstructorArgs([['datadir' => $this->tmpDir]]) |
|
| 84 | + ->getMock(); |
|
| 85 | + $storage->expects($this->any()) |
|
| 86 | + ->method('free_space') |
|
| 87 | + ->willReturn(-2); |
|
| 88 | + $storage->getScanner()->scan(''); |
|
| 89 | + |
|
| 90 | + $instance = new Quota(['storage' => $storage, 'quota' => 9]); |
|
| 91 | + $instance->getCache()->put( |
|
| 92 | + '', ['size' => 3] |
|
| 93 | + ); |
|
| 94 | + $this->assertEquals(6, $instance->free_space('')); |
|
| 95 | + } |
|
| 96 | + |
|
| 97 | + public function testFreeSpaceWithUsedSpaceAndEncryption(): void { |
|
| 98 | + $instance = $this->getLimitedStorage(9); |
|
| 99 | + $instance->getCache()->put( |
|
| 100 | + '', ['size' => 7] |
|
| 101 | + ); |
|
| 102 | + $this->assertEquals(2, $instance->free_space('')); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + public function testFWriteNotEnoughSpace(): void { |
|
| 106 | + $instance = $this->getLimitedStorage(9); |
|
| 107 | + $stream = $instance->fopen('files/foo', 'w+'); |
|
| 108 | + $this->assertEquals(6, fwrite($stream, 'foobar')); |
|
| 109 | + $this->assertEquals(3, fwrite($stream, 'qwerty')); |
|
| 110 | + fclose($stream); |
|
| 111 | + $this->assertEquals('foobarqwe', $instance->file_get_contents('files/foo')); |
|
| 112 | + } |
|
| 113 | + |
|
| 114 | + public function testStreamCopyWithEnoughSpace(): void { |
|
| 115 | + $instance = $this->getLimitedStorage(16); |
|
| 116 | + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); |
|
| 117 | + $outputStream = $instance->fopen('files/foo', 'w+'); |
|
| 118 | + [$count, $result] = Files::streamCopy($inputStream, $outputStream, true); |
|
| 119 | + $this->assertEquals(12, $count); |
|
| 120 | + $this->assertTrue($result); |
|
| 121 | + fclose($inputStream); |
|
| 122 | + fclose($outputStream); |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + public function testStreamCopyNotEnoughSpace(): void { |
|
| 126 | + $instance = $this->getLimitedStorage(9); |
|
| 127 | + $inputStream = fopen('data://text/plain,foobarqwerty', 'r'); |
|
| 128 | + $outputStream = $instance->fopen('files/foo', 'w+'); |
|
| 129 | + [$count, $result] = Files::streamCopy($inputStream, $outputStream, true); |
|
| 130 | + $this->assertEquals(9, $count); |
|
| 131 | + $this->assertFalse($result); |
|
| 132 | + fclose($inputStream); |
|
| 133 | + fclose($outputStream); |
|
| 134 | + } |
|
| 135 | + |
|
| 136 | + public function testReturnFalseWhenFopenFailed(): void { |
|
| 137 | + $failStorage = $this->getMockBuilder(Local::class) |
|
| 138 | + ->onlyMethods(['fopen']) |
|
| 139 | + ->setConstructorArgs([['datadir' => $this->tmpDir]]) |
|
| 140 | + ->getMock(); |
|
| 141 | + $failStorage->expects($this->any()) |
|
| 142 | + ->method('fopen') |
|
| 143 | + ->willReturn(false); |
|
| 144 | + |
|
| 145 | + $instance = new Quota(['storage' => $failStorage, 'quota' => 1000]); |
|
| 146 | + |
|
| 147 | + $this->assertFalse($instance->fopen('failedfopen', 'r')); |
|
| 148 | + } |
|
| 149 | + |
|
| 150 | + public function testReturnRegularStreamOnRead(): void { |
|
| 151 | + $instance = $this->getLimitedStorage(9); |
|
| 152 | + |
|
| 153 | + // create test file first |
|
| 154 | + $stream = $instance->fopen('files/foo', 'w+'); |
|
| 155 | + fwrite($stream, 'blablacontent'); |
|
| 156 | + fclose($stream); |
|
| 157 | + |
|
| 158 | + $stream = $instance->fopen('files/foo', 'r'); |
|
| 159 | + $meta = stream_get_meta_data($stream); |
|
| 160 | + $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 161 | + fclose($stream); |
|
| 162 | + |
|
| 163 | + $stream = $instance->fopen('files/foo', 'rb'); |
|
| 164 | + $meta = stream_get_meta_data($stream); |
|
| 165 | + $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 166 | + fclose($stream); |
|
| 167 | + } |
|
| 168 | + |
|
| 169 | + public function testReturnRegularStreamWhenOutsideFiles(): void { |
|
| 170 | + $instance = $this->getLimitedStorage(9); |
|
| 171 | + $instance->mkdir('files_other'); |
|
| 172 | + |
|
| 173 | + // create test file first |
|
| 174 | + $stream = $instance->fopen('files_other/foo', 'w+'); |
|
| 175 | + $meta = stream_get_meta_data($stream); |
|
| 176 | + $this->assertEquals('plainfile', $meta['wrapper_type']); |
|
| 177 | + fclose($stream); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + public function testReturnQuotaStreamOnWrite(): void { |
|
| 181 | + $instance = $this->getLimitedStorage(9); |
|
| 182 | + $stream = $instance->fopen('files/foo', 'w+'); |
|
| 183 | + $meta = stream_get_meta_data($stream); |
|
| 184 | + $expected_type = 'user-space'; |
|
| 185 | + $this->assertEquals($expected_type, $meta['wrapper_type']); |
|
| 186 | + fclose($stream); |
|
| 187 | + } |
|
| 188 | + |
|
| 189 | + public function testSpaceRoot(): void { |
|
| 190 | + $storage = $this->getMockBuilder(Local::class)->disableOriginalConstructor()->getMock(); |
|
| 191 | + $cache = $this->getMockBuilder('\OC\Files\Cache\Cache')->disableOriginalConstructor()->getMock(); |
|
| 192 | + $storage->expects($this->once()) |
|
| 193 | + ->method('getCache') |
|
| 194 | + ->willReturn($cache); |
|
| 195 | + $storage->expects($this->once()) |
|
| 196 | + ->method('free_space') |
|
| 197 | + ->willReturn(2048); |
|
| 198 | + $cache->expects($this->once()) |
|
| 199 | + ->method('get') |
|
| 200 | + ->with('files') |
|
| 201 | + ->willReturn(new CacheEntry(['size' => 50])); |
|
| 202 | + |
|
| 203 | + $instance = new Quota(['storage' => $storage, 'quota' => 1024, 'root' => 'files']); |
|
| 204 | + |
|
| 205 | + $this->assertEquals(1024 - 50, $instance->free_space('')); |
|
| 206 | + } |
|
| 207 | + |
|
| 208 | + public function testInstanceOfStorageWrapper(): void { |
|
| 209 | + $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Local')); |
|
| 210 | + $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Wrapper')); |
|
| 211 | + $this->assertTrue($this->instance->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')); |
|
| 212 | + } |
|
| 213 | + |
|
| 214 | + public function testNoMkdirQuotaZero(): void { |
|
| 215 | + $instance = $this->getLimitedStorage(0.0); |
|
| 216 | + $this->assertFalse($instance->mkdir('files')); |
|
| 217 | + $this->assertFalse($instance->mkdir('files/foobar')); |
|
| 218 | + } |
|
| 219 | + |
|
| 220 | + public function testMkdirQuotaZeroTrashbin(): void { |
|
| 221 | + $instance = $this->getLimitedStorage(0.0); |
|
| 222 | + $this->assertTrue($instance->mkdir('files_trashbin')); |
|
| 223 | + $this->assertTrue($instance->mkdir('files_trashbin/files')); |
|
| 224 | + $this->assertTrue($instance->mkdir('files_versions')); |
|
| 225 | + $this->assertTrue($instance->mkdir('cache')); |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + public function testNoTouchQuotaZero(): void { |
|
| 229 | + $instance = $this->getLimitedStorage(0.0); |
|
| 230 | + $this->assertFalse($instance->touch('foobar')); |
|
| 231 | + } |
|
| 232 | 232 | } |