diff options
-rw-r--r-- | apps/files/js/files.js | 14 | ||||
-rw-r--r-- | apps/files_sharing/appinfo/update.php | 22 | ||||
-rw-r--r-- | apps/files_sharing/appinfo/version | 2 | ||||
-rw-r--r-- | apps/files_sharing/lib/updater.php | 19 | ||||
-rw-r--r-- | lib/private/connector/sabre/directory.php | 48 | ||||
-rw-r--r-- | lib/private/connector/sabre/file.php | 66 | ||||
-rw-r--r-- | lib/private/connector/sabre/node.php | 17 | ||||
-rwxr-xr-x | lib/private/util.php | 5 | ||||
-rw-r--r-- | tests/lib/connector/sabre/file.php | 38 |
9 files changed, 147 insertions, 84 deletions
diff --git a/apps/files/js/files.js b/apps/files/js/files.js index 899bc6469e5..53858d65c65 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -98,6 +98,8 @@ Files={ lastWidth: 0, initBreadCrumbs: function () { + var $controls = $('#controls'); + Files.lastWidth = 0; Files.breadcrumbs = []; @@ -118,7 +120,10 @@ Files={ }); // event handlers for breadcrumb items - $('#controls .crumb a').on('click', onClickBreadcrumb); + $controls.find('.crumb a').on('click', onClickBreadcrumb); + + // setup drag and drop + $controls.find('.crumb:not(.last)').droppable(crumbDropOptions); }, resizeBreadcrumbs: function (width, firstRun) { @@ -176,11 +181,8 @@ $(document).ready(function() { $('#file_action_panel').attr('activeAction', false); - $('div.crumb:not(.last)').droppable(crumbDropOptions); - $('ul#apps>li:first-child').data('dir',''); - if($('div.crumb').length){ - $('ul#apps>li:first-child').droppable(crumbDropOptions); - } + // allow dropping on the "files" app icon + $('ul#apps li:first-child').data('dir','').droppable(crumbDropOptions); // Triggers invisible file input $('#upload a').on('click', function() { diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 48e41e93048..bc33dd40437 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -68,11 +68,21 @@ if (version_compare($installedVersion, '0.3', '<')) { // $query = OCP\DB::prepare('DROP TABLE `*PREFIX*sharing`'); // $query->execute(); } -if (version_compare($installedVersion, '0.3.3', '<')) { - OC_User::useBackend(new OC_User_Database()); - OC_App::loadApps(array('authentication')); - $users = OC_User::getUsers(); - foreach ($users as $user) { -// OC_FileCache::delete('Shared', '/'.$user.'/files/'); + +// clean up oc_share table from files which are no longer exists +if (version_compare($installedVersion, '0.3.4', '<')) { + + // get all shares where the original file no longer exists + $findShares = \OC_DB::prepare('SELECT `file_source` FROM `*PREFIX*share` LEFT JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` WHERE `*PREFIX*filecache`.`fileid` IS NULL'); + $sharesFound = $findShares->execute(array())->fetchAll(); + + // delete those shares from the oc_share table + if (is_array($sharesFound) && !empty($sharesFound)) { + $delArray = array(); + foreach ($sharesFound as $share) { + $delArray[] = $share['file_source']; + } + $removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `file_source` IN (?)'); + $result = $removeShares->execute(array(implode(',', $delArray))); } } diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 87a0871112f..448a0fa11cd 100644 --- a/apps/files_sharing/appinfo/version +++ b/apps/files_sharing/appinfo/version @@ -1 +1 @@ -0.3.3
\ No newline at end of file +0.3.4
\ No newline at end of file diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index a43ab2e2a0a..08aaa62e252 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -58,6 +58,23 @@ class Shared_Updater { } /** + * @brief remove all shares for a given file if the file was deleted + * + * @param string $path + */ + private static function removeShare($path) { + $fileInfo = \OC\Files\Filesystem::getFileInfo($path); + $fileSource = $fileInfo['fileid']; + + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `file_source`=?'); + try { + \OC_DB::executeAudited($query, array($fileSource)); + } catch (\Exception $e) { + \OCP\Util::writeLog('files_sharing', "can't remove share: " . $e->getMessage(), \OCP\Util::WARN); + } + } + + /** * @param array $params */ static public function writeHook($params) { @@ -77,8 +94,10 @@ class Shared_Updater { */ static public function deleteHook($params) { self::correctFolders($params['path']); + self::removeShare($params['path']); } + /** * @param array $params */ diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 382bdf06df1..af0dfd70f08 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -54,47 +54,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa throw new \Sabre_DAV_Exception_Forbidden(); } - if (isset($_SERVER['HTTP_OC_CHUNKED'])) { - $info = OC_FileChunking::decodeName($name); - if (empty($info)) { - throw new Sabre_DAV_Exception_NotImplemented(); - } - $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); - } - } else { - $newPath = $this->path . '/' . $name; - - // mark file as partial while uploading (ignored by the scanner) - $partpath = $newPath . '.part'; - - \OC\Files\Filesystem::file_put_contents($partpath, $data); - - // rename to correct path - $renameOkay = \OC\Files\Filesystem::rename($partpath, $newPath); - $fileExists = \OC\Files\Filesystem::file_exists($newPath); - if ($renameOkay === false || $fileExists === false) { - \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); - \OC\Files\Filesystem::unlink($partpath); - throw new Sabre_DAV_Exception(); - } - - // allow sync clients to send the mtime along in a header - $mtime = OC_Request::hasModificationTime(); - if ($mtime !== false) { - if(\OC\Files\Filesystem::touch($newPath, $mtime)) { - header('X-OC-MTime: accepted'); - } - } - - return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); - } + $path = $this->path . '/' . $name; + $node = new OC_Connector_Sabre_File($path); + return $node->put($data); - return null; } /** @@ -243,13 +206,12 @@ 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); if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) { - $props[self::GETETAG_PROPERTYNAME] - = OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); + $props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path); } return $props; } diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 433b1148552..8ffec371e3f 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -28,7 +28,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * * The data argument is a readable stream resource. * - * After a succesful put operation, you may choose to return an ETag. The + * After a successful put operation, you may choose to return an ETag. The * etag must always be surrounded by double-quotes. These quotes must * appear in the actual string you're returning. * @@ -45,8 +45,9 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @return string|null */ public function put($data) { - - if (!\OC\Files\Filesystem::isUpdatable($this->path)) { + $fs = $this->getFS(); + if ($fs->file_exists($this->path) && + !$fs->isUpdatable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -54,44 +55,59 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D if (\OC_Util::encryptedFiles()) { throw new \Sabre_DAV_Exception_ServiceUnavailable(); } - + + // chunked handling + if (isset($_SERVER['HTTP_OC_CHUNKED'])) { + list(, $name) = \Sabre_DAV_URLUtil::splitPath($this->path); + + $info = OC_FileChunking::decodeName($name); + if (empty($info)) { + throw new Sabre_DAV_Exception_NotImplemented(); + } + $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 $this->getETagPropertyForPath($newPath); + } + + return null; + } + // mark file as partial while uploading (ignored by the scanner) $partpath = $this->path . '.part'; - \OC\Files\Filesystem::file_put_contents($partpath, $data); - - //detect aborted upload - if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') { - if (isset($_SERVER['CONTENT_LENGTH'])) { - $expected = $_SERVER['CONTENT_LENGTH']; - $actual = \OC\Files\Filesystem::filesize($partpath); - if ($actual != $expected) { - \OC\Files\Filesystem::unlink($partpath); - throw new Sabre_DAV_Exception_BadRequest( - 'expected filesize ' . $expected . ' got ' . $actual); - } + try { + $putOkay = $fs->file_put_contents($partpath, $data); + if ($putOkay === false) { + \OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR); + $fs->unlink($partpath); + // because we have no clue about the cause we can only throw back a 500/Internal Server Error + throw new Sabre_DAV_Exception(); } + } catch (\OCP\Files\NotPermittedException $e) { + throw new Sabre_DAV_Exception_Forbidden(); } // rename to correct path - $renameOkay = \OC\Files\Filesystem::rename($partpath, $this->path); - $fileExists = \OC\Files\Filesystem::file_exists($this->path); + $renameOkay = $fs->rename($partpath, $this->path); + $fileExists = $fs->file_exists($this->path); if ($renameOkay === false || $fileExists === false) { \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); - \OC\Files\Filesystem::unlink($partpath); + $fs->unlink($partpath); throw new Sabre_DAV_Exception(); } - - //allow sync clients to send the mtime along in a header + // allow sync clients to send the mtime along in a header $mtime = OC_Request::hasModificationTime(); if ($mtime !== false) { - if (\OC\Files\Filesystem::touch($this->path, $mtime)) { + if($fs->touch($this->path, $mtime)) { header('X-OC-MTime: accepted'); } } - return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); + return $this->getETagPropertyForPath($this->path); } /** @@ -101,7 +117,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function get() { - //throw execption if encryption is disabled but files are still encrypted + //throw exception if encryption is disabled but files are still encrypted if (\OC_Util::encryptedFiles()) { throw new \Sabre_DAV_Exception_ServiceUnavailable(); } else { @@ -144,7 +160,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * * An ETag is a unique identifier representing the current version of the * file. If the file changes, the ETag MUST change. The ETag is an - * arbritrary string, but MUST be surrounded by double-quotes. + * arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined * diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php index e65ad7b8bef..fa27abb381a 100644 --- a/lib/private/connector/sabre/node.php +++ b/lib/private/connector/sabre/node.php @@ -33,6 +33,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr public static $ETagFunction = null; /** + * is kept public to allow overwrite for unit testing + * + * @var \OC\Files\View + */ + public $fileView; + + /** * The path to the current node * * @var string @@ -234,12 +241,18 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @param string $path Path of the file * @return string|null Returns null if the ETag can not effectively be determined */ - static public function getETagPropertyForPath($path) { - $data = \OC\Files\Filesystem::getFileInfo($path); + protected function getETagPropertyForPath($path) { + $data = $this->getFS()->getFileInfo($path); if (isset($data['etag'])) { return '"'.$data['etag'].'"'; } return null; } + protected function getFS() { + if (is_null($this->fileView)) { + $this->fileView = \OC\Files\Filesystem::getView(); + } + return $this->fileView; + } } diff --git a/lib/private/util.php b/lib/private/util.php index c5b4d2ae93e..6c0a8d7bab5 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -182,9 +182,12 @@ class OC_Util { * @description load the version.php into the session as cache */ private static function loadVersion() { - if(!\OC::$server->getSession()->exists('OC_Version')) { + $timestamp = filemtime(OC::$SERVERROOT.'/version.php'); + if(!\OC::$server->getSession()->exists('OC_Version') or OC::$server->getSession()->get('OC_Version_Timestamp') != $timestamp) { require 'version.php'; $session = \OC::$server->getSession(); + /** @var $timestamp int */ + $session->set('OC_Version_Timestamp', $timestamp); /** @var $OC_Version string */ $session->set('OC_Version', $OC_Version); /** @var $OC_VersionString string */ diff --git a/tests/lib/connector/sabre/file.php b/tests/lib/connector/sabre/file.php new file mode 100644 index 00000000000..a1dade3d63d --- /dev/null +++ b/tests/lib/connector/sabre/file.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase { + + /** + * @expectedException Sabre_DAV_Exception + */ + public function testSimplePutFails() { + // setup + $file = new OC_Connector_Sabre_File('/test.txt'); + $file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents'), array(), '', FALSE); + $file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(false)); + + // action + $etag = $file->put('test data'); + } + + /** + * @expectedException Sabre_DAV_Exception + */ + public function testSimplePutFailsOnRename() { + // setup + $file = new OC_Connector_Sabre_File('/test.txt'); + $file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents', 'rename'), array(), '', FALSE); + $file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(true)); + $file->fileView->expects($this->any())->method('rename')->withAnyParameters()->will($this->returnValue(false)); + + // action + $etag = $file->put('test data'); + } + +} |