/** * Retrieves the contents of a trash bin directory. * * @param string $dir path to the directory inside the trashbin * or empty to retrieve the root of the trashbin * @param string $user * @param string $sortAttribute attribute to sort on or empty to disable sorting * @param bool $sortDescending true for descending sort, false otherwise * @return \OCP\Files\FileInfo[] */ public static function getTrashFiles($dir, $user, $sortAttribute = '', $sortDescending = false) { $result = array(); $timestamp = null; $view = new \OC\Files\View('/' . $user . '/files_trashbin/files'); if (ltrim($dir, '/') !== '' && !$view->is_dir($dir)) { throw new \Exception('Directory does not exists'); } $dirContent = $view->opendir($dir); if ($dirContent === false) { return $result; } $mount = $view->getMount($dir); $storage = $mount->getStorage(); $absoluteDir = $view->getAbsolutePath($dir); $internalPath = $mount->getInternalPath($absoluteDir); if (is_resource($dirContent)) { $originalLocations = \OCA\Files_Trashbin\Trashbin::getLocations($user); while (($entryName = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { $id = $entryName; if ($dir === '' || $dir === '/') { $size = $view->filesize($id); $pathparts = pathinfo($entryName); $timestamp = substr($pathparts['extension'], 1); $id = $pathparts['filename']; } else { if ($timestamp === null) { // for subfolders we need to calculate the timestamp only once $size = $view->filesize($dir . '/' . $id); $parts = explode('/', ltrim($dir, '/')); $timestamp = substr(pathinfo($parts[0], PATHINFO_EXTENSION), 1); } } $originalPath = ''; if (isset($originalLocations[$id][$timestamp])) { $originalPath = $originalLocations[$id][$timestamp]; if (substr($originalPath, -1) === '/') { $originalPath = substr($originalPath, 0, -1); } } $i = array('name' => $id, 'mtime' => $timestamp, 'mimetype' => $view->is_dir($dir . '/' . $entryName) ? 'httpd/unix-directory' : \OC_Helper::getFileNameMimeType($id), 'type' => $view->is_dir($dir . '/' . $entryName) ? 'dir' : 'file', 'directory' => $dir === '/' ? '' : $dir, 'size' => $size); if ($originalPath) { $i['extraData'] = $originalPath . '/' . $id; } $result[] = new FileInfo($absoluteDir . '/' . $i['name'], $storage, $internalPath . '/' . $i['name'], $i, $mount); } } closedir($dirContent); } if ($sortAttribute !== '') { return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending); } return $result; }
/** * Retrieves the contents of a trash bin directory. * @param string $dir path to the directory inside the trashbin * or empty to retrieve the root of the trashbin * @return array of files */ public static function getTrashFiles($dir) { $result = array(); $user = \OCP\User::getUser(); if ($dir && $dir !== '/') { $view = new \OC_Filesystemview('/' . $user . '/files_trashbin/files'); $dirContent = $view->opendir($dir); if ($dirContent === false) { return null; } if (is_resource($dirContent)) { while (($entryName = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($entryName)) { $pos = strpos($dir . '/', '/', 1); $tmp = substr($dir, 0, $pos); $pos = strrpos($tmp, '.d'); $timestamp = substr($tmp, $pos + 2); $result[] = array('id' => $entryName, 'timestamp' => $timestamp, 'mime' => $view->getMimeType($dir . '/' . $entryName), 'type' => $view->is_dir($dir . '/' . $entryName) ? 'dir' : 'file', 'location' => $dir); } } closedir($dirContent); } } else { $query = \OC_DB::prepare('SELECT `id`,`location`,`timestamp`,`type`,`mime` FROM `*PREFIX*files_trash` WHERE `user` = ?'); $result = $query->execute(array($user))->fetchAll(); } $files = array(); $id = 0; foreach ($result as $r) { $i = array(); $i['id'] = $id++; $i['name'] = $r['id']; $i['date'] = \OCP\Util::formatDate($r['timestamp']); $i['timestamp'] = $r['timestamp']; $i['etag'] = $i['timestamp']; // dummy etag $i['mimetype'] = $r['mime']; $i['type'] = $r['type']; if ($i['type'] === 'file') { $fileinfo = pathinfo($r['id']); $i['basename'] = $fileinfo['filename']; $i['extension'] = isset($fileinfo['extension']) ? '.' . $fileinfo['extension'] : ''; } $i['directory'] = $r['location']; if ($i['directory'] === '/') { $i['directory'] = ''; } $i['permissions'] = \OCP\PERMISSION_READ; $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($r['mime']); $i['icon'] = \OCA\Files\Helper::determineIcon($i); $files[] = $i; } usort($files, array('\\OCA\\Files\\Helper', 'fileCmp')); return $files; }
public function tearDown() { // test that nothing outside our jail is touched $contents = array(); $dh = $this->sourceStorage->opendir(''); while ($file = readdir($dh)) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { $contents[] = $file; } } $this->assertEquals(array('foo'), $contents); $this->sourceStorage->cleanUp(); parent::tearDown(); }
/** * For adapters that dont support copying folders natively * * @param $source * @param $target * @return bool */ protected function copyRecursive($source, $target) { $dh = $this->opendir($source); $result = true; while ($file = readdir($dh)) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($this->is_dir($source . '/' . $file)) { $this->mkdir($target . '/' . $file); $result = $this->copyRecursive($source . '/' . $file, $target . '/' . $file); } else { $result = parent::copy($source . '/' . $file, $target . '/' . $file); } if (!$result) { break; } } } return $result; }
/** * scan all the files and folders in a folder * * @param string $path * @param bool $recursive * @param int $reuse * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ public function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1) { if ($reuse === -1) { $reuse = $recursive === self::SCAN_SHALLOW ? self::REUSE_ETAG | self::REUSE_SIZE : 0; } $this->emit('\\OC\\Files\\Cache\\Scanner', 'scanFolder', array($path, $this->storageId)); $size = 0; $childQueue = array(); $existingChildren = array(); if ($this->cache->inCache($path)) { $children = $this->cache->getFolderContents($path); foreach ($children as $child) { $existingChildren[] = $child['name']; } } $newChildren = array(); if ($this->storage->is_dir($path) && ($dh = $this->storage->opendir($path))) { $exceptionOccurred = false; \OC_DB::beginTransaction(); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { $child = $path ? $path . '/' . $file : $file; if (!Filesystem::isIgnoredDir($file)) { $newChildren[] = $file; try { $data = $this->scanFile($child, $reuse, true); if ($data) { if ($data['size'] === -1) { if ($recursive === self::SCAN_RECURSIVE) { $childQueue[] = $child; } else { $size = -1; } } else { if ($size !== -1) { $size += $data['size']; } } } } catch (\Doctrine\DBAL\DBALException $ex) { // might happen if inserting duplicate while a scanning // process is running in parallel // log and ignore \OC_Log::write('core', 'Exception while scanning file "' . $child . '": ' . $ex->getMessage(), \OC_Log::DEBUG); $exceptionOccurred = true; } } } } $removedChildren = \array_diff($existingChildren, $newChildren); foreach ($removedChildren as $childName) { $child = $path ? $path . '/' . $childName : $childName; $this->cache->remove($child); } \OC_DB::commit(); if ($exceptionOccurred) { // It might happen that the parallel scan process has already // inserted mimetypes but those weren't available yet inside the transaction // To make sure to have the updated mime types in such cases, // we reload them here $this->cache->loadMimetypes(); } foreach ($childQueue as $child) { $childSize = $this->scanChildren($child, self::SCAN_RECURSIVE, $reuse); if ($childSize === -1) { $size = -1; } else { $size += $childSize; } } $this->cache->put($path, array('size' => $size)); } $this->emit('\\OC\\Files\\Cache\\Scanner', 'postScanFolder', array($path, $this->storageId)); return $size; }
/** * copies a directory recursively * * @param string $source * @param string $target * @return void */ public static function copyr($source, $target) { $dir = opendir($source); @mkdir($target); while (false !== ($file = readdir($dir))) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if (is_dir($source . '/' . $file)) { OC_Util::copyr($source . '/' . $file, $target . '/' . $file); } else { copy($source . '/' . $file, $target . '/' . $file); } } } closedir($dir); }
/** * copies a directory recursively by using streams * * @param string $source * @param \OCP\Files\Folder $target * @return void */ public static function copyr($source, \OCP\Files\Folder $target) { $dir = opendir($source); while (false !== ($file = readdir($dir))) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if (is_dir($source . '/' . $file)) { $child = $target->newFolder($file); self::copyr($source . '/' . $file, $child); } else { $child = $target->newFile($file); stream_copy_to_stream(fopen($source . '/' . $file,'r'), $child->fopen('w')); } } } closedir($dir); }
/** * @param string $path * @param string $fileName * @throws InvalidPathException */ public function verifyPath($path, $fileName) { $l10n = \OC::$server->getL10N('lib'); // verify empty and dot files $trimmed = trim($fileName); if ($trimmed === '') { throw new InvalidPathException($l10n->t('Empty filename is not allowed')); } if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { throw new InvalidPathException($l10n->t('Dot files are not allowed')); } // verify database - e.g. mysql only 3-byte chars if (preg_match('%(?: \\xF0[\\x90-\\xBF][\\x80-\\xBF]{2} # planes 1-3 | [\\xF1-\\xF3][\\x80-\\xBF]{3} # planes 4-15 | \\xF4[\\x80-\\x8F][\\x80-\\xBF]{2} # plane 16 )%xs', $fileName)) { throw new InvalidPathException($l10n->t('4-byte characters are not supported in file names')); } try { /** @type \OCP\Files\Storage $storage */ list($storage, $internalPath) = $this->resolvePath($path); $storage->verifyPath($internalPath, $fileName); } catch (ReservedWordException $ex) { throw new InvalidPathException($l10n->t('File name is a reserved word')); } catch (InvalidCharacterInPathException $ex) { throw new InvalidPathException($l10n->t('File name contains at least one invalid character')); } catch (FileNameTooLongException $ex) { throw new InvalidPathException($l10n->t('File name is too long')); } }
/** * @param \OCP\Files\Storage $sourceStorage * @param string $sourceInternalPath * @param string $targetInternalPath * @param bool $preserveMtime * @return bool */ public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) { if ($sourceStorage === $this) { return $this->copy($sourceInternalPath, $targetInternalPath); } if ($sourceStorage->is_dir($sourceInternalPath)) { $dh = $sourceStorage->opendir($sourceInternalPath); $result = $this->mkdir($targetInternalPath); if (is_resource($dh)) { while ($result and ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file); } } } } else { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); // TODO: call fopen in a way that we execute again all storage wrappers // to avoid that we bypass storage wrappers which perform important actions // for this operation. Same is true for all other operations which // are not the same as the original one.Once this is fixed we also // need to adjust the encryption wrapper. $target = $this->fopen($targetInternalPath, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); if ($result and $preserveMtime) { $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath)); } fclose($source); fclose($target); if (!$result) { // delete partially written target file $this->unlink($targetInternalPath); // delete cache entry that was created by fopen $this->getCache()->remove($targetInternalPath); } } return (bool) $result; }
public function copy($path1, $path2) { if ($this->is_dir($path1)) { $this->remove($path2); $dir = $this->opendir($path1); $this->mkdir($path2); while ($file = readdir($dir)) { if (!Filesystem::isIgnoredDir($file)) { if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) { return false; } } } closedir($dir); return true; } else { $source = $this->fopen($path1, 'r'); $target = $this->fopen($path2, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); $this->removeCachedFile($path2); return $result; } }
/** * @param string $query * @param string $dir * @return array */ protected function searchInDir($query, $dir = '') { $files = array(); $physicalDir = $this->getSourcePath($dir); foreach (scandir($physicalDir) as $item) { if (\OC\Files\Filesystem::isIgnoredDir($item)) { continue; } $physicalItem = $physicalDir . '/' . $item; if (strstr(strtolower($item), strtolower($query)) !== false) { $files[] = $dir . '/' . $item; } if (is_dir($physicalItem)) { $files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item)); } } return $files; }
/** * recursively delete share keys from given users * * @param string $dir directory * @param array $userIds user ids for which the share keys should be deleted * @param \OC\Files\View $view view relative to data/ */ private static function recursiveDelShareKeys($dir, $userIds, $view) { $dirContent = $view->opendir($dir); if (is_resource($dirContent)) { while (($file = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($view->is_dir($dir . '/' . $file)) { self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $view); } else { foreach ($userIds as $userId) { if ($userId . '.shareKey' === $file) { \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); self::deleteKey($view, $dir . '/' . $file); } } } } } closedir($dirContent); } }
/** * remove all files in PHP /oc-noclean temp dir */ public static function cleanTmpNoClean() { $tmpDirNoCleanName = get_temp_dir() . '/oc-noclean/'; if (file_exists($tmpDirNoCleanName) && is_dir($tmpDirNoCleanName)) { $files = scandir($tmpDirNoCleanName); foreach ($files as $file) { $fileName = $tmpDirNoCleanName . $file; if (!\OC\Files\Filesystem::isIgnoredDir($file) && filemtime($fileName) + 600 < time()) { unlink($fileName); } } // if oc-noclean is empty delete it $isTmpDirNoCleanEmpty = true; $tmpDirNoClean = opendir($tmpDirNoCleanName); if (is_resource($tmpDirNoClean)) { while (false !== ($file = readdir($tmpDirNoClean))) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { $isTmpDirNoCleanEmpty = false; } } } if ($isTmpDirNoCleanEmpty) { rmdir($tmpDirNoCleanName); } } }
/** * find all share keys for a given file * @param string $path to the file * @param \OC\Files\View $view view, relative to data/ * @return array list of files, path relative to data/ */ public static function findShareKeys($path, $view) { $result = array(); $pathinfo = pathinfo($path); $dirContent = $view->opendir($pathinfo['dirname']); if (is_resource($dirContent)) { while (($file = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if (preg_match("/" . $pathinfo['filename'] . ".(.*).shareKey/", $file)) { $result[] = $pathinfo['dirname'] . '/' . $file; } } } closedir($dirContent); } return $result; }
/** * @brief Deletes all files and folders recursively within a directory * @param string $directory The directory whose contents will be deleted * @param bool $empty Flag indicating whether directory will be emptied * @returns bool * * @note By default the directory specified by $directory will be * deleted together with its contents. To avoid this set $empty to true */ public function deleteAll($directory, $empty = false) { $directory = trim($directory, '/'); if (!$this->is_dir($directory) || !$this->isReadable($directory)) { return false; } else { $directoryHandle = $this->opendir($directory); if (is_resource($directoryHandle)) { while (($contents = readdir($directoryHandle)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($contents)) { $path = $directory . '/' . $contents; if ($this->is_dir($path)) { $this->deleteAll($path); } else { $this->unlink($path); } } } } if ($empty === false) { if (!$this->rmdir($directory)) { return false; } } return true; } }
public function copy($path1, $path2) { if ($this->is_dir($path1)) { if ($this->is_dir($path2)) { $this->rmdir($path2); } else { if ($this->is_file($path2)) { $this->unlink($path2); } } $dir = $this->opendir($path1); $this->mkdir($path2); while ($file = readdir($dir)) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file)) { return false; } } } closedir($dir); return true; } else { if ($return = copy($this->getSourcePath($path1), $this->getSourcePath($path2))) { $this->copyMapping($path1, $path2); } return $return; } }
/** * recursively delete share keys from given users * * @param string $dir directory * @param array $userIds user ids for which the share keys should be deleted * @param string $owner owner of the file * @param \OC\Files\View $view view relative to data/ */ private static function recursiveDelShareKeys($dir, $userIds, $owner, $view) { $dirContent = $view->opendir($dir); $dirSlices = explode('/', ltrim($dir, '/')); $realFileDir = '/' . $owner . '/files/' . implode('/', array_slice($dirSlices, 3)) . '/'; if (is_resource($dirContent)) { while (($file = readdir($dirContent)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($view->is_dir($dir . '/' . $file)) { self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view); } else { $realFile = $realFileDir . self::getFilenameFromShareKey($file); foreach ($userIds as $userId) { if (preg_match("/(.*)." . $userId . ".shareKey/", $file)) { if ($userId === $owner && $view->file_exists($realFile)) { \OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR); continue; } \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); $view->unlink($dir . '/' . $file); } } } } } closedir($dirContent); } }
/** * rename file keys * * @param string $user * @param string $path * @param bool $trash */ private function renameFileKeys($user, $path, $trash = false) { if ($this->view->is_dir($user . '/' . $path) === false) { $this->logger->info('Skip dir /' . $user . '/' . $path . ': does not exist'); return; } $dh = $this->view->opendir($user . '/' . $path); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($this->view->is_dir($user . '/' . $path . '/' . $file)) { $this->renameFileKeys($user, $path . '/' . $file, $trash); } else { $target = $this->getTargetDir($user, $path, $file, $trash); if ($target) { $this->createPathForKeys(dirname($target)); $this->view->rename($user . '/' . $path . '/' . $file, $target); } else { $this->logger->warning('did not move key "' . $file . '" could not find the corresponding file in /data/' . $user . '/files.' . 'Most likely the key was already moved in a previous migration run and is already on the right place.'); } } } } closedir($dh); } }
public function rename($source, $target) { $source = $this->normalizePath($source); $target = $this->normalizePath($target); $stat1 = $this->stat($source); if (isset($stat1['mimetype']) && $stat1['mimetype'] === 'httpd/unix-directory') { $this->remove($target); $dir = $this->opendir($source); $this->mkdir($target); while ($file = readdir($dir)) { if (!Filesystem::isIgnoredDir($file)) { if (!$this->rename($source . '/' . $file, $target . '/' . $file)) { return false; } } } closedir($dir); $this->remove($source); return true; } else { if (is_array($stat1)) { $parent = $this->stat(dirname($target)); if (is_array($parent)) { $this->remove($target); $stat1['parent'] = $parent['fileid']; $stat1['path'] = $target; $stat1['path_hash'] = md5($target); $stat1['name'] = \OC_Util::basename($target); $stat1['mtime'] = time(); $stat1['etag'] = $this->getETag($target); $this->getCache()->update($stat1['fileid'], $stat1); return true; } } } return false; }
public function copy($path1, $path2) { $path1 = $this->normalizePath($path1); $path2 = $this->normalizePath($path2); if ($this->is_file($path1)) { try { $this->getConnection()->copyObject(array('Bucket' => $this->bucket, 'Key' => $this->cleanKey($path2), 'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1))); $this->testTimeout(); } catch (S3Exception $e) { \OCP\Util::logException('files_external', $e); return false; } } else { $this->remove($path2); try { $this->getConnection()->copyObject(array('Bucket' => $this->bucket, 'Key' => $path2 . '/', 'CopySource' => S3Client::encodeKey($this->bucket . '/' . $path1 . '/'))); $this->testTimeout(); } catch (S3Exception $e) { \OCP\Util::logException('files_external', $e); return false; } $dh = $this->opendir($path1); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } $source = $path1 . '/' . $file; $target = $path2 . '/' . $file; $this->copy($source, $target); } } } return true; }
/** * copy file between two storages * * @param Storage $sourceStorage * @param string $sourceInternalPath * @param string $targetInternalPath * @param bool $preserveMtime * @param bool $isRename * @return bool * @throws \Exception */ private function copyBetweenStorage(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename) { // for versions we have nothing to do, because versions should always use the // key from the original file. Just create a 1:1 copy and done if ($this->isVersion($targetInternalPath) || $this->isVersion($sourceInternalPath)) { $result = $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); if ($result) { $info = $this->getCache('', $sourceStorage)->get($sourceInternalPath); // make sure that we update the unencrypted size for the version if (isset($info['encrypted']) && $info['encrypted'] === true) { $this->updateUnencryptedSize($this->getFullPath($targetInternalPath), $info['size']); } } return $result; } // first copy the keys that we reuse the existing file key on the target location // and don't create a new one which would break versions for example. $mount = $this->mountManager->findByStorageId($sourceStorage->getId()); if (count($mount) === 1) { $mountPoint = $mount[0]->getMountPoint(); $source = $mountPoint . '/' . $sourceInternalPath; $target = $this->getFullPath($targetInternalPath); $this->copyKeys($source, $target); } else { $this->logger->error('Could not find mount point, can\'t keep encryption keys'); } if ($sourceStorage->is_dir($sourceInternalPath)) { $dh = $sourceStorage->opendir($sourceInternalPath); $result = $this->mkdir($targetInternalPath); if (is_resource($dh)) { while ($result and ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file); } } } } else { try { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); $target = $this->fopen($targetInternalPath, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); fclose($source); fclose($target); } catch (\Exception $e) { fclose($source); fclose($target); throw $e; } if ($result) { if ($preserveMtime) { $this->touch($targetInternalPath, $sourceStorage->filemtime($sourceInternalPath)); } $isEncrypted = $this->encryptionManager->isEnabled() && $this->mount->getOption('encrypt', true) ? 1 : 0; // in case of a rename we need to manipulate the source cache because // this information will be kept for the new target if ($isRename) { $sourceStorage->getCache()->put($sourceInternalPath, ['encrypted' => $isEncrypted]); } else { $this->getCache()->put($targetInternalPath, ['encrypted' => $isEncrypted]); } } else { // delete partially written target file $this->unlink($targetInternalPath); // delete cache entry that was created by fopen $this->getCache()->remove($targetInternalPath); } } return (bool) $result; }
/** * Returns whether the given file name is valid * * @param string $file file name to check * @return bool true if the file name is valid, false otherwise * @deprecated use \OC\Files\View::verifyPath() */ public static function isValidFileName($file) { $trimmed = trim($file); if ($trimmed === '') { return false; } if (\OC\Files\Filesystem::isIgnoredDir($trimmed)) { return false; } foreach (str_split($trimmed) as $char) { if (strpos(\OCP\Constants::FILENAME_INVALID_CHARS, $char) !== false) { return false; } } return true; }
/** * Get the children from the storage * * @param string $folder * @return string[] */ protected function getNewChildren($folder) { $children = array(); if ($dh = $this->storage->opendir($folder)) { if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { $children[] = $file; } } } } return $children; }
public function rmdir($path) { if (trim($path, '/') === '') { $dir = $this->opendir($path); if (is_resource($dir)) { while (($file = readdir($dir)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if (!$this->unlink($path . '/' . $file)) { return false; } } } closedir($dir); } $this->driveFiles = array(); return true; } else { return $this->unlink($path); } }
public function copy($path1, $path2) { $path1 = $this->normalizePath($path1); $path2 = $this->normalizePath($path2); $fileType = $this->filetype($path1); if ($fileType === 'file') { // make way $this->unlink($path2); try { $source = $this->fetchObject($path1); $source->copy($this->bucket . '/' . $path2); // invalidate target object to force repopulation on fetch $this->objectCache->remove($path2); $this->objectCache->remove($path2 . '/'); } catch (ClientErrorResponseException $e) { \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR); return false; } } else { if ($fileType === 'dir') { // make way $this->unlink($path2); try { $source = $this->fetchObject($path1 . '/'); $source->copy($this->bucket . '/' . $path2 . '/'); // invalidate target object to force repopulation on fetch $this->objectCache->remove($path2); $this->objectCache->remove($path2 . '/'); } catch (ClientErrorResponseException $e) { \OCP\Util::writeLog('files_external', $e->getMessage(), \OCP\Util::ERROR); return false; } $dh = $this->opendir($path1); while ($file = readdir($dh)) { if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } $source = $path1 . '/' . $file; $target = $path2 . '/' . $file; $this->copy($source, $target); } } else { //file does not exist return false; } } return true; }
/** * rename file keys * * @param string $user * @param string $path * @param bool $trash */ private function renameFileKeys($user, $path, $trash = false) { $dh = $this->view->opendir($user . '/' . $path); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($file)) { if ($this->view->is_dir($user . '/' . $path . '/' . $file)) { $this->renameFileKeys($user, $path . '/' . $file, $trash); } else { $target = $this->getTargetDir($user, $path, $file, $trash); $this->createPathForKeys(dirname($target)); $this->view->rename($user . '/' . $path . '/' . $file, $target); } } } closedir($dh); } }
/** * Copy a file/folder from the source path to target path * * @param string $path1 source path * @param string $path2 target path * @param bool $preserveMtime whether to preserve mtime on the copy * * @return bool|mixed */ public function copy($path1, $path2, $preserveMtime = false) { $postFix1 = substr($path1, -1, 1) === '/' ? '/' : ''; $postFix2 = substr($path2, -1, 1) === '/' ? '/' : ''; $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); if (Filesystem::isValidPath($path2) and Filesystem::isValidPath($path1) and !Filesystem::isFileBlacklisted($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); if ($path1 == null or $path2 == null) { return false; } $run = true; $exists = $this->file_exists($path2); if ($this->shouldEmitHooks()) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_copy, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2), Filesystem::signal_param_run => &$run)); $this->emit_file_hooks_pre($exists, $path2, $run); } if ($run) { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->copy($internalPath1, $internalPath2); if (!$result) { // delete partially written target file $storage->unlink($internalPath2); $storage->getCache()->remove($internalPath2); } } else { $result = false; } } else { if ($this->is_dir($path1) && ($dh = $this->opendir($path1))) { $result = $this->mkdir($path2); if ($preserveMtime) { $this->touch($path2, $this->filemtime($path1)); } if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file, $preserveMtime)) { $result = false; } } } } } else { list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); list(, $result) = \OC_Helper::streamCopy($source, $target); if ($result && $preserveMtime) { $this->touch($path2, $this->filemtime($path1)); } fclose($source); fclose($target); if (!$result) { // delete partially written target file $storage2->unlink($internalPath2); $storage2->getCache()->remove($internalPath2); } } } $this->updater->update($path2); if ($this->shouldEmitHooks() && $result !== false) { \OC_Hook::emit(Filesystem::CLASSNAME, Filesystem::signal_post_copy, array(Filesystem::signal_param_oldpath => $this->getHookPath($path1), Filesystem::signal_param_newpath => $this->getHookPath($path2))); $this->emit_file_hooks_post($exists, $path2); } return $result; } else { return false; } } else { return false; } }
/** * check if trash bin is empty for a given user * * @param string $user * @return bool */ public static function isEmpty($user) { $view = new View('/' . $user . '/files_trashbin'); if ($view->is_dir('/files') && ($dh = $view->opendir('/files'))) { while ($file = readdir($dh)) { if (!Filesystem::isIgnoredDir($file)) { return false; } } } return true; }
/** * Recursive delete files and folders from a given directory * * @param string $dir */ protected static function tearDownAfterClassCleanStrayDataUnlinkDir($dir) { if ($dh = @opendir($dir)) { while (($file = readdir($dh)) !== false) { if (\OC\Files\Filesystem::isIgnoredDir($file)) { continue; } $path = $dir . '/' . $file; if (is_dir($path)) { self::tearDownAfterClassCleanStrayDataUnlinkDir($path); } else { @unlink($path); } } closedir($dh); } @rmdir($dir); }
/** * get a list of all available versions of a file in descending chronological order * @param string $uid user id from the owner of the file * @param string $filename file to find versions of, relative to the user files dir * @param string $userFullPath * @return array versions newest version first */ public static function getVersions($uid, $filename, $userFullPath = '') { $versions = array(); if (empty($filename)) { return $versions; } // fetch for old versions $view = new View('/' . $uid . '/'); $pathinfo = pathinfo($filename); $versionedFile = $pathinfo['basename']; $dir = Filesystem::normalizePath(self::VERSIONS_ROOT . '/' . $pathinfo['dirname']); $dirContent = false; if ($view->is_dir($dir)) { $dirContent = $view->opendir($dir); } if ($dirContent === false) { return $versions; } if (is_resource($dirContent)) { while (($entryName = readdir($dirContent)) !== false) { if (!Filesystem::isIgnoredDir($entryName)) { $pathparts = pathinfo($entryName); $filename = $pathparts['filename']; if ($filename === $versionedFile) { $pathparts = pathinfo($entryName); $timestamp = substr($pathparts['extension'], 1); $filename = $pathparts['filename']; $key = $timestamp . '#' . $filename; $versions[$key]['version'] = $timestamp; $versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($timestamp); if (empty($userFullPath)) { $versions[$key]['preview'] = ''; } else { $versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $userFullPath, 'version' => $timestamp)); } $versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename); $versions[$key]['name'] = $versionedFile; $versions[$key]['size'] = $view->filesize($dir . '/' . $entryName); } } } closedir($dirContent); } // sort with newest version first krsort($versions); return $versions; }