function testPostFileSizeWithDirectory() { $this->view->file_put_contents($this->filename, $this->data); \OC_FileProxy::$enabled = false; // get root size, must match the file's unencrypted size $unencryptedSize = $this->view->filesize(''); \OC_FileProxy::$enabled = true; $encryptedSize = $this->view->filesize(''); $this->assertTrue($encryptedSize !== $unencryptedSize); // cleanup $this->view->unlink($this->filename); }
/** * save text file * * @NoAdminRequired * * @param string $path * @param string $filecontents * @param integer $mtime * @return DataResponse */ public function save($path, $filecontents, $mtime) { try { if ($path !== '' && (is_integer($mtime) && $mtime > 0)) { // Get file mtime $filemtime = $this->view->filemtime($path); if ($mtime !== $filemtime) { // Then the file has changed since opening $this->logger->error('File: ' . $path . ' modified since opening.', ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('Cannot save file as it has been modified since opening')], Http::STATUS_BAD_REQUEST); } else { // File same as when opened, save file if ($this->view->isUpdatable($path)) { $filecontents = iconv(mb_detect_encoding($filecontents), "UTF-8", $filecontents); try { $this->view->file_put_contents($path, $filecontents); } catch (LockedException $e) { $message = (string) $this->l->t('The file is locked.'); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } catch (ForbiddenException $e) { return new DataResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST); } // Clear statcache clearstatcache(); // Get new mtime $newmtime = $this->view->filemtime($path); $newsize = $this->view->filesize($path); return new DataResponse(['mtime' => $newmtime, 'size' => $newsize], Http::STATUS_OK); } else { // Not writeable! $this->logger->error('User does not have permission to write to file: ' . $path, ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('Insufficient permissions')], Http::STATUS_BAD_REQUEST); } } } else { if ($path === '') { $this->logger->error('No file path supplied'); return new DataResponse(['message' => $this->l->t('File path not supplied')], Http::STATUS_BAD_REQUEST); } else { $this->logger->error('No file mtime supplied', ['app' => 'files_texteditor']); return new DataResponse(['message' => $this->l->t('File mtime not supplied')], Http::STATUS_BAD_REQUEST); } } } catch (HintException $e) { $message = (string) $e->getHint(); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } catch (\Exception $e) { $message = (string) $this->l->t('An internal server error occurred.'); return new DataResponse(['message' => $message], Http::STATUS_BAD_REQUEST); } }
/** * Encrypt all files in a directory * @param string $dirPath the directory whose files will be encrypted * @return bool * @note Encryption is recursive */ public function encryptAll($dirPath) { $result = true; $found = $this->findEncFiles($dirPath); // Disable proxy to prevent file being encrypted twice \OC_FileProxy::$enabled = false; $versionStatus = \OCP\App::isEnabled('files_versions'); \OC_App::disable('files_versions'); $encryptedFiles = array(); // Encrypt unencrypted files foreach ($found['plain'] as $plainFile) { //get file info $fileInfo = \OC\Files\Filesystem::getFileInfo($plainFile['path']); //relative to data/<user>/file $relPath = $plainFile['path']; //relative to /data $rawPath = '/' . $this->userId . '/files/' . $plainFile['path']; // keep timestamp $timestamp = $fileInfo['mtime']; // Open plain file handle for binary reading $plainHandle = $this->view->fopen($rawPath, 'rb'); // Open enc file handle for binary writing, with same filename as original plain file $encHandle = fopen('crypt://' . $rawPath . '.part', 'wb'); if (is_resource($encHandle) && is_resource($plainHandle)) { // Move plain file to a temporary location $size = stream_copy_to_stream($plainHandle, $encHandle); fclose($encHandle); fclose($plainHandle); $fakeRoot = $this->view->getRoot(); $this->view->chroot('/' . $this->userId . '/files'); $this->view->rename($relPath . '.part', $relPath); // set timestamp $this->view->touch($relPath, $timestamp); $encSize = $this->view->filesize($relPath); $this->view->chroot($fakeRoot); // Add the file to the cache \OC\Files\Filesystem::putFileInfo($relPath, array('encrypted' => true, 'size' => $encSize, 'unencrypted_size' => $size, 'etag' => $fileInfo['etag'])); $encryptedFiles[] = $relPath; } else { \OCP\Util::writeLog('files_encryption', 'initial encryption: could not encrypt ' . $rawPath, \OCP\Util::FATAL); $result = false; } } \OC_FileProxy::$enabled = true; if ($versionStatus) { \OC_App::enable('files_versions'); } $result = $result && $this->encryptVersions($encryptedFiles); return $result; }
/** * @param $path raw path relative to data/ * @param $mode * @param $options * @param $opened_path * @return bool */ public function stream_open($path, $mode, $options, &$opened_path) { // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; if (!isset($this->rootView)) { $this->rootView = new \OC_FilesystemView('/'); } $this->session = new \OCA\Encryption\Session($this->rootView); $this->privateKey = $this->session->getPrivateKey(); // rawPath is relative to the data directory $this->rawPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); $this->userId = Helper::getUser($this->rawPath); $util = new Util($this->rootView, $this->userId); // get the key ID which we want to use, can be the users key or the // public share key $this->keyId = $util->getKeyId(); // Strip identifier text from path, this gives us the path relative to data/<user>/files $this->relPath = Helper::stripUserFilesPath($this->rawPath); // if raw path doesn't point to a real file, check if it is a version or a file in the trash bin if ($this->relPath === false) { $this->relPath = Helper::getPathToRealFile($this->rawPath); } if ($this->relPath === false) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to "files", "files_versions" or "cache"', \OCP\Util::ERROR); return false; } // Disable fileproxies so we can get the file size and open the source file without recursive encryption $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($mode === 'w' or $mode === 'w+' or $mode === 'wb' or $mode === 'wb+') { // We're writing a new file so start write counter with 0 bytes $this->size = 0; $this->unencryptedSize = 0; } else { if ($this->privateKey === false) { // if private key is not valid redirect user to a error page \OCA\Encryption\Helper::redirectToErrorPage($this->session); } $this->size = $this->rootView->filesize($this->rawPath, $mode); } $this->handle = $this->rootView->fopen($this->rawPath, $mode); \OC_FileProxy::$enabled = $proxyStatus; if (!is_resource($this->handle)) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); } else { $this->meta = stream_get_meta_data($this->handle); } return is_resource($this->handle); }
public function show() { if ($this->useOriginal) { $fp = @$this->view->fopen($this->path, 'rb'); $mtime = $this->view->filemtime($this->path); $size = $this->view->filesize($this->path); $mime = $this->view->getMimetype($this->path); } else { $fp = @fopen($this->path, 'rb'); $mtime = filemtime($this->path); $size = filesize($this->path); $mime = \OC_Helper::getMimetype($this->path); } if ($fp) { \OCP\Response::enableCaching(); \OCP\Response::setLastModifiedHeader($mtime); header('Content-Length: ' . $size); header('Content-Type: ' . $mime); fpassthru($fp); } else { \OC_Response::setStatus(\OC_Response::STATUS_NOT_FOUND); } }
/** * @param $path * @param $mode * @param $options * @param $opened_path * @return bool */ public function stream_open($path, $mode, $options, &$opened_path) { if (!isset($this->rootView)) { $this->rootView = new \OC_FilesystemView('/'); } $this->session = new \OCA\Encryption\Session($this->rootView); $this->privateKey = $this->session->getPrivateKey($this->userId); $util = new Util($this->rootView, \OCP\USER::getUser()); $this->userId = $util->getUserId(); // Strip identifier text from path, this gives us the path relative to data/<user>/files $this->relPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); // rawPath is relative to the data directory $this->rawPath = $util->getUserFilesDir() . $this->relPath; // Disable fileproxies so we can get the file size and open the source file without recursive encryption $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($mode === 'w' or $mode === 'w+' or $mode === 'wb' or $mode === 'wb+') { // We're writing a new file so start write counter with 0 bytes $this->size = 0; $this->unencryptedSize = 0; } else { if ($this->privateKey === false) { // if private key is not valid redirect user to a error page \OCA\Encryption\Helper::redirectToErrorPage(); } $this->size = $this->rootView->filesize($this->rawPath, $mode); } $this->handle = $this->rootView->fopen($this->rawPath, $mode); \OC_FileProxy::$enabled = $proxyStatus; if (!is_resource($this->handle)) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); } else { $this->meta = stream_get_meta_data($this->handle); } return is_resource($this->handle); }
/** * @return int */ public function getSize() { return $this->view->filesize($this->path); }
/** * get the size from a given root folder * @param \OC\Files\View $view file view on the root folder * @return integer size of the folder */ private static function calculateSize($view) { $root = \OCP\Config::getSystemValue('datadirectory') . $view->getAbsolutePath(''); if (!file_exists($root)) { return 0; } $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST); $size = 0; /** * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach * This bug is fixed in PHP 5.5.9 or before * See #8376 */ $iterator->rewind(); while ($iterator->valid()) { $path = $iterator->current(); $relpath = substr($path, strlen($root) - 1); if (!$view->is_dir($relpath)) { $size += $view->filesize($relpath); } $iterator->next(); } return $size; }
/** * returns all stored file versions from a given user * @param string $uid id of the user * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename */ private static function getAllVersions($uid) { $view = new View('/' . $uid . '/'); $dirs = array(self::VERSIONS_ROOT); $versions = array(); while (!empty($dirs)) { $dir = array_pop($dirs); $files = $view->getDirectoryContent($dir); foreach ($files as $file) { if ($file['type'] === 'dir') { array_push($dirs, $file['path']); } else { $versionsBegin = strrpos($file['path'], '.v'); $relPathStart = strlen(self::VERSIONS_ROOT); $version = substr($file['path'], $versionsBegin + 2); $relpath = substr($file['path'], $relPathStart, $versionsBegin - $relPathStart); $key = $version . '#' . $relpath; $versions[$key] = array('path' => $relpath, 'timestamp' => $version); } } } // newest version first krsort($versions); $result = array(); foreach ($versions as $key => $value) { $size = $view->filesize(self::VERSIONS_ROOT . '/' . $value['path'] . '.v' . $value['timestamp']); $filename = $value['path']; $result['all'][$key]['version'] = $value['timestamp']; $result['all'][$key]['path'] = $filename; $result['all'][$key]['size'] = $size; $result['by_file'][$filename][$key]['version'] = $value['timestamp']; $result['by_file'][$filename][$key]['path'] = $filename; $result['by_file'][$filename][$key]['size'] = $size; } return $result; }
public static function filesize($path) { return self::$defaultInstance->filesize($path); }
/** * @brief restore versions from trash bin * * @param \OC\Files\View $view file view * @param $file complete path to file * @param $filename name of file once it was deleted * @param $uniqueFilename new file name to restore the file without overwriting existing files * @param $location location if file * @param $timestamp deleteion time * * @return size of restored versions */ private static function restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp) { $size = 0; if (\OCP\App::isEnabled('files_versions')) { // disable proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $user = \OCP\User::getUser(); $rootView = new \OC\Files\View('/'); $target = \OC\Files\Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename); list($owner, $ownerPath) = self::getUidAndFilename($target); if ($timestamp) { $versionedFile = $filename; } else { $versionedFile = $file; } if ($view->is_dir('/files_trashbin/versions/' . $file)) { $size += self::calculateSize(new \OC\Files\View('/' . $user . '/' . 'files_trashbin/versions/' . $file)); $rootView->rename(\OC\Files\Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), \OC\Files\Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath)); } else { if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp)) { foreach ($versions as $v) { if ($timestamp) { $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp); $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v); } else { $size += $view->filesize('files_trashbin/versions/' . $versionedFile . '.v' . $v); $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v); } } } } // enable proxy \OC_FileProxy::$enabled = $proxyStatus; } return $size; }
/** * @param string $path raw path relative to data/ * @param string $mode * @param int $options * @param string $opened_path * @return bool * @throw \OCA\Files_Encryption\Exception\EncryptionException */ public function stream_open($path, $mode, $options, &$opened_path) { // read default cipher from config $this->cipher = Helper::getCipher(); // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; $this->rootView = new \OC\Files\View('/'); $this->session = new Session($this->rootView); $this->privateKey = $this->session->getPrivateKey(); if ($this->privateKey === false) { throw new EncryptionException('Session does not contain a private key, maybe your login password changed?', EncryptionException::PRIVATE_KEY_MISSING); } $normalizedPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); $originalFile = Helper::getPathFromTmpFile($normalizedPath); if ($originalFile) { $this->rawPath = $originalFile; $this->isLocalTmpFile = true; $this->localTmpFile = $normalizedPath; } else { $this->rawPath = $normalizedPath; } $this->util = new Util($this->rootView, Helper::getUser($this->rawPath)); // get the key ID which we want to use, can be the users key or the // public share key $this->keyId = $this->util->getKeyId(); $fileType = Helper::detectFileType($this->rawPath); switch ($fileType) { case Util::FILE_TYPE_FILE: $this->relPath = Helper::stripUserFilesPath($this->rawPath); $user = \OC::$server->getUserSession()->getUser(); $this->userId = $user ? $user->getUID() : Helper::getUserFromPath($this->rawPath); break; case Util::FILE_TYPE_VERSION: $this->relPath = Helper::getPathFromVersion($this->rawPath); $this->userId = Helper::getUserFromPath($this->rawPath); break; case Util::FILE_TYPE_CACHE: $this->relPath = Helper::getPathFromCachedFile($this->rawPath); Helper::mkdirr($this->rawPath, new \OC\Files\View('/')); $user = \OC::$server->getUserSession()->getUser(); $this->userId = $user ? $user->getUID() : Helper::getUserFromPath($this->rawPath); break; default: \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to "files", "files_versions" or "cache"', \OCP\Util::ERROR); return false; } // Disable fileproxies so we can get the file size and open the source file without recursive encryption $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($mode === 'w' or $mode === 'w+' or $mode === 'wb' or $mode === 'wb+') { // We're writing a new file so start write counter with 0 bytes $this->size = 0; $this->unencryptedSize = 0; } else { $this->size = $this->rootView->filesize($this->rawPath); $this->readHeader(); } if ($this->isLocalTmpFile) { $this->handle = fopen($this->localTmpFile, $mode); } else { $this->handle = $this->rootView->fopen($this->rawPath, $mode); } \OC_FileProxy::$enabled = $proxyStatus; if (!is_resource($this->handle)) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); } else { $this->meta = stream_get_meta_data($this->handle); // sometimes fopen changes the mode, e.g. for a url "r" convert to "r+" // but we need to remember the original access type $this->meta['mode'] = $mode; } return is_resource($this->handle); }
/** * @param string $path raw path relative to data/ * @param string $mode * @param int $options * @param string $opened_path * @return bool * @throw \OCA\Files_Encryption\Exception\EncryptionException */ public function stream_open($path, $mode, $options, &$opened_path) { // read default cipher from config $this->cipher = Helper::getCipher(); // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; if (!isset($this->rootView)) { $this->rootView = new \OC\Files\View('/'); } $this->session = new Session($this->rootView); $this->privateKey = $this->session->getPrivateKey(); if ($this->privateKey === false) { throw new EncryptionException('Session does not contain a private key, maybe your login password changed?', EncryptionException::PRIVATE_KEY_MISSING); } $normalizedPath = \OC\Files\Filesystem::normalizePath(str_replace('crypt://', '', $path)); if ($originalFile = Helper::getPathFromTmpFile($normalizedPath)) { $this->rawPath = $originalFile; $this->isLocalTmpFile = true; $this->localTmpFile = $normalizedPath; } else { $this->rawPath = $normalizedPath; } $this->userId = Helper::getUser($this->rawPath); $util = new Util($this->rootView, $this->userId); // get the key ID which we want to use, can be the users key or the // public share key $this->keyId = $util->getKeyId(); // Strip identifier text from path, this gives us the path relative to data/<user>/files $this->relPath = Helper::stripUserFilesPath($this->rawPath); // if raw path doesn't point to a real file, check if it is a version or a file in the trash bin if ($this->relPath === false) { $this->relPath = Helper::getPathToRealFile($this->rawPath); } if ($this->relPath === false) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to "files", "files_versions" or "cache"', \OCP\Util::ERROR); return false; } // Disable fileproxies so we can get the file size and open the source file without recursive encryption $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; if ($mode === 'w' or $mode === 'w+' or $mode === 'wb' or $mode === 'wb+') { // We're writing a new file so start write counter with 0 bytes $this->size = 0; $this->unencryptedSize = 0; } else { if ($this->privateKey === false) { // if private key is not valid redirect user to a error page Helper::redirectToErrorPage($this->session); } $this->size = $this->rootView->filesize($this->rawPath); $this->readHeader(); } if ($this->isLocalTmpFile) { $this->handle = fopen($this->localTmpFile, $mode); } else { $this->handle = $this->rootView->fopen($this->rawPath, $mode); } \OC_FileProxy::$enabled = $proxyStatus; if (!is_resource($this->handle)) { \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR); } else { $this->meta = stream_get_meta_data($this->handle); // sometimes fopen changes the mode, e.g. for a url "r" convert to "r+" // but we need to remember the original access type $this->meta['mode'] = $mode; } return is_resource($this->handle); }
/** * Get the size of the requested file */ protected function getFilesize() { return $this->view->filesize($this->filepath); }