/** * @medium * test if stream wrapper can read files outside from the data folder */ function testStreamFromLocalFile() { $filename = '/' . $this->userId . '/files/' . 'tmp-' . uniqid() . '.txt'; $tmpFilename = "/tmp/" . uniqid() . ".txt"; // write an encrypted file $cryptedFile = $this->view->file_put_contents($filename, $this->dataShort); // Test that data was successfully written $this->assertTrue(is_int($cryptedFile)); // create a copy outside of the data folder in /tmp $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; $encryptedContent = $this->view->file_get_contents($filename); \OC_FileProxy::$enabled = $proxyStatus; file_put_contents($tmpFilename, $encryptedContent); \OCA\Encryption\Helper::addTmpFileToMapper($tmpFilename, $filename); // try to read the file from /tmp $handle = fopen("crypt://" . $tmpFilename, "r"); $contentFromTmpFile = stream_get_contents($handle); // check if it was successful $this->assertEquals($this->dataShort, $contentFromTmpFile); // clean up unlink($tmpFilename); $this->view->unlink($filename); }
/** * get the file size of the unencrypted file * @param string $path absolute path * @return bool */ public function getFileSize($path) { $result = 0; // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // split the path parts $pathParts = explode('/', $path); if (isset($pathParts[2]) && $pathParts[2] === 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) { $offset = 0; if ($this->containHeader($path)) { $offset = Crypt::BLOCKSIZE; } // get the size from filesystem if the file contains a encryption header we // we substract it $size = $this->view->filesize($path) - $offset; // fast path, else the calculation for $lastChunkNr is bogus if ($size === 0) { \OC_FileProxy::$enabled = $proxyStatus; return 0; } // calculate last chunk nr // next highest is end of chunks, one subtracted is last one // we have to read the last chunk, we can't just calculate it (because of padding etc) $lastChunkNr = ceil($size / Crypt::BLOCKSIZE) - 1; $lastChunkSize = $size - $lastChunkNr * Crypt::BLOCKSIZE; // open stream $stream = fopen('crypt://' . $path, "r"); if (is_resource($stream)) { // calculate last chunk position $lastChunckPos = $lastChunkNr * Crypt::BLOCKSIZE; // seek to end 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); // calc the real file size with the size of the last chunk $realSize = $lastChunkNr * 6126 + strlen($lastChunkContent); // store file size $result = $realSize; } } \OC_FileProxy::$enabled = $proxyStatus; return $result; }