diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2013-10-31 15:27:04 +0400 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2013-10-31 15:27:04 +0400 |
commit | 817a10b465ca04148cbcb5d5a2fb1c558ad1415e (patch) | |
tree | 1a21070f2c788190b7880de2ece4bb74f1c10425 /lib | |
parent | 640a1f28feb18acac8126f7eb2004ac85c416faf (diff) | |
parent | e7fb6be72a3ef548a068f83ac2f4f45ee36c2588 (diff) |
Merge pull request #5327 from owncloud/backport-4867-stable5
[stable5] Adding detection of aborted uploads for chunked uploads
Diffstat (limited to 'lib')
-rw-r--r-- | lib/cache/file.php | 18 | ||||
-rw-r--r-- | lib/connector/sabre/directory.php | 40 | ||||
-rw-r--r-- | lib/filechunking.php | 33 |
3 files changed, 82 insertions, 9 deletions
diff --git a/lib/cache/file.php b/lib/cache/file.php index 361138e4736..eed2637c981 100644 --- a/lib/cache/file.php +++ b/lib/cache/file.php @@ -40,6 +40,24 @@ class OC_Cache_File{ return $result; } + /** + * Returns the size of the stored/cached data + * + * @param $key + * @return int + */ + public function size($key) { + $result = 0; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + if ($this->hasKey($key)) { + $storage = $this->getStorage(); + $result = $storage->filesize($key); + } + \OC_FileProxy::$enabled = $proxyStatus; + return $result; + } + public function set($key, $value, $ttl=0) { $storage = $this->getStorage(); $result = false; diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 96b9cd06d5b..3cccf6ef3d0 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -61,13 +61,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa throw new \Sabre_DAV_Exception_Forbidden(); } - $chunk_handler = new OC_FileChunking($info); - $chunk_handler->store($info['index'], $data); - if ($chunk_handler->isComplete()) { - $newPath = $this->path . '/' . $info['name']; - $chunk_handler->file_assemble($newPath); - return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); - } + return $this->createFileChunked($name, $data); } else { if (!\OC\Files\Filesystem::isCreatable($this->path)) { @@ -264,7 +258,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * If the array is empty, all properties should be returned * * @param array $properties - * @return void + * @return array */ public function getProperties($properties) { $props = parent::getProperties($properties); @@ -274,4 +268,34 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa } return $props; } + + private function createFileChunked($name, $data) + { + $info = OC_FileChunking::decodeName($name); + if (empty($info)) { + throw new Sabre_DAV_Exception_NotImplemented(); + } + $chunk_handler = new OC_FileChunking($info); + $bytesWritten = $chunk_handler->store($info['index'], $data); + + //detect aborted upload + if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) { + if (isset($_SERVER['CONTENT_LENGTH'])) { + $expected = $_SERVER['CONTENT_LENGTH']; + if ($bytesWritten != $expected) { + $chunk_handler->remove($info['index']); + throw new Sabre_DAV_Exception_BadRequest( + 'expected filesize ' . $expected . ' got ' . $bytesWritten); + } + } + } + + if ($chunk_handler->isComplete()) { + $newPath = $this->path . '/' . $info['name']; + $chunk_handler->file_assemble($newPath); + return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); + } + + return null; + } } diff --git a/lib/filechunking.php b/lib/filechunking.php index e6d69273a44..bee6f702298 100644 --- a/lib/filechunking.php +++ b/lib/filechunking.php @@ -34,10 +34,19 @@ class OC_FileChunking { return $this->cache; } + /** + * Stores the given $data under the given $key - the number of stored bytes is returned + * + * @param $index + * @param $data + * @return int + */ public function store($index, $data) { $cache = $this->getCache(); $name = $this->getPrefix().$index; $cache->set($name, $data); + + return $cache->size($name); } public function isComplete() { @@ -58,12 +67,34 @@ class OC_FileChunking { $count = 0; for($i=0; $i < $this->info['chunkcount']; $i++) { $chunk = $cache->get($prefix.$i); - $cache->remove($prefix.$i); $count += fwrite($f, $chunk); } + + $this->cleanup(); return $count; } + /** + * Removes all chunks which belong to this transmission + */ + public function cleanup() { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + for($i=0; $i < $this->info['chunkcount']; $i++) { + $cache->remove($prefix.$i); + } + } + + /** + * Removes one specific chunk + * @param $index + */ + public function remove($index) { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + $cache->remove($prefix.$index); + } + public function signature_split($orgfile, $input) { $info = unpack('n', fread($input, 2)); $blocksize = $info[1]; |