Skip to content

Commit 8ff536f

Browse files
authored
Merge pull request #14641 from nextcloud/assemblystream-seek
make assemblystream seekable
2 parents 6bc1c88 + 6a47f92 commit 8ff536f

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

apps/dav/lib/Upload/AssemblyStream.php

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,46 @@ public function stream_open($path, $mode, $options, &$opened_path) {
8383
}
8484

8585
/**
86-
* @param string $offset
86+
* @param int $offset
8787
* @param int $whence
8888
* @return bool
8989
*/
9090
public function stream_seek($offset, $whence = SEEK_SET) {
91-
return false;
91+
if ($whence === SEEK_CUR) {
92+
$offset = $this->stream_tell() + $offset;
93+
} else if ($whence === SEEK_END) {
94+
$offset = $this->size + $offset;
95+
}
96+
97+
if ($offset > $this->size) {
98+
return false;
99+
}
100+
101+
$nodeIndex = 0;
102+
$nodeStart = 0;
103+
while (true) {
104+
if (!isset($this->nodes[$nodeIndex + 1])) {
105+
break;
106+
}
107+
$node = $this->nodes[$nodeIndex];
108+
if ($nodeStart + $node->getSize() > $offset) {
109+
break;
110+
}
111+
$nodeIndex++;
112+
$nodeStart += $node->getSize();
113+
}
114+
115+
$stream = $this->getStream($this->nodes[$nodeIndex]);
116+
$nodeOffset = $offset - $nodeStart;
117+
if(fseek($stream, $nodeOffset) === -1) {
118+
return false;
119+
}
120+
$this->currentNode = $nodeIndex;
121+
$this->currentNodeRead = $nodeOffset;
122+
$this->currentStream = $stream;
123+
$this->pos = $offset;
124+
125+
return true;
92126
}
93127

94128
/**
@@ -210,7 +244,7 @@ public function stream_close() {
210244
*
211245
* @param string $name
212246
* @return array
213-
* @throws \Exception
247+
* @throws \BadMethodCallException
214248
*/
215249
protected function loadContext($name) {
216250
$context = stream_context_get_options($this->context);

apps/dav/tests/unit/Upload/AssemblyStreamTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ public function testGetContentsFread($expected, $nodes) {
5454
$this->assertEquals($expected, $content);
5555
}
5656

57+
/**
58+
* @dataProvider providesNodes()
59+
*/
60+
public function testSeek($expected, $nodes) {
61+
$stream = \OCA\DAV\Upload\AssemblyStream::wrap($nodes);
62+
63+
$offset = floor(strlen($expected) * 0.6);
64+
if(fseek($stream, $offset) === -1) {
65+
$this->fail('fseek failed');
66+
}
67+
68+
$content = stream_get_contents($stream);
69+
$this->assertEquals(substr($expected, $offset), $content);
70+
}
71+
5772
function providesNodes() {
5873
$data8k = $this->makeData(8192);
5974
$dataLess8k = $this->makeData(8191);

0 commit comments

Comments
 (0)