summaryrefslogtreecommitdiffstats
path: root/lib/private/files/stream/encryption.php
diff options
context:
space:
mode:
authorjknockaert <jasper@knockaert.nl>2015-03-30 12:21:59 +0200
committerThomas Müller <thomas.mueller@tmit.eu>2015-04-07 13:30:28 +0200
commit3e6eb28ee39d366bccfb8a1c96839f4b05c9da6e (patch)
tree5688fb4dd5799e81a35dda819327cfc36007c081 /lib/private/files/stream/encryption.php
parenta85e2e0bfdb86de029f7b5fde42ead60498aed82 (diff)
downloadnextcloud-server-3e6eb28ee39d366bccfb8a1c96839f4b05c9da6e.tar.gz
nextcloud-server-3e6eb28ee39d366bccfb8a1c96839f4b05c9da6e.zip
Applying diff as of https://github.com/owncloud/core/pull/15303
Diffstat (limited to 'lib/private/files/stream/encryption.php')
-rw-r--r--lib/private/files/stream/encryption.php70
1 files changed, 46 insertions, 24 deletions
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index ddef9067bad..0cefa53ad82 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -43,6 +43,9 @@ class Encryption extends Wrapper {
/** @var string */
protected $internalPath;
+ /** @var string */
+ protected $cache;
+
/** @var integer */
protected $size;
@@ -79,6 +82,9 @@ class Encryption extends Wrapper {
/** @var bool */
protected $readOnly;
+ /** @var bool */
+ protected $writeFlag;
+
/** @var array */
protected $expectedContextProperties;
@@ -235,18 +241,18 @@ class Encryption extends Wrapper {
while ($count > 0) {
$remainingLength = $count;
// update the cache of the current block
- $data = parent::stream_read($this->util->getBlockSize());
- $decrypted = $this->encryptionModule->decrypt($data);
+ $this->readCache();
// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
// if entire read inside current block then only position needs to be updated
if ($remainingLength < ($this->unencryptedBlockSize - $blockPosition)) {
- $result .= substr($decrypted, $blockPosition, $remainingLength);
+ $result .= substr($this->cache, $blockPosition, $remainingLength);
$this->position += $remainingLength;
$count = 0;
// otherwise remainder of current block is fetched, the block is flushed and the position updated
} else {
- $result .= substr($decrypted, $blockPosition);
+ $result .= substr($this->cache, $blockPosition);
+ $this->flush();
$this->position += ($this->unencryptedBlockSize - $blockPosition);
$count -= ($this->unencryptedBlockSize - $blockPosition);
}
@@ -266,9 +272,8 @@ class Encryption extends Wrapper {
while (strlen($data) > 0) {
$remainingLength = strlen($data);
- // read current block
- $currentBlock = parent::stream_read($this->util->getBlockSize());
- $decrypted = $this->encryptionModule->decrypt($currentBlock, $this->uid);
+ // set the cache to the current 6126 block
+ $this->readCache();
// for seekable streams the pointer is moved back to the beginning of the encrypted block
// flush will start writing there when the position moves to another block
@@ -277,7 +282,10 @@ class Encryption extends Wrapper {
$resultFseek = parent::stream_seek($positionInFile);
// only allow writes on seekable streams, or at the end of the encrypted stream
- if ($resultFseek || $positionInFile === $this->size) {
+ if (!($this->readOnly) && ($resultFseek || $positionInFile === $this->size)) {
+
+ // switch the writeFlag so flush() will write the block
+ $this->writeFlag=true;
// determine the relative position in the current block
$blockPosition = ($this->position % $this->unencryptedBlockSize);
@@ -285,28 +293,22 @@ class Encryption extends Wrapper {
// if so, overwrite existing data (if any)
// update position and liberate $data
if ($remainingLength < ($this->unencryptedBlockSize - $blockPosition)) {
- $decrypted = substr($decrypted, 0, $blockPosition)
- . $data . substr($decrypted, $blockPosition + $remainingLength);
- $encrypted = $this->encryptionModule->encrypt($decrypted);
- parent::stream_write($encrypted);
+ $this->cache = substr($this->cache, 0, $blockPosition)
+ . $data . substr($this->cache, $blockPosition + $remainingLength);
$this->position += $remainingLength;
$length += $remainingLength;
$data = '';
// if $data doens't fit the current block, the fill the current block and reiterate
// after the block is filled, it is flushed and $data is updatedxxx
} else {
- $decrypted = substr($decrypted, 0, $blockPosition) .
+ $this->cache = substr($this->cache, 0, $blockPosition) .
substr($data, 0, $this->unencryptedBlockSize - $blockPosition);
- $encrypted = $this->encryptionModule->encrypt($decrypted);
- parent::stream_write($encrypted);
+ $this->flush();
$this->position += ($this->unencryptedBlockSize - $blockPosition);
- $this->size = max($this->size, $this->stream_tell());
$length += ($this->unencryptedBlockSize - $blockPosition);
$data = substr($data, $this->unencryptedBlockSize - $blockPosition);
}
} else {
- $encrypted = $this->encryptionModule->encrypt($data);
- parent::stream_write($encrypted);
$data = '';
}
}
@@ -346,6 +348,7 @@ class Encryption extends Wrapper {
* $this->util->getBlockSize() + $this->util->getHeaderSize();
if (parent::stream_seek($newFilePosition)) {
+ $this->flush();
$this->position = $newPosition;
$return = true;
}
@@ -359,18 +362,37 @@ class Encryption extends Wrapper {
}
/**
- * tell encryption module that we are done and write remaining data to the file
+ * write block to file
*/
protected function flush() {
- $remainingData = $this->encryptionModule->end($this->fullPath);
- if ($this->readOnly === false) {
- if(!empty($remainingData)) {
- parent::stream_write($remainingData);
- }
+ // write to disk only when writeFlag was set to 1
+ if ($this->writeFlag) {
+ // Disable the file proxies so that encryption is not
+ // automatically attempted when the file is written to disk -
+ // we are handling that separately here and we don't want to
+ // get into an infinite loop
+ $encrypted = $this->encryptionModule->encrypt($this->cache);
+ parent::stream_write($encrypted);
+ $this->writeFlag = false;
$this->encryptionStorage->updateUnencryptedSize($this->fullPath, $this->unencryptedSize);
+ $this->size = max($this->size,parent::stream_tell());
}
+ // always empty the cache (otherwise readCache() will not fill it with the new block)
+ $this->cache = '';
}
+ /**
+ * read block to file
+ */
+ protected function readCache() {
+ // cache should always be empty string when this function is called
+ // don't try to fill the cache when trying to write at the end of the unencrypted file when it coincides with new block
+ if ($this->cache === '' && !($this->position===$this->unencryptedSize && ($this->position % $this->unencryptedBlockSize)===0)) {
+ // Get the data from the file handle
+ $data = parent::stream_read($this->util->getBlockSize());
+ $this->cache = $this->encryptionModule->decrypt($data);
+ }
+ }
/**
* write header at beginning of encrypted file