This commit is contained in:
jknockaert 2015-03-30 12:21:59 +02:00 committed by Thomas Müller
parent a85e2e0bfd
commit 3e6eb28ee3
1 changed files with 46 additions and 24 deletions

View File

@ -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