From d8b245490bf0e74156c66ca594977cbdb2920c4e Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 25 Oct 2013 12:09:46 +0200 Subject: [PATCH 1/3] Fixed quota stream's fseek method - Added missing return statement - Added missing support for SEEK_END - Fixes #5524 --- lib/private/files/stream/quota.php | 14 +++++- tests/lib/files/stream/quota.php | 72 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/lib/private/files/stream/quota.php b/lib/private/files/stream/quota.php index 53d8a03d30..87301c2361 100644 --- a/lib/private/files/stream/quota.php +++ b/lib/private/files/stream/quota.php @@ -66,12 +66,22 @@ class Quota { } public function stream_seek($offset, $whence = SEEK_SET) { - if ($whence === SEEK_SET) { + if ($whence === SEEK_END){ + // go to the end to find out last position's offset + $oldOffset = $this->stream_tell(); + if (fseek($this->source, 0, $whence) !== 0){ + return false; + } + $whence = SEEK_SET; + $offset = $this->stream_tell() + $offset; + $this->limit += $oldOffset - $offset; + } + else if ($whence === SEEK_SET) { $this->limit += $this->stream_tell() - $offset; } else { $this->limit -= $offset; } - fseek($this->source, $offset, $whence); + return !fseek($this->source, $offset, $whence); } public function stream_tell() { diff --git a/tests/lib/files/stream/quota.php b/tests/lib/files/stream/quota.php index 22d3e93592..b11f0ac74c 100644 --- a/tests/lib/files/stream/quota.php +++ b/tests/lib/files/stream/quota.php @@ -75,4 +75,76 @@ class Quota extends \PHPUnit_Framework_TestCase { rewind($stream); $this->assertEquals('qwerty', fread($stream, 100)); } + + public function testFseekReturnsSuccess() { + $stream = $this->getStream('w+', 100); + fwrite($stream, '0123456789'); + $this->assertEquals(0, fseek($stream, 3, SEEK_SET)); + $this->assertEquals(0, fseek($stream, -1, SEEK_CUR)); + $this->assertEquals(0, fseek($stream, -4, SEEK_END)); + } + + public function testWriteAfterSeekEndWithEnoughSpace() { + $stream = $this->getStream('w+', 100); + fwrite($stream, '0123456789'); + fseek($stream, -3, SEEK_END); + $this->assertEquals(11, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); + } + + public function testWriteAfterSeekEndWithNotEnoughSpace() { + $stream = $this->getStream('w+', 13); + fwrite($stream, '0123456789'); + // seek forward first to potentially week out + // potential limit calculation errors + fseek($stream, 4, SEEK_SET); + // seek to the end + fseek($stream, -3, SEEK_END); + $this->assertEquals(6, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdef', fread($stream, 100)); + } + + public function testWriteAfterSeekSetWithEnoughSpace() { + $stream = $this->getStream('w+', 100); + fwrite($stream, '0123456789'); + fseek($stream, 7, SEEK_SET); + $this->assertEquals(11, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); + } + + public function testWriteAfterSeekSetWithNotEnoughSpace() { + $stream = $this->getStream('w+', 13); + fwrite($stream, '0123456789'); + fseek($stream, 7, SEEK_SET); + $this->assertEquals(6, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdef', fread($stream, 100)); + } + + public function testWriteAfterSeekCurWithEnoughSpace() { + $stream = $this->getStream('w+', 100); + fwrite($stream, '0123456789'); + rewind($stream); + fseek($stream, 3, SEEK_CUR); + fseek($stream, 5, SEEK_CUR); + fseek($stream, -1, SEEK_CUR); + $this->assertEquals(11, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdefghijk', fread($stream, 100)); + } + + public function testWriteAfterSeekCurWithNotEnoughSpace() { + $stream = $this->getStream('w+', 13); + fwrite($stream, '0123456789'); + rewind($stream); + fseek($stream, 3, SEEK_CUR); + fseek($stream, 5, SEEK_CUR); + fseek($stream, -1, SEEK_CUR); + $this->assertEquals(6, fwrite($stream, 'abcdefghijk')); + rewind($stream); + $this->assertEquals('0123456abcdef', fread($stream, 100)); + } } From c8df27de73f845f6d1661386f06304b7c209e7d7 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 25 Oct 2013 12:33:16 +0200 Subject: [PATCH 2/3] Fixed quota stream to not wrap read-only fopen calls --- lib/private/files/storage/wrapper/quota.php | 2 +- tests/lib/files/storage/wrapper/quota.php | 22 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php index e2da8cf2e0..43016e0892 100644 --- a/lib/private/files/storage/wrapper/quota.php +++ b/lib/private/files/storage/wrapper/quota.php @@ -95,7 +95,7 @@ class Quota extends Wrapper { public function fopen($path, $mode) { $source = $this->storage->fopen($path, $mode); $free = $this->free_space(''); - if ($free >= 0) { + if ($free >= 0 && $mode !== 'r') { return \OC\Files\Stream\Quota::wrap($source, $free); } else { return $source; diff --git a/tests/lib/files/storage/wrapper/quota.php b/tests/lib/files/storage/wrapper/quota.php index 3702f8154f..9b14335782 100644 --- a/tests/lib/files/storage/wrapper/quota.php +++ b/tests/lib/files/storage/wrapper/quota.php @@ -58,4 +58,26 @@ class Quota extends \Test\Files\Storage\Storage { fclose($stream); $this->assertEquals('foobarqwe', $instance->file_get_contents('foo')); } + + public function testReturnRegularStreamOnRead(){ + $instance = $this->getLimitedStorage(9); + + // create test file first + $stream = $instance->fopen('foo', 'w+'); + fwrite($stream, 'blablacontent'); + fclose($stream); + + $stream = $instance->fopen('foo', 'r'); + $meta = stream_get_meta_data($stream); + $this->assertEquals('plainfile', $meta['wrapper_type']); + fclose($stream); + } + + public function testReturnQuotaStreamOnWrite(){ + $instance = $this->getLimitedStorage(9); + $stream = $instance->fopen('foo', 'w+'); + $meta = stream_get_meta_data($stream); + $this->assertEquals('user-space', $meta['wrapper_type']); + fclose($stream); + } } From ebcd9ae6280a7658313a51272dc6cdffe9c17494 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 25 Oct 2013 16:15:01 +0200 Subject: [PATCH 3/3] Added comment for clarification about fseek() call in quota.php --- lib/private/files/stream/quota.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/private/files/stream/quota.php b/lib/private/files/stream/quota.php index 87301c2361..60e60da8e6 100644 --- a/lib/private/files/stream/quota.php +++ b/lib/private/files/stream/quota.php @@ -81,6 +81,8 @@ class Quota { } else { $this->limit -= $offset; } + // this wrapper needs to return "true" for success. + // the fseek call itself returns 0 on succeess return !fseek($this->source, $offset, $whence); }