diff options
-rw-r--r-- | apps/files_sharing/appinfo/update.php | 17 | ||||
-rw-r--r-- | apps/files_sharing/appinfo/version | 2 | ||||
-rw-r--r-- | apps/files_sharing/lib/updater.php | 15 | ||||
-rw-r--r-- | apps/files_sharing/tests/updater.php | 91 | ||||
-rw-r--r-- | lib/private/connector/sabre/quotaplugin.php | 11 | ||||
-rw-r--r-- | lib/private/filechunking.php | 40 | ||||
-rw-r--r-- | settings/js/users.js | 2 |
7 files changed, 158 insertions, 20 deletions
diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 4b716e764f4..ab32108ea25 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -71,19 +71,6 @@ if (version_compare($installedVersion, '0.3', '<')) { } // clean up oc_share table from files which are no longer exists -if (version_compare($installedVersion, '0.3.5', '<')) { - - // 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 AND `*PREFIX*share`.`item_type` IN (\'file\', \'folder\')'); - $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))); - } +if (version_compare($installedVersion, '0.3.5.6', '<')) { + \OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate(); } diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 09e9157034c..8f91d33378e 100644 --- a/apps/files_sharing/appinfo/version +++ b/apps/files_sharing/appinfo/version @@ -1 +1 @@ -0.3.5
\ No newline at end of file +0.3.5.6 diff --git a/apps/files_sharing/lib/updater.php b/apps/files_sharing/lib/updater.php index 23ebc9fb811..e3a7679292d 100644 --- a/apps/files_sharing/lib/updater.php +++ b/apps/files_sharing/lib/updater.php @@ -135,4 +135,19 @@ class Shared_Updater { } } + /** + * clean up oc_share table from files which are no longer exists + * + * This fixes issues from updates from files_sharing < 0.3.5.6 (ownCloud 4.5) + * It will just be called during the update of the app + */ + static public function fixBrokenSharesOnAppUpdate() { + // delete all shares where the original file no longer exists + $findAndRemoveShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share` ' . + 'WHERE `file_source` NOT IN ( ' . + 'SELECT `fileid` FROM `*PREFIX*filecache` WHERE `item_type` IN (\'file\', \'folder\'))' + ); + $findAndRemoveShares->execute(array()); + } + } diff --git a/apps/files_sharing/tests/updater.php b/apps/files_sharing/tests/updater.php new file mode 100644 index 00000000000..79ae4879b64 --- /dev/null +++ b/apps/files_sharing/tests/updater.php @@ -0,0 +1,91 @@ +<?php +/** + * ownCloud + * + * @author Morris Jobke + * @copyright 2014 Morris Jobke <morris.jobke@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * Class Test_Files_Sharing_Updater + */ +class Test_Files_Sharing_Updater extends \PHPUnit_Framework_TestCase { + + function setUp() { + // some previous tests didn't clean up and therefore this has to be done here + // FIXME: DIRTY HACK - TODO: find tests, that don't clean up and fix it there + $this->tearDown(); + + // add items except one - because this is the test case for the broken share table + $addItems = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` (`storage`, `path_hash`, ' . + '`parent`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`) ' . + 'VALUES (1, ?, 1, 1, 1, 1, 1, 1)'); + $items = array(1, 3); + $fileIds = array(); + foreach($items as $item) { + // the number is used as path_hash + $addItems->execute(array($item)); + $fileIds[] = \OC_DB::insertId('*PREFIX*filecache'); + } + + $addShares = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`file_source`, `item_type`, `uid_owner`) VALUES (?, \'file\', 1)'); + // the number is used as item_source + $addShares->execute(array($fileIds[0])); + $addShares->execute(array(200)); // id of "deleted" file + $addShares->execute(array($fileIds[1])); + } + + function tearDown() { + $removeShares = \OC_DB::prepare('DELETE FROM `*PREFIX*share`'); + $removeShares->execute(); + $removeItems = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache`'); + $removeItems->execute(); + } + + /** + * @medium + */ + function testRemoveBrokenShares() { + // check if there are just 3 shares (see setUp - precondition: empty table) + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(3, $result); + + // check if there are just 2 items (see setUp - precondition: empty table) + $countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`'); + $result = $countItems->execute()->fetchOne(); + $this->assertEquals(2, $result); + + // execute actual code which should be tested + \OC\Files\Cache\Shared_Updater::fixBrokenSharesOnAppUpdate(); + + // check if there are just 2 shares (one gets killed by the code as there is no filecache entry for this) + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share`'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(2, $result); + + // check if the share of file '200' is removed as there is no entry for this in filecache table + $countShares = \OC_DB::prepare('SELECT COUNT(`id`) FROM `*PREFIX*share` WHERE `file_source` = 200'); + $result = $countShares->execute()->fetchOne(); + $this->assertEquals(0, $result); + + // check if there are just 2 items + $countItems = \OC_DB::prepare('SELECT COUNT(`fileid`) FROM `*PREFIX*filecache`'); + $result = $countItems->execute()->fetchOne(); + $this->assertEquals(2, $result); + } +} diff --git a/lib/private/connector/sabre/quotaplugin.php b/lib/private/connector/sabre/quotaplugin.php index 8099794f670..227e684741c 100644 --- a/lib/private/connector/sabre/quotaplugin.php +++ b/lib/private/connector/sabre/quotaplugin.php @@ -56,8 +56,19 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin { $uri='/'.$uri; } list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri); + $req = $this->server->httpRequest; + if ($req->getHeader('OC-Chunked')) { + $info = OC_FileChunking::decodeName($newName); + $chunkHandler = new OC_FileChunking($info); + // substract the already uploaded size to see whether + // there is still enough space for the remaining chunks + $length -= $chunkHandler->getCurrentSize(); + } $freeSpace = $this->getFreeSpace($parentUri); if ($freeSpace !== \OC\Files\SPACE_UNKNOWN && $length > $freeSpace) { + if (isset($chunkHandler)) { + $chunkHandler->cleanup(); + } throw new Sabre_DAV_Exception_InsufficientStorage(); } } diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php index be7f4e14a11..1da02fc81e3 100644 --- a/lib/private/filechunking.php +++ b/lib/private/filechunking.php @@ -64,20 +64,46 @@ class OC_FileChunking { return $parts == $this->info['chunkcount']; } + /** + * Assembles the chunks into the file specified by the path. + * Chunks are deleted afterwards. + * + * @param string $f target path + * + * @return assembled file size + * + * @throws \OC\InsufficientStorageException when file could not be fully + * assembled due to lack of free space + */ public function assemble($f) { $cache = $this->getCache(); $prefix = $this->getPrefix(); $count = 0; - for($i=0; $i < $this->info['chunkcount']; $i++) { + for ($i = 0; $i < $this->info['chunkcount']; $i++) { $chunk = $cache->get($prefix.$i); + // remove after reading to directly save space + $cache->remove($prefix.$i); $count += fwrite($f, $chunk); } - $this->cleanup(); return $count; } /** + * Returns the size of the chunks already present + * @return size in bytes + */ + public function getCurrentSize() { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + $total = 0; + for ($i = 0; $i < $this->info['chunkcount']; $i++) { + $total += $cache->size($prefix.$i); + } + return $total; + } + + /** * Removes all chunks which belong to this transmission */ public function cleanup() { @@ -128,7 +154,15 @@ class OC_FileChunking { } /** - * @param string $path + * Assembles the chunks into the file specified by the path. + * Also triggers the relevant hooks and proxies. + * + * @param string $path target path + * + * @return assembled file size or false if file could not be created + * + * @throws \OC\InsufficientStorageException when file could not be fully + * assembled due to lack of free space */ public function file_assemble($path) { $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path)); diff --git a/settings/js/users.js b/settings/js/users.js index 284976d3bad..eef3c237277 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -226,7 +226,7 @@ var UserList = { $('table+.loading').css('visibility', 'visible'); UserList.updating = true; var query = $.param({ offset: UserList.offset, limit: UserList.usersToLoad }); - $.get(OC.generateUrl('/settings/ajax/userlist') + query, function (result) { + $.get(OC.generateUrl('/settings/ajax/userlist') + '?' + query, function (result) { var loadedUsers = 0; var trs = []; if (result.status === 'success') { |