Example #1
0
 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);
     }
 }
Example #3
0
 /**
  * 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;
 }
Example #4
0
 /**
  * @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);
 }
Example #5
0
 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);
     }
 }
Example #6
0
 /**
  * @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);
 }
Example #7
0
 /**
  * @return int
  */
 public function getSize()
 {
     return $this->view->filesize($this->path);
 }
Example #8
0
 /**
  * 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;
 }
Example #9
0
 /**
  * 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;
 }
Example #10
0
 public static function filesize($path)
 {
     return self::$defaultInstance->filesize($path);
 }
Example #11
0
 /**
  * @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;
 }
Example #12
0
 /**
  * @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);
 }
Example #13
0
 /**
  * @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);
 }
Example #14
0
 /**
  * Get the size of the requested file
  */
 protected function getFilesize()
 {
     return $this->view->filesize($this->filepath);
 }