*/
class Helper {
+ private static $tmpFileMapping; // Map tmp files to files in data/user/files
+
/**
* @brief register share related hooks
*
public static function escapeGlobPattern($path) {
return preg_replace('/(\*|\?|\[)/', '[$1]', $path);
}
+
+ /**
+ * @brief remember from which file the tmp file (getLocalFile() call) was created
+ * @param string $tmpFile path of tmp file
+ * @param string $originalFile path of the original file relative to data/
+ */
+ public static function addTmpFileToMapper($tmpFile, $originalFile) {
+ self::$tmpFileMapping[$tmpFile] = $originalFile;
+ }
+
+ /**
+ * @brief get the path of the original file
+ * @param string $tmpFile path of the tmp file
+ * @return mixed path of the original file or false
+ */
+ public static function getPathFromTmpFile($tmpFile) {
+ if (isset(self::$tmpFileMapping[$tmpFile])) {
+ return self::$tmpFileMapping[$tmpFile];
+ }
+
+ return false;
+ }
}
private $publicKey;
private $encKeyfile;
private $newFile; // helper var, we only need to write the keyfile for new files
+ private $isLocalTmpFile = false; // do we operate on a local tmp file
+ private $localTmpFile; // path of local tmp file
+
/**
* @var \OC\Files\View
*/
$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));
+ $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);
\OCA\Encryption\Helper::redirectToErrorPage($this->session);
}
- $this->size = $this->rootView->filesize($this->rawPath, $mode);
+ $this->size = $this->rootView->filesize($this->rawPath);
}
- $this->handle = $this->rootView->fopen($this->rawPath, $mode);
+ if ($this->isLocalTmpFile) {
+ $this->handle = fopen($this->localTmpFile, $mode);
+ } else {
+ $this->handle = $this->rootView->fopen($this->rawPath, $mode);
+ }
\OC_FileProxy::$enabled = $proxyStatus;
if ($this->privateKey === false) {
// cleanup
- if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb') {
+ if ($this->meta['mode'] !== 'r' && $this->meta['mode'] !== 'rb' && !$this->isLocalTmpFile) {
// Disable encryption proxy to prevent recursive calls
$proxyStatus = \OC_FileProxy::$enabled;
if (
$this->meta['mode'] !== 'r' &&
$this->meta['mode'] !== 'rb' &&
+ $this->isLocalTmpFile === false &&
$this->size > 0 &&
$this->unencryptedSize > 0
) {
$data = '';
$handle = $this->view->fopen($path, 'r');
if (is_resource($handle)) {
- if (fseek($handle, -24, SEEK_END) === 0) {
+ // suppress fseek warining, we handle the case that fseek doesn't
+ // work in the else branch
+ if (@fseek($handle, -24, SEEK_END) === 0) {
$data = fgets($handle);
} else {
// if fseek failed on the storage we create a local copy from the file
$lastChunckPos = ($lastChunkNr * 8192);
// seek to end
- fseek($stream, $lastChunckPos);
+ if (@fseek($stream, $lastChunckPos) === -1) {
+ // storage doesn't support fseek, we need a local copy
+ fclose($stream);
+ $localFile = $this->view->getLocalFile($path);
+ Helper::addTmpFileToMapper($localFile, $path);
+ $stream = fopen('crypt://' . $localFile, "r");
+ if (fseek($stream, $lastChunckPos) === -1) {
+ // if fseek also fails on the local storage, than
+ // there is nothing we can do
+ fclose($stream);
+ \OCP\Util::writeLog('Encryption library', 'couldn\'t determine size of "' . $path, \OCP\Util::ERROR);
+ return $result;
+ }
+ }
// get the content of the last chunk
$lastChunkContent = fread($stream, $lastChunkSize);