From e13be94e56ec59d92b6c9cf67b7a17bd03438efb Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 6 Dec 2013 17:23:51 +0100 Subject: [PATCH 01/51] Fixed Dropbox/Google storage async save call When clicking "Grant access", the settings for Dropbox/Google were saved through a call that gets cancelled when redirecting to the grant page (for example in Firefox) This fix makes sure the "save settings" call finished before redirecting to the grant page. Fixes #6176 --- apps/files_external/js/dropbox.js | 17 +++++++++-------- apps/files_external/js/google.js | 21 +++++++++++---------- apps/files_external/js/settings.js | 14 +++++++++++++- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/apps/files_external/js/dropbox.js b/apps/files_external/js/dropbox.js index 957daeb4d1f..6baaabe11b6 100644 --- a/apps/files_external/js/dropbox.js +++ b/apps/files_external/js/dropbox.js @@ -23,9 +23,12 @@ $(document).ready(function() { $(token).val(result.access_token); $(token_secret).val(result.access_token_secret); $(configured).val('true'); - OC.MountConfig.saveStorage(tr); - $(tr).find('.configuration input').attr('disabled', 'disabled'); - $(tr).find('.configuration').append(''+t('files_external', 'Access granted')+''); + OC.MountConfig.saveStorage(tr, function(status) { + if (status) { + $(tr).find('.configuration input').attr('disabled', 'disabled'); + $(tr).find('.configuration').append(''+t('files_external', 'Access granted')+''); + } + }); } else { OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Dropbox storage')); } @@ -77,7 +80,6 @@ $(document).ready(function() { var tr = $(this).parent().parent(); var app_key = $(this).parent().find('[data-parameter="app_key"]').val(); var app_secret = $(this).parent().find('[data-parameter="app_secret"]').val(); - var statusSpan = $(tr).find('.status span'); if (app_key != '' && app_secret != '') { var tr = $(this).parent().parent(); var configured = $(this).parent().find('[data-parameter="configured"]'); @@ -88,10 +90,9 @@ $(document).ready(function() { $(configured).val('false'); $(token).val(result.data.request_token); $(token_secret).val(result.data.request_token_secret); - OC.MountConfig.saveStorage(tr); - statusSpan.removeClass(); - statusSpan.addClass('waiting'); - window.location = result.data.url; + OC.MountConfig.saveStorage(tr, function() { + window.location = result.data.url; + }); } else { OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Dropbox storage')); } diff --git a/apps/files_external/js/google.js b/apps/files_external/js/google.js index b4be1c1dc41..068c2c13c66 100644 --- a/apps/files_external/js/google.js +++ b/apps/files_external/js/google.js @@ -32,11 +32,14 @@ $(document).ready(function() { if (result && result.status == 'success') { $(token).val(result.data.token); $(configured).val('true'); - OC.MountConfig.saveStorage(tr); - $(tr).find('.configuration input').attr('disabled', 'disabled'); - $(tr).find('.configuration').append($('') - .attr('id', 'access') - .text(t('files_external', 'Access granted'))); + OC.MountConfig.saveStorage(tr, function(status) { + if (status) { + $(tr).find('.configuration input').attr('disabled', 'disabled'); + $(tr).find('.configuration').append($('') + .attr('id', 'access') + .text(t('files_external', 'Access granted'))); + } + }); } else { OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Google Drive storage') @@ -99,7 +102,6 @@ $(document).ready(function() { var configured = $(this).parent().find('[data-parameter="configured"]'); var client_id = $(this).parent().find('[data-parameter="client_id"]').val(); var client_secret = $(this).parent().find('[data-parameter="client_secret"]').val(); - var statusSpan = $(tr).find('.status span'); if (client_id != '' && client_secret != '') { var token = $(this).parent().find('[data-parameter="token"]'); $.post(OC.filePath('files_external', 'ajax', 'google.php'), @@ -112,10 +114,9 @@ $(document).ready(function() { if (result && result.status == 'success') { $(configured).val('false'); $(token).val('false'); - OC.MountConfig.saveStorage(tr); - statusSpan.removeClass(); - statusSpan.addClass('waiting'); - window.location = result.data.url; + OC.MountConfig.saveStorage(tr, function(status) { + window.location = result.data.url; + }); } else { OC.dialogs.alert(result.data.message, t('files_external', 'Error configuring Google Drive storage') diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index 886c324e338..895f97bd2c3 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -12,7 +12,7 @@ function updateStatus(statusEl, result){ } OC.MountConfig={ - saveStorage:function(tr) { + saveStorage:function(tr, callback) { var mountPoint = $(tr).find('.mountPoint input').val(); if (mountPoint == '') { return false; @@ -84,9 +84,15 @@ OC.MountConfig={ }, success: function(result) { status = updateStatus(statusSpan, result); + if (callback) { + callback(status); + } }, error: function(result){ status = updateStatus(statusSpan, result); + if (callback) { + callback(status); + } } }); }); @@ -137,9 +143,15 @@ OC.MountConfig={ }, success: function(result) { status = updateStatus(statusSpan, result); + if (callback) { + callback(status); + } }, error: function(result){ status = updateStatus(statusSpan, result); + if (callback) { + callback(status); + } } }); } From baccc8f584940d607393ef2bdd9c6d3e511b75b8 Mon Sep 17 00:00:00 2001 From: ben-denham Date: Mon, 6 Jan 2014 11:14:43 +1300 Subject: [PATCH 02/51] Unshare all will now delete all shares for the item, instead of only for a single owner. --- lib/public/share.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/public/share.php b/lib/public/share.php index f0fd8e1ab1b..eb1dd8d1c95 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -655,7 +655,15 @@ class Share { * @return Returns true on success or false on failure */ public static function unshareAll($itemType, $itemSource) { - if ($shares = self::getItemShared($itemType, $itemSource)) { + // Get all of the owners of shares of this item. + $query = \OC_DB::prepare( 'SELECT `uid_owner` from `*PREFIX*share` WHERE `item_type`=? AND `item_source`=?' ); + $result = $query->execute(array($itemType, $itemSource)); + $shares = array(); + // Add each owner's shares to the array of all shares for this item. + while ($row = $result->fetchRow()) { + $shares = array_merge($shares, self::getItems($itemType, $itemSource, null, null, $row['uid_owner'])); + } + if (!empty($shares)) { // Pass all the vars we have for now, they may be useful $hookParams = array( 'itemType' => $itemType, From 30f77f53d5c97e369a879eab9381b856a5caf79c Mon Sep 17 00:00:00 2001 From: ben-denham Date: Fri, 10 Jan 2014 14:08:29 +1300 Subject: [PATCH 03/51] updated the unit test for OCP\Share::unshareAll() to verify that shares by all users are removed for an item. --- tests/lib/share/share.php | 58 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index 84e2e5c63eb..2fe2837019f 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -149,6 +149,26 @@ class Test_Share extends PHPUnit_Framework_TestCase { ); } + protected function shareUserTestFileWithUser($sharer, $receiver) { + OC_User::setUserId($sharer); + $this->assertTrue( + OCP\Share::shareItem('test', 'test.txt', OCP\Share::SHARE_TYPE_USER, $receiver, OCP\PERMISSION_READ | OCP\PERMISSION_SHARE), + 'Failed asserting that ' . $sharer . ' successfully shared text.txt with ' . $receiver . '.' + ); + $this->assertContains( + 'test.txt', + OCP\Share::getItemShared('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE), + 'Failed asserting that test.txt is a shared file of ' . $sharer . '.' + ); + + OC_User::setUserId($receiver); + $this->assertContains( + 'test.txt', + OCP\Share::getItemSharedWith('test', 'test.txt', Test_Share_Backend::FORMAT_SOURCE), + 'Failed asserting that ' . $receiver . ' has access to test.txt after initial sharing.' + ); + } + public function testShareWithUser() { // Invalid shares $message = 'Sharing test.txt failed, because the user '.$this->user1.' is the item owner'; @@ -585,25 +605,55 @@ class Test_Share extends PHPUnit_Framework_TestCase { } public function testUnshareAll() { - $this->shareUserOneTestFileWithUserTwo(); + $this->shareUserTestFileWithUser($this->user1, $this->user2); + $this->shareUserTestFileWithUser($this->user2, $this->user3); + $this->shareUserTestFileWithUser($this->user3, $this->user4); $this->shareUserOneTestFileWithGroupOne(); OC_User::setUserId($this->user1); $this->assertEquals( array('test.txt', 'test.txt'), OCP\Share::getItemsShared('test', 'test.txt'), - 'Failed asserting that the test.txt file is shared exactly two times.' + 'Failed asserting that the test.txt file is shared exactly two times by user1.' + ); + + OC_User::setUserId($this->user2); + $this->assertEquals( + array('test.txt'), + OCP\Share::getItemsShared('test', 'test.txt'), + 'Failed asserting that the test.txt file is shared exactly once by user2.' + ); + + OC_User::setUserId($this->user3); + $this->assertEquals( + array('test.txt'), + OCP\Share::getItemsShared('test', 'test.txt'), + 'Failed asserting that the test.txt file is shared exactly once by user3.' ); $this->assertTrue( OCP\Share::unshareAll('test', 'test.txt'), - 'Failed asserting that user 1 successfully unshared all shares of the test.txt share.' + 'Failed asserting that user 3 successfully unshared all shares of the test.txt share.' ); $this->assertEquals( array(), OCP\Share::getItemsShared('test'), - 'Failed asserting that both shares of the test.txt file have been removed.' + 'Failed asserting that the share of the test.txt file by user 3 has been removed.' + ); + + OC_User::setUserId($this->user1); + $this->assertEquals( + array(), + OCP\Share::getItemsShared('test'), + 'Failed asserting that both shares of the test.txt file by user 1 have been removed.' + ); + + OC_User::setUserId($this->user2); + $this->assertEquals( + array(), + OCP\Share::getItemsShared('test'), + 'Failed asserting that the share of the test.txt file by user 2 has been removed.' ); } } From 2abea964625713180d811e4fd1cfd25a92ee2c88 Mon Sep 17 00:00:00 2001 From: Joan Date: Fri, 10 Jan 2014 09:33:35 +0100 Subject: [PATCH 04/51] Disabled internet checking as mentioned when in proxy mode --- lib/private/util.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/private/util.php b/lib/private/util.php index c0e618cc863..9b37dccb507 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -892,6 +892,11 @@ class OC_Util { return false; } + // in case the connection is via proxy return true to avoid connecting to owncloud.org + if(OC_Config::getValue('proxy', '') != '') { + return true; + } + // try to connect to owncloud.org to see if http connections to the internet are possible. $connected = @fsockopen("www.owncloud.org", 80); if ($connected) { From 0802b662be298fac5787576007233f8ce456581c Mon Sep 17 00:00:00 2001 From: Myles McNamara Date: Fri, 10 Jan 2014 12:20:31 -0500 Subject: [PATCH 05/51] fix upload button layout --- apps/files_sharing/templates/public.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 1d527dca8eb..a427e3d8f28 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -24,9 +24,10 @@ - Download" - />t('Download'))?> + + Download" /> + t('Download'))?> + @@ -43,9 +44,10 @@ -
+ From 9ebffd663532bb74075e6858559eb6506004a7c5 Mon Sep 17 00:00:00 2001 From: Myles McNamara Date: Fri, 10 Jan 2014 14:03:55 -0500 Subject: [PATCH 06/51] remove extra upload controls --- apps/files_sharing/templates/public.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index a427e3d8f28..8b5e0976412 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -53,20 +53,8 @@
- -
From 97be32e2e8291f3c5412bc9cbbdeda38552bbb81 Mon Sep 17 00:00:00 2001 From: Myles McNamara Date: Fri, 10 Jan 2014 14:07:20 -0500 Subject: [PATCH 07/51] modify js to move upload wrapper, modify css to match core values --- apps/files_sharing/css/public.css | 17 ++++++++++------- apps/files_sharing/js/public.js | 3 ++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index 060d4dfedc7..be53a7d8a84 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -141,10 +141,13 @@ thead{ .directLink { margin-bottom: 20px; } - .directLink label { - font-weight: normal; - } - .directLink input { - margin-left: 10px; - width: 300px; - } +.directLink label { + font-weight: normal; +} +.directLink input { + margin-left: 10px; + width: 300px; +} +.public_actions { + padding: 0.3em; +} diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index eacd4096ed8..88dbac9c88a 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -59,7 +59,8 @@ $(document).ready(function() { }); // Add Uploadprogress Wrapper to controls bar - $('#controls').append($('#additional_controls div#uploadprogresswrapper')); + $('#controls').append($('#controls .actions div#uploadprogresswrapper')); + $('#uploadprogresswrapper').addClass('public_actions'); // Cancel upload trigger $('#cancel_upload_button').click(function() { From 7c1649fc2441f5fa0b21749e549a76ea26128edd Mon Sep 17 00:00:00 2001 From: tsumi Date: Fri, 10 Jan 2014 21:19:30 +0100 Subject: [PATCH 08/51] Added SVG fallback to apps settings popup This fix issue of calendar app with IE8, see issue report for details: https://github.com/owncloud/calendar/issues/291 --- core/js/js.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/js/js.js b/core/js/js.js index f380234af05..92f2ac484e4 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -416,6 +416,11 @@ var OC={ throw e; }); } + if(!SVGSupport()) { + replaceSVG(); + } else { + SVGSupport.checkMimeType(); + } }).show(); }, 'html'); } From 8135828b2ed411c06bcde3a2c3c738ecfa821714 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 9 Dec 2013 16:03:23 +0100 Subject: [PATCH 09/51] Fix to not destroy draggable when no draggable was set When a dir has no delete permission, the draggable isn't initialized on files. This fix makes sure we don't try to destroy a draggable when it wasn't inited in the first place. Fixes #6254 --- apps/files/js/filelist.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index c02ab70ce8d..30aea9c8c8d 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -300,7 +300,10 @@ var FileList={ }, remove:function(name){ var fileEl = FileList.findFileEl(name); - fileEl.find('td.filename').draggable('destroy'); + if (fileEl.data('permissions') & OC.PERMISSION_DELETE) { + // file is only draggable when delete permissions are set + fileEl.find('td.filename').draggable('destroy'); + } fileEl.remove(); FileList.updateFileSummary(); if ( ! $('tr[data-file]').exists() ) { From f41255f65217ab40cbe9c1af87be361736d6af55 Mon Sep 17 00:00:00 2001 From: tsumi Date: Wed, 15 Jan 2014 09:39:21 +0100 Subject: [PATCH 10/51] Useless else removed As suggested by @PVince81 : https://github.com/owncloud/core/pull/6721#issuecomment-32289922 --- core/js/js.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/js/js.js b/core/js/js.js index 92f2ac484e4..e84f482d672 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -418,8 +418,6 @@ var OC={ } if(!SVGSupport()) { replaceSVG(); - } else { - SVGSupport.checkMimeType(); } }).show(); }, 'html'); From d279ddd9a25286bed6817413cc69987d57695e3b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 15 Jan 2014 13:36:14 +0100 Subject: [PATCH 11/51] Show the name of the shared folder in the breadcrumb when viewing a publicly shared folder --- apps/files/templates/part.breadcrumb.php | 6 +++++- apps/files_sharing/public.php | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/files/templates/part.breadcrumb.php b/apps/files/templates/part.breadcrumb.php index 90d07d4336c..2a0df622767 100644 --- a/apps/files/templates/part.breadcrumb.php +++ b/apps/files/templates/part.breadcrumb.php @@ -1,6 +1,10 @@
" data-dir=''> - + + +
assign('sharingroot', $basePath); $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb); + $breadcrumbNav->assign('rootBreadCrumb', $rootName); $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path='); $maxUploadFilesize=OCP\Util::maxUploadFilesize($path); $fileHeader = (!isset($files) or count($files) > 0); From f11f65c6a5fa683e7b7d9476c7b2238ff2c1fc75 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 15 Jan 2014 14:27:23 +0100 Subject: [PATCH 12/51] copy files to owner trash recursively --- apps/files_trashbin/lib/trashbin.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 567f88b91b1..322a6aab9c8 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -189,7 +189,8 @@ class Trashbin { if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) { $size += self::calculateSize(new \OC\Files\View('/' . $owner . '/files_versions/' . $ownerPath)); if ($owner !== $user) { - $rootView->copy($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp); + //$rootView->copy($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp); + self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp); } else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) { @@ -247,7 +248,8 @@ class Trashbin { if ($rootView->is_dir($keyfile)) { $size += self::calculateSize(new \OC\Files\View($keyfile)); if ($owner !== $user) { - $rootView->copy($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp); + //$rootView->copy($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp); + self::copy_recursive($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($keyfile, $user . '/files_trashbin/keyfiles/' . $filename . '.d' . $timestamp); } else { @@ -265,7 +267,8 @@ class Trashbin { if ($rootView->is_dir($sharekeys)) { $size += self::calculateSize(new \OC\Files\View($sharekeys)); if ($owner !== $user) { - $rootView->copy($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp); + //$rootView->copy($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp); + self::copy_recursive($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($sharekeys, $user . '/files_trashbin/share-keys/' . $filename . '.d' . $timestamp); } else { From f4179a3f5aa14c047b466dd69d6e0844091e527e Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 15 Jan 2014 14:29:33 +0100 Subject: [PATCH 13/51] don't try to encrypt/decrypt cache chunks or files in the trash bin --- apps/files_encryption/lib/proxy.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 41f352d853a..4fe76b97711 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -255,8 +255,8 @@ class Proxy extends \OC_FileProxy { // split the path parts $pathParts = explode('/', $path); - // FIXME: handling for /userId/cache used by webdav for chunking. The cache chunks are NOT encrypted - if (isset($pathParts[2]) && $pathParts[2] === 'cache') { + // don't try to encrypt/decrypt cache chunks or files in the trash bin + if (isset($pathParts[2]) && ($pathParts[2] === 'cache' || $pathParts[2] === 'files_trashbin')) { return $result; } From 592ae166037a42a3a06d41d42369ad0910e93747 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 15 Jan 2014 14:35:17 +0100 Subject: [PATCH 14/51] remove old code --- apps/files_trashbin/lib/trashbin.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 322a6aab9c8..769fd8d8990 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -189,7 +189,6 @@ class Trashbin { if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) { $size += self::calculateSize(new \OC\Files\View('/' . $owner . '/files_versions/' . $ownerPath)); if ($owner !== $user) { - //$rootView->copy($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp); self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp); @@ -248,7 +247,6 @@ class Trashbin { if ($rootView->is_dir($keyfile)) { $size += self::calculateSize(new \OC\Files\View($keyfile)); if ($owner !== $user) { - //$rootView->copy($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp); self::copy_recursive($keyfile, $owner . '/files_trashbin/keyfiles/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($keyfile, $user . '/files_trashbin/keyfiles/' . $filename . '.d' . $timestamp); @@ -267,7 +265,6 @@ class Trashbin { if ($rootView->is_dir($sharekeys)) { $size += self::calculateSize(new \OC\Files\View($sharekeys)); if ($owner !== $user) { - //$rootView->copy($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp); self::copy_recursive($sharekeys, $owner . '/files_trashbin/share-keys/' . basename($ownerPath) . '.d' . $timestamp, $rootView); } $rootView->rename($sharekeys, $user . '/files_trashbin/share-keys/' . $filename . '.d' . $timestamp); From 7f68497b39db9528975862a091effe03fc802f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 15 Jan 2014 17:11:29 +0100 Subject: [PATCH 15/51] error handling in case a requested app doesn't exists --- lib/private/installer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/private/installer.php b/lib/private/installer.php index 8375b231e9b..835b6b4c01a 100644 --- a/lib/private/installer.php +++ b/lib/private/installer.php @@ -407,6 +407,9 @@ class OC_Installer{ include OC_App::getAppPath($app)."/appinfo/install.php"; } $info=OC_App::getAppInfo($app); + if (is_null($info)) { + return false; + } OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app)); //set remote/public handelers From 5730e05a145ac96f6e92e4e63129d018259007f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Wed, 15 Jan 2014 17:12:42 +0100 Subject: [PATCH 16/51] properly handle app activation for unit testing --- tests/enable_all.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/enable_all.php b/tests/enable_all.php index 4f2fe5cdb60..0267c4e2450 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -8,16 +8,16 @@ require_once __DIR__.'/../lib/base.php'; -OC_App::enable('files_sharing'); -OC_App::enable('files_encryption'); -OC_App::enable('user_ldap'); -OC_App::enable('calendar'); -OC_App::enable('contacts'); -OC_App::enable('apptemplateadvanced'); -OC_App::enable('appframework'); -#OC_App::enable('files_archive'); -#OC_App::enable('mozilla_sync'); -#OC_App::enable('news'); -#OC_App::enable('provisioning_api'); -#OC_App::enable('user_external'); +function enableApp($app) { + try { + OC_App::enable($app); + } catch (Exception $e) { + echo $e; + } +} + +enableApp('files_sharing'); +enableApp('files_encryption'); +enableApp('files_external'); +enableApp('user_ldap'); From 97b0840bbecf54bdd317dcbe9a8173d10fa8370e Mon Sep 17 00:00:00 2001 From: Volkan Gezer Date: Wed, 15 Jan 2014 18:36:33 +0100 Subject: [PATCH 17/51] Fix untranslated text when deleting user This should fix issue #6728 --- settings/js/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/js/users.js b/settings/js/users.js index 5ae157b07c6..6886db668b5 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -44,7 +44,7 @@ var UserList = { // Provide user with option to undo $('#notification').data('deleteuser', true); - OC.Notification.showHtml(t('users', 'deleted') + ' ' + escapeHTML(uid) + '' + t('users', 'undo') + ''); + OC.Notification.showHtml(t('settings', 'deleted') + ' ' + escapeHTML(uid) + '' + t('settings', 'undo') + ''); }, /** From 62040fe2d2cacafb3b534ff7de2cded7ca64daf4 Mon Sep 17 00:00:00 2001 From: Myles McNamara Date: Wed, 15 Jan 2014 17:06:48 -0500 Subject: [PATCH 18/51] change em to px --- apps/files_sharing/css/public.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css index be53a7d8a84..f4121430b9e 100644 --- a/apps/files_sharing/css/public.css +++ b/apps/files_sharing/css/public.css @@ -149,5 +149,5 @@ thead{ width: 300px; } .public_actions { - padding: 0.3em; + padding: 4px; } From 6b69c52037d84089e43e3e7cf9819867a9a05c22 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 17 Jan 2014 11:08:49 +0100 Subject: [PATCH 19/51] updated description of the files encryption app --- apps/files_encryption/appinfo/info.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml index 9d495916d26..ee05b651361 100644 --- a/apps/files_encryption/appinfo/info.xml +++ b/apps/files_encryption/appinfo/info.xml @@ -2,7 +2,7 @@ files_encryption Encryption - The new ownCloud 5 files encryption system. After the app was enabled you need to re-login to initialize your encryption keys. + The ownCloud files encryption system provides server side-encryption. After the app was enabled you need to re-login to initialize your encryption keys. AGPL Sam Tuke, Bjoern Schiessle, Florin Peter 4 From a78dc117327a3109805d2a4cbfe28b9a5ca49a81 Mon Sep 17 00:00:00 2001 From: Tigran Mkrtchyan Date: Thu, 16 Jan 2014 10:53:58 +0100 Subject: [PATCH 20/51] webdav: return SPACE_UNKNOWN if server do not support quota Signed-off-by: Tigran Mkrtchyan --- apps/files_external/lib/webdav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 0f8034e57d9..f6f4cb16e87 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -224,7 +224,7 @@ class DAV extends \OC\Files\Storage\Common{ if (isset($response['{DAV:}quota-available-bytes'])) { return (int)$response['{DAV:}quota-available-bytes']; } else { - return 0; + return \OC\Files\SPACE_UNKNOWN; } } catch(\Exception $e) { return \OC\Files\SPACE_UNKNOWN; From 817b49af581631ea641716291e2e5def44ec8c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 17 Jan 2014 12:07:27 +0100 Subject: [PATCH 21/51] don't enable files_external tests --- tests/enable_all.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/enable_all.php b/tests/enable_all.php index 0267c4e2450..d54418ff8e4 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -18,6 +18,6 @@ function enableApp($app) { enableApp('files_sharing'); enableApp('files_encryption'); -enableApp('files_external'); +//enableApp('files_external'); enableApp('user_ldap'); From 23e6578601a8aff24b57c1115e7db03a5f7c29dd Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 17 Jan 2014 12:29:21 +0100 Subject: [PATCH 22/51] Fix array access syntax for older PHP There was a syntax error when running tests in PHP 5.3.10. --- tests/lib/files/cache/cache.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 7d9329328a3..5d876932479 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -169,8 +169,9 @@ class Cache extends \PHPUnit_Framework_TestCase { $this->assertEquals(916, $this->cache->calculateFolderSize($file1)); // direct cache entry retrieval returns the original values - $this->assertEquals(1025, $this->cache->get($file1)['size']); - $this->assertEquals(916, $this->cache->get($file1)['unencrypted_size']); + $entry = $this->cache->get($file1); + $this->assertEquals(1025, $entry['size']); + $this->assertEquals(916, $entry['unencrypted_size']); $this->cache->remove($file2); $this->cache->remove($file3); From f4c198b907f3cbd59555a72693c48123736b7cbb Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 17 Jan 2014 14:21:15 +0100 Subject: [PATCH 23/51] Fixed isPreviewAvailable warnings in log isPreviewAvailable wasn't always set as the files formatting code is slightly different than the one from the files app. Fixes #6423 --- apps/files/templates/part.list.php | 2 +- apps/files_sharing/public.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 2f630e1f014..f4fb96a7a7c 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -18,7 +18,7 @@ $totalsize = 0; ?> data-size="" data-etag="" data-permissions=""> - + getPreviewManager()->isMimeSupported($i['mimetype']); } + $i['isPreviewAvailable'] = \OC::$server->getPreviewManager()->isMimeSupported($i['mimetype']); $i['directory'] = $getPath; $i['permissions'] = OCP\PERMISSION_READ; $i['icon'] = determineIcon($i, $basePath, $token); From 6b4c3df0876a4786bbde406349746600c87e1e6b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 17 Jan 2014 14:40:48 +0100 Subject: [PATCH 24/51] Load a separate config (if present) when running unit tests --- lib/base.php | 14 ++++++++++++-- lib/private/config.php | 2 +- lib/private/legacy/config.php | 1 - lib/private/util.php | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/base.php b/lib/base.php index f30575c7b12..d320f6f2411 100644 --- a/lib/base.php +++ b/lib/base.php @@ -57,6 +57,9 @@ class OC { * web path in 'url' */ public static $APPSROOTS = array(); + + public static $configDir; + /* * requested app */ @@ -100,6 +103,13 @@ class OC { get_include_path() ); + if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/test_config/')) { + self::$configDir = OC::$SERVERROOT . '/test_config/'; + } else { + self::$configDir = OC::$SERVERROOT . '/config/'; + } + OC_Config::$object = new \OC\Config(self::$configDir); + OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT))); $scriptName = OC_Request::scriptName(); if (substr($scriptName, -1) == '/') { @@ -175,8 +185,8 @@ class OC { } public static function checkConfig() { - if (file_exists(OC::$SERVERROOT . "/config/config.php") - and !is_writable(OC::$SERVERROOT . "/config/config.php") + if (file_exists(self::$configDir . "/config.php") + and !is_writable(self::$configDir . "/config.php") ) { $defaults = new OC_Defaults(); if (self::$CLI) { diff --git a/lib/private/config.php b/lib/private/config.php index caf7b1d7066..8a9d5ca6158 100644 --- a/lib/private/config.php +++ b/lib/private/config.php @@ -50,7 +50,7 @@ class Config { protected $debugMode; /** - * @param $configDir path to the config dir, needs to end with '/' + * @param string $configDir path to the config dir, needs to end with '/' */ public function __construct($configDir) { $this->configDir = $configDir; diff --git a/lib/private/legacy/config.php b/lib/private/legacy/config.php index c457979113e..ab67c8d3020 100644 --- a/lib/private/legacy/config.php +++ b/lib/private/legacy/config.php @@ -38,7 +38,6 @@ * This class is responsible for reading and writing config.php, the very basic * configuration file of ownCloud. */ -OC_Config::$object = new \OC\Config(OC::$SERVERROOT.'/config/'); class OC_Config { /** diff --git a/lib/private/util.php b/lib/private/util.php index a4b3761dbd3..be8b5439543 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -312,7 +312,7 @@ class OC_Util { .'" target="_blank">giving the webserver write access to the root directory.'; // Check if config folder is writable. - if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) { + if(!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) { $errors[] = array( 'error' => "Can't write into config directory", 'hint' => 'This can usually be fixed by ' From 1df6bf997a5f4bb44902d237d07bd06eccf6a9fc Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 17 Jan 2014 14:05:33 +0100 Subject: [PATCH 25/51] add link to documentation --- apps/files_encryption/appinfo/info.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml index ee05b651361..b6d9d6bb0a3 100644 --- a/apps/files_encryption/appinfo/info.xml +++ b/apps/files_encryption/appinfo/info.xml @@ -7,6 +7,10 @@ Sam Tuke, Bjoern Schiessle, Florin Peter 4 true + + http://doc.owncloud.org/server/6.0/user_manual/files/encryption.html + http://doc.owncloud.org/server/6.0/admin_manual/configuration/configuration_encryption.html + false From bf0471a92ed4fca8fe3344839acd83d6918cf566 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 17 Jan 2014 14:05:39 +0100 Subject: [PATCH 26/51] show link to app documentation --- lib/private/app.php | 4 ++++ settings/css/settings.css | 6 ++++++ settings/js/apps.js | 20 +++++++++++++++++++- settings/templates/apps.php | 5 +++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/private/app.php b/lib/private/app.php index 34c00e97fb9..0c60557914a 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -555,6 +555,10 @@ class OC_App{ }elseif($child->getName()=='description') { $xml=(string)$child->asXML(); $data[$child->getName()]=substr($xml, 13, -14);//script tags + }elseif($child->getName()=='documentation') { + foreach($child as $subchild) { + $data["documentation"][$subchild->getName()] = (string)$subchild; + } }else{ $data[$child->getName()]=(string)$child; } diff --git a/settings/css/settings.css b/settings/css/settings.css index a93c675d466..8a96885b789 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -131,6 +131,12 @@ span.version { margin-left:1em; margin-right:1em; color:#555; } .appslink { text-decoration: underline; } .score { color:#666; font-weight:bold; font-size:0.8em; } +.appinfo .documentation { + margin-top: 1em; + margin-bottom: 1em; +} + + /* LOG */ #log { white-space:normal; } #lessLog { display:none; } diff --git a/settings/js/apps.js b/settings/js/apps.js index a55c55e24cf..1d05d01e1f2 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -37,6 +37,24 @@ OC.Settings.Apps = OC.Settings.Apps || { } page.find('span.licence').text(appLicense); + var userDocumentation = false; + var adminDocumentation = false; + if (typeof(app.documentation.user) !== 'undefined') { + userDocumentation = true; + page.find('span.userDocumentation').html("" + t('settings', 'User Documentation') + ""); + page.find('p.documentation').show(); + } + if (typeof(app.documentation.admin) !== 'undefined') { + adminDocumentation = true; + page.find('span.adminDocumentation').html("" + t('settings', 'Admin Documentation') + ""); + page.find('p.documentation').show(); + } + + if(userDocumentation && adminDocumentation) { + page.find('span.userDocumentation').after(', '); + } + + if (app.update !== false) { page.find('input.update').show(); page.find('input.update').data('appid', app.id); @@ -110,7 +128,7 @@ OC.Settings.Apps = OC.Settings.Apps || { element.val(t('settings','Disable')); } },'json') - .fail(function() { + .fail(function() { OC.Settings.Apps.showErrorMessage(t('settings', 'Error while enabling app')); appitem.data('errormsg', t('settings', 'Error while enabling app')); appitem.data('active',false); diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 0b76f775fea..ce48ef77d12 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -34,6 +34,11 @@ class="version">

+ From e2de3b833765caa021de93713eba134e9e6edc7f Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Fri, 17 Jan 2014 16:07:58 +0100 Subject: [PATCH 27/51] distinguish app links from doc links --- settings/css/settings.css | 1 + settings/js/apps.js | 2 +- settings/templates/apps.php | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/settings/css/settings.css b/settings/css/settings.css index 8a96885b789..3f5d59e56e2 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -129,6 +129,7 @@ span.version { margin-left:1em; margin-right:1em; color:#555; } .app:hover, .app:active { max-width: inherit; } .appslink { text-decoration: underline; } +.doclink { text-decoration: underline; } .score { color:#666; font-weight:bold; font-size:0.8em; } .appinfo .documentation { diff --git a/settings/js/apps.js b/settings/js/apps.js index 1d05d01e1f2..ce81dff4485 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -70,7 +70,7 @@ OC.Settings.Apps = OC.Settings.Apps || { if (app.internal === false) { page.find('span.score').show(); page.find('p.appslink').show(); - page.find('a').attr('href', 'http://apps.owncloud.com/content/show.php?content=' + app.id); + page.find('a.appslink').attr('href', 'http://apps.owncloud.com/content/show.php?content=' + app.id); page.find('small.externalapp').hide(); } else { page.find('p.appslink').hide(); diff --git a/settings/templates/apps.php b/settings/templates/apps.php index ce48ef77d12..be1cf0387b8 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -36,8 +36,8 @@

- + From 90a41ef26abaacddd58c1e2e4c687935214e4f1a Mon Sep 17 00:00:00 2001 From: rnveach Date: Fri, 17 Jan 2014 11:46:44 -0500 Subject: [PATCH 29/51] fixed selector string and removed all checkbox if it was selected --- apps/files/js/files.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files/js/files.js b/apps/files/js/files.js index fdaa3aa3342..999d3eee0c8 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -610,11 +610,12 @@ function procesSelection() { return el.type==='dir'; }); if (selectedFiles.length === 0 && selectedFolders.length === 0) { - $('#headerName>span.name').text(t('files','Name')); + $('#headerName span.name').text(t('files','Name')); $('#headerSize').text(t('files','Size')); $('#modified').text(t('files','Modified')); $('table').removeClass('multiselect'); $('.selectedActions').hide(); + $('#select_all').removeAttr('checked'); } else { $('.selectedActions').show(); From a41440436cfb051d8075f72eb45d470feb1d15d7 Mon Sep 17 00:00:00 2001 From: rnveach Date: Fri, 17 Jan 2014 11:49:00 -0500 Subject: [PATCH 30/51] added trigger to redo selection text on a directory change --- apps/files/js/filelist.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 473bcf25f2d..3857ba10fa0 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -20,6 +20,8 @@ var FileList={ Files.setupDragAndDrop(); } FileList.updateFileSummary(); + procesSelection(); + $fileList.trigger(jQuery.Event("updated")); }, createRow:function(type, name, iconurl, linktarget, size, lastModified, permissions) { From 1af7dab5358d7fd495e4382037c6e2528e2b76d5 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Sun, 19 Jan 2014 18:49:51 +0100 Subject: [PATCH 31/51] Fixed quota wrapper to not wrap failed fopen streams When calling fopen() on some storage types, these return false instead of throwing an exception. This fix makes sure that in case the stream wasn't opened (for example when a file doesn't exist any more) the stream isn't wrapped. Also added 'rb' as another case that doesn't need to be wrapped. Fixes #6832 --- lib/private/files/storage/wrapper/quota.php | 2 +- tests/lib/files/storage/wrapper/quota.php | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php index 43016e0892f..a430e3e4617 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 && $mode !== 'r') { + if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') { 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 9b14335782f..87bafb64d41 100644 --- a/tests/lib/files/storage/wrapper/quota.php +++ b/tests/lib/files/storage/wrapper/quota.php @@ -59,6 +59,20 @@ class Quota extends \Test\Files\Storage\Storage { $this->assertEquals('foobarqwe', $instance->file_get_contents('foo')); } + public function testReturnFalseWhenFopenFailed(){ + $failStorage = $this->getMock( + '\OC\Files\Storage\Local', + array('fopen'), + array(array('datadir' => $this->tmpDir))); + $failStorage->expects($this->any()) + ->method('fopen') + ->will($this->returnValue(false)); + + $instance = new \OC\Files\Storage\Wrapper\Quota(array('storage' => $failStorage, 'quota' => 1000)); + + $this->assertFalse($instance->fopen('failedfopen', 'r')); + } + public function testReturnRegularStreamOnRead(){ $instance = $this->getLimitedStorage(9); @@ -71,6 +85,11 @@ class Quota extends \Test\Files\Storage\Storage { $meta = stream_get_meta_data($stream); $this->assertEquals('plainfile', $meta['wrapper_type']); fclose($stream); + + $stream = $instance->fopen('foo', 'rb'); + $meta = stream_get_meta_data($stream); + $this->assertEquals('plainfile', $meta['wrapper_type']); + fclose($stream); } public function testReturnQuotaStreamOnWrite(){ From 8e64909e996f2da53274bedfaf9b6c66f54af31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 20 Jan 2014 09:25:30 +0100 Subject: [PATCH 32/51] Updating 3rdparty once more .... --- 3rdparty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty b/3rdparty index faeedfcc057..7c2c94c904c 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit faeedfcc0573868a2f0bde81f25a67a940c100ab +Subproject commit 7c2c94c904c2721763e97d5bafd115f863080a60 From 221e656e91de48f74e170662cb9680e5e2aac792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 20 Jan 2014 10:10:34 +0100 Subject: [PATCH 33/51] Revert "use getAppWebPath() in here as well" This reverts commit 6254f0a403e315461f8e20ebccf71cb91e9313a3. --- lib/private/template/cssresourcelocator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/template/cssresourcelocator.php b/lib/private/template/cssresourcelocator.php index e26daa25827..8e7831ca549 100644 --- a/lib/private/template/cssresourcelocator.php +++ b/lib/private/template/cssresourcelocator.php @@ -22,7 +22,7 @@ class CSSResourceLocator extends ResourceLocator { $app = substr($style, 0, strpos($style, '/')); $style = substr($style, strpos($style, '/')+1); $app_path = \OC_App::getAppPath($app); - $app_url = \OC_App::getAppWebPath($app); + $app_url = $this->webroot . '/index.php/apps/' . $app; if ($this->appendIfExist($app_path, $style.$this->form_factor.'.css', $app_url) || $this->appendIfExist($app_path, $style.'.css', $app_url) ) { From 99e068761af6d31cf707488ee8db3620b6892e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 20 Jan 2014 10:17:31 +0100 Subject: [PATCH 34/51] adding a comment to the database schema --- tests/data/db_structure.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/data/db_structure.xml b/tests/data/db_structure.xml index bfff2143349..d98066c4b7e 100644 --- a/tests/data/db_structure.xml +++ b/tests/data/db_structure.xml @@ -21,6 +21,7 @@ 1 true 4 + This is the id From 164915a3f8c420b4274ebf3841044f18ca7435a4 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 20 Jan 2014 13:41:52 +0100 Subject: [PATCH 35/51] Move test config folder to tests/config --- lib/base.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/base.php b/lib/base.php index d320f6f2411..0597183adcf 100644 --- a/lib/base.php +++ b/lib/base.php @@ -103,8 +103,8 @@ class OC { get_include_path() ); - if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/test_config/')) { - self::$configDir = OC::$SERVERROOT . '/test_config/'; + if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) { + self::$configDir = OC::$SERVERROOT . '/tests/config/'; } else { self::$configDir = OC::$SERVERROOT . '/config/'; } From 3d6d8d1bb683f9daca3a2b8a876e291adc320375 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 20 Jan 2014 15:21:21 +0100 Subject: [PATCH 36/51] Reuse the data retrieved from the cache in checkUpdate --- apps/files_sharing/lib/watcher.php | 2 +- lib/private/files/cache/watcher.php | 4 ++-- lib/private/files/view.php | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php index c40cf6911b8..285b1a58c6e 100644 --- a/apps/files_sharing/lib/watcher.php +++ b/apps/files_sharing/lib/watcher.php @@ -32,7 +32,7 @@ class Shared_Watcher extends Watcher { * @param string $path */ public function checkUpdate($path) { - if ($path != '' && parent::checkUpdate($path)) { + if ($path != '' && parent::checkUpdate($path) === true) { // since checkUpdate() has already updated the size of the subdirs, // only apply the update to the owner's parent dirs diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php index 58f624c8990..251ecbe7071 100644 --- a/lib/private/files/cache/watcher.php +++ b/lib/private/files/cache/watcher.php @@ -40,7 +40,7 @@ class Watcher { * check $path for updates * * @param string $path - * @return boolean true if path was updated, false otherwise + * @return boolean | array true if path was updated, otherwise the cached data is returned */ public function checkUpdate($path) { $cachedEntry = $this->cache->get($path); @@ -56,7 +56,7 @@ class Watcher { $this->cache->correctFolderSize($path); return true; } - return false; + return $cachedEntry; } /** diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 8893911ed5d..d97544b865e 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -801,6 +801,7 @@ class View { * @var string $internalPath */ list($storage, $internalPath) = Filesystem::resolvePath($path); + $data = null; if ($storage) { $cache = $storage->getCache($internalPath); $permissionsCache = $storage->getPermissionsCache($internalPath); @@ -811,10 +812,12 @@ class View { $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { $watcher = $storage->getWatcher($internalPath); - $watcher->checkUpdate($internalPath); + $data = $watcher->checkUpdate($internalPath); } - $data = $cache->get($internalPath); + if (!is_array($data)) { + $data = $cache->get($internalPath); + } if ($data and $data['fileid']) { if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') { From ca57a849ffc73aa4c8feba972b3e36138fecb089 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 20 Jan 2014 17:10:09 +0100 Subject: [PATCH 37/51] When reading the size of "files" mountpoints need to be excluded The versions and trashbin app are now passing "includeMountPoints=false" to "getFileInfo()" to make sure that the calculated total size doesn't include mount points like Shared or external storage. This is because the default call (legacy) used to return the size of mount points as well. Fixes #6731 --- apps/files_trashbin/lib/trashbin.php | 2 +- apps/files_versions/lib/versions.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 769fd8d8990..7544980e071 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -734,7 +734,7 @@ class Trashbin { // calculate available space for trash bin // subtract size of files and current trash bin size from quota if ($softQuota) { - $rootInfo = $view->getFileInfo('/files/'); + $rootInfo = $view->getFileInfo('/files/', false); $free = $quota - $rootInfo['size']; // remaining free space for user if ($free > 0) { $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 7e6cc818efb..f268fa10b66 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -445,7 +445,7 @@ class Storage { // subtract size of files and current versions size from quota if ($softQuota) { $files_view = new \OC\Files\View('/'.$uid.'/files'); - $rootInfo = $files_view->getFileInfo('/'); + $rootInfo = $files_view->getFileInfo('/', false); $free = $quota-$rootInfo['size']; // remaining free space for user if ( $free > 0 ) { $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - ($versionsSize + $offset); // how much space can be used for versions From 955530556550d2e753675142486ee91d5a9ce6fa Mon Sep 17 00:00:00 2001 From: Myles McNamara Date: Mon, 20 Jan 2014 11:58:01 -0500 Subject: [PATCH 38/51] change publicUploadButtonMock to public_upload Changed jQuery selector for public preview to public_upload to correctly show preview --- apps/files/js/files.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/js/files.js b/apps/files/js/files.js index fdaa3aa3342..12e870f141b 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -717,7 +717,7 @@ Files.lazyLoadPreview = function(path, mime, ready, width, height, etag) { console.warn('Files.lazyLoadPreview(): missing etag argument'); } - if ( $('#publicUploadButtonMock').length ) { + if ( $('#public_upload').length ) { urlSpec.t = $('#dirToken').val(); previewURL = OC.Router.generate('core_ajax_public_preview', urlSpec); } else { From 9fd4cb1b6683cdebdeaec0f744bd2ba1fb1c64e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 21 Jan 2014 10:42:47 +0100 Subject: [PATCH 39/51] adding password protection check to getShareByToken() --- apps/files_sharing/public.php | 2 +- lib/public/share.php | 36 +++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index d050efd5b32..100379047d3 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -35,7 +35,7 @@ function determineIcon($file, $sharingRoot, $sharingToken) { if (isset($_GET['t'])) { $token = $_GET['t']; - $linkItem = OCP\Share::getShareByToken($token); + $linkItem = OCP\Share::getShareByToken($token, false); if (is_array($linkItem) && isset($linkItem['uid_owner'])) { // seems to be a valid share $type = $linkItem['item_type']; diff --git a/lib/public/share.php b/lib/public/share.php index eb1dd8d1c95..4573fe8d8d3 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -347,11 +347,11 @@ class Share { } /** - * Get the item shared by a token - * @param string token - * @return Item + * Based on the given token the share information will be returned - password protected shares will be verified + * @param string $token + * @return array | bool false will be returned in case the token is unknown or unauthorized */ - public static function getShareByToken($token) { + public static function getShareByToken($token, $checkPasswordProtection = true) { $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1); $result = $query->execute(array($token)); if (\OC_DB::isError($result)) { @@ -361,6 +361,12 @@ class Share { if (is_array($row) and self::expireItem($row)) { return false; } + + // password protected shares need to me authenticated + if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) { + return false; + } + return $row; } @@ -1888,6 +1894,28 @@ class Share { } } + /** + * In case a password protected link is not yet authenticated this function will return false + * + * @param array $linkItem + * @return bool + */ + public static function checkPasswordProtectedShare(array $linkItem) { + if (!isset($linkItem['share_with'])) { + return true; + } + + if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) { + return true; + } + + if ( \OC::$session->exists('public_link_authenticated') + && \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) { + return true; + } + + return false; + } } /** From 6746ad0a7315d1ee06f7b1804b7c9457755f6648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 21 Jan 2014 10:55:10 +0100 Subject: [PATCH 40/51] in case no share is found for the given token we can return right away --- lib/public/share.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/public/share.php b/lib/public/share.php index 4573fe8d8d3..ddc9e1e066f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -358,6 +358,9 @@ class Share { \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR); } $row = $result->fetchRow(); + if ($row === false) { + return false; + } if (is_array($row) and self::expireItem($row)) { return false; } From 23a4d0d44ef8b918f054e7ad608d04b2e9a68995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 21 Jan 2014 11:32:30 +0100 Subject: [PATCH 41/51] OC_Util::setupFS($user) will create a data dir for the given string - no matter if the user really exists - OCP\JSON::checkUserExists($owner); introduces a ready to use check which will bail out with an JSON error --- apps/files/ajax/upload.php | 1 + apps/files/triggerupdate.php | 1 + apps/files_sharing/ajax/publicpreview.php | 3 ++- apps/files_sharing/appinfo/update.php | 1 + apps/files_sharing/public.php | 6 +++--- lib/private/json.php | 14 ++++++++++++++ lib/private/util.php | 4 ++++ lib/public/json.php | 10 +++++++++- 8 files changed, 35 insertions(+), 5 deletions(-) diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 0e905f993ac..bdaf6a77d14 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -34,6 +34,7 @@ if (empty($_POST['dirToken'])) { // resolve reshares $rootLinkItem = OCP\Share::resolveReShare($linkItem); + OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); // Setup FS with owner OC_Util::tearDownFS(); OC_Util::setupFS($rootLinkItem['uid_owner']); diff --git a/apps/files/triggerupdate.php b/apps/files/triggerupdate.php index 0e29edbba35..a37b9823add 100644 --- a/apps/files/triggerupdate.php +++ b/apps/files/triggerupdate.php @@ -6,6 +6,7 @@ if (OC::$CLI) { if (count($argv) === 2) { $file = $argv[1]; list(, $user) = explode('/', $file); + OCP\JSON::checkUserExists($owner); OC_Util::setupFS($user); $view = new \OC\Files\View(''); /** diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php index 54a9806e8bf..a52f522afac 100644 --- a/apps/files_sharing/ajax/publicpreview.php +++ b/apps/files_sharing/ajax/publicpreview.php @@ -39,6 +39,7 @@ if(!isset($linkedItem['uid_owner']) || !isset($linkedItem['file_source'])) { $rootLinkItem = OCP\Share::resolveReShare($linkedItem); $userId = $rootLinkItem['uid_owner']; +OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); \OC_Util::setupFS($userId); \OC\Files\Filesystem::initMountPoints($userId); $view = new \OC\Files\View('/' . $userId . '/files'); @@ -88,4 +89,4 @@ try{ } catch (\Exception $e) { \OC_Response::setStatus(500); \OC_Log::write('core', $e->getmessage(), \OC_Log::DEBUG); -} \ No newline at end of file +} diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 0d827da28ea..4b716e764f4 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -44,6 +44,7 @@ if (version_compare($installedVersion, '0.3', '<')) { $shareType = OCP\Share::SHARE_TYPE_USER; $shareWith = $row['uid_shared_with']; } + OCP\JSON::checkUserExists($row['uid_owner']); OC_User::setUserId($row['uid_owner']); //we need to setup the filesystem for the user, otherwise OC_FileSystem::getRoot will fail and break OC_Util::setupFS($row['uid_owner']); diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index d050efd5b32..80dd708ee51 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -43,10 +43,10 @@ if (isset($_GET['t'])) { $shareOwner = $linkItem['uid_owner']; $path = null; $rootLinkItem = OCP\Share::resolveReShare($linkItem); - $fileOwner = $rootLinkItem['uid_owner']; - if (isset($fileOwner)) { + if (isset($rootLinkItem['uid_owner'])) { + OCP\JSON::checkUserExists($rootLinkItem['uid_owner']); OC_Util::tearDownFS(); - OC_Util::setupFS($fileOwner); + OC_Util::setupFS($rootLinkItem['uid_owner']); $path = \OC\Files\Filesystem::getPath($linkItem['file_source']); } } diff --git a/lib/private/json.php b/lib/private/json.php index 6a9e5a2df5e..5c5d7e3a3da 100644 --- a/lib/private/json.php +++ b/lib/private/json.php @@ -64,6 +64,20 @@ class OC_JSON{ } } + /** + * Check is a given user exists - send json error msg if not + * @param string $user + */ + public static function checkUserExists($user) { + if (!OCP\User::userExists($user)) { + $l = OC_L10N::get('lib'); + OCP\JSON::error(array('data' => array('message' => $l->t('Unknown user')))); + exit; + } + } + + + /** * Check if the user is a subadmin, send json error msg if not */ diff --git a/lib/private/util.php b/lib/private/util.php index 72afa6f9478..8aa7a074d0d 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -51,6 +51,10 @@ class OC_Util { self::$rootMounted = true; } + if ($user != '' && !OCP\User::userExists($user)) { + return false; + } + //if we aren't logged in, there is no use to set up the filesystem if( $user != "" ) { \OC\Files\Filesystem::addStorageWrapper(function($mountPoint, $storage){ diff --git a/lib/public/json.php b/lib/public/json.php index 831e3ef1cf6..cd5d233ef90 100644 --- a/lib/public/json.php +++ b/lib/public/json.php @@ -167,7 +167,7 @@ class JSON { * @return string json formatted string if not admin user. */ public static function checkAdminUser() { - return(\OC_JSON::checkAdminUser()); + \OC_JSON::checkAdminUser(); } /** @@ -177,4 +177,12 @@ class JSON { public static function encode($data) { return(\OC_JSON::encode($data)); } + + /** + * Check is a given user exists - send json error msg if not + * @param string $user + */ + public static function checkUserExists($user) { + \OC_JSON::checkUserExists($user); + } } From 21832bc89092e150edce8247abd06c91655b034d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Tue, 21 Jan 2014 11:56:34 +0100 Subject: [PATCH 42/51] user workarount to compare CLOB column with CHAR value --- apps/user_ldap/lib/helper.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 09f646921e3..9727d847d27 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -48,18 +48,25 @@ class Helper { static public function getServerConfigurationPrefixes($activeConfigurations = false) { $referenceConfigkey = 'ldap_configuration_active'; - $query = ' + $sql = ' SELECT DISTINCT `configkey` FROM `*PREFIX*appconfig` WHERE `appid` = \'user_ldap\' AND `configkey` LIKE ? '; - if($activeConfigurations) { - $query .= ' AND `configvalue` = \'1\''; - } - $query = \OCP\DB::prepare($query); - $serverConfigs = $query->execute(array('%'.$referenceConfigkey))->fetchAll(); + if($activeConfigurations) { + if (\OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { + //FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison + $sql .= ' AND to_char(`configvalue`)=\'1\''; + } else { + $sql .= ' AND `configvalue` = \'1\''; + } + } + + $stmt = \OCP\DB::prepare($sql); + + $serverConfigs = $stmt->execute(array('%'.$referenceConfigkey))->fetchAll(); $prefixes = array(); foreach($serverConfigs as $serverConfig) { From a3ea5aa2ac85fea812e25e2578db4cf86a0d3418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 21 Jan 2014 12:07:08 +0100 Subject: [PATCH 43/51] fixing comment + adding unit test for checkPasswordProtectedShare --- lib/public/share.php | 8 +++++++- tests/lib/share/share.php | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/public/share.php b/lib/public/share.php index ddc9e1e066f..f832d04a70f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -365,7 +365,7 @@ class Share { return false; } - // password protected shares need to me authenticated + // password protected shares need to be authenticated if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) { return false; } @@ -1907,6 +1907,12 @@ class Share { if (!isset($linkItem['share_with'])) { return true; } + if (!isset($linkItem['share_type'])) { + return true; + } + if (!isset($linkItem['id'])) { + return true; + } if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) { return true; diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index 2fe2837019f..d6acee6c924 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -25,6 +25,8 @@ class Test_Share extends PHPUnit_Framework_TestCase { protected $userBackend; protected $user1; protected $user2; + protected $user3; + protected $user4; protected $groupBackend; protected $group1; protected $group2; @@ -656,4 +658,44 @@ class Test_Share extends PHPUnit_Framework_TestCase { 'Failed asserting that the share of the test.txt file by user 2 has been removed.' ); } + + /** + * @dataProvider checkPasswordProtectedShareDataProvider + * @param $expected + * @param $item + */ + public function testCheckPasswordProtectedShare($expected, $item) { + \OC::$session->set('public_link_authenticated', 100); + $result = \OCP\Share::checkPasswordProtectedShare($item); + $this->assertEquals($expected, $result); + } + + function checkPasswordProtectedShareDataProvider() { + return array( + array(true, array()), + array(true, array('share_with' => null)), + array(true, array('share_with' => '')), + array(true, array('share_with' => '1234567890', 'share_type' => '1')), + array(true, array('share_with' => '1234567890', 'share_type' => 1)), + array(true, array('share_with' => '1234567890', 'share_type' => '3', 'id' => 100)), + array(true, array('share_with' => '1234567890', 'share_type' => 3, 'id' => 100)), + array(false, array('share_with' => '1234567890', 'share_type' => '3', 'id' => 101)), + array(false, array('share_with' => '1234567890', 'share_type' => 3, 'id' => 101)), + ); + + /* + if (!isset($linkItem['share_with'])) { + return true; + } + + if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) { + return true; + } + + if ( \OC::$session->exists('public_link_authenticated') + && \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) { + return true; + } + * */ + } } From 267e1f3c40b9b9bdabaf0e49221744f80f7bc5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Tue, 21 Jan 2014 12:41:10 +0100 Subject: [PATCH 44/51] use 'download.zip' as default name for zip downloads instead of 'owncloud.zip' --- lib/private/files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/files.php b/lib/private/files.php index e6c81d58bd2..8ce632013cf 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -83,7 +83,7 @@ class OC_Files { if ($basename) { $name = $basename . '.zip'; } else { - $name = 'owncloud.zip'; + $name = 'download.zip'; } set_time_limit($executionTime); From 37e278f2a90bd460668e840775dd741b85eca022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Tue, 21 Jan 2014 13:50:56 +0100 Subject: [PATCH 45/51] don't use the user id within the versions preview call as it could be used to access previews of another user --- apps/files_versions/ajax/getVersions.php | 2 +- apps/files_versions/ajax/preview.php | 10 ++-------- apps/files_versions/lib/versions.php | 17 +++++++++++------ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/apps/files_versions/ajax/getVersions.php b/apps/files_versions/ajax/getVersions.php index 4f48f71d8ca..df29f401629 100644 --- a/apps/files_versions/ajax/getVersions.php +++ b/apps/files_versions/ajax/getVersions.php @@ -5,7 +5,7 @@ $source = $_GET['source']; $start = $_GET['start']; list ($uid, $filename) = OCA\Files_Versions\Storage::getUidAndFilename($source); $count = 5; //show the newest revisions -if( ($versions = OCA\Files_Versions\Storage::getVersions($uid, $filename)) ) { +if( ($versions = OCA\Files_Versions\Storage::getVersions($uid, $filename, $source)) ) { $endReached = false; if (count($versions) <= $start+$count) { diff --git a/apps/files_versions/ajax/preview.php b/apps/files_versions/ajax/preview.php index 31525028ef3..bd9b7366ab0 100644 --- a/apps/files_versions/ajax/preview.php +++ b/apps/files_versions/ajax/preview.php @@ -12,18 +12,11 @@ if(!\OC_App::isEnabled('files_versions')){ } $file = array_key_exists('file', $_GET) ? (string) urldecode($_GET['file']) : ''; -$user = array_key_exists('user', $_GET) ? $_GET['user'] : ''; $maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : 44; $maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : 44; $version = array_key_exists('version', $_GET) ? $_GET['version'] : ''; $scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true; -if($user === '') { - \OC_Response::setStatus(400); //400 Bad Request - \OC_Log::write('versions-preview', 'No user parameter was passed', \OC_Log::DEBUG); - exit; -} - if($file === '' && $version === '') { \OC_Response::setStatus(400); //400 Bad Request \OC_Log::write('versions-preview', 'No file parameter was passed', \OC_Log::DEBUG); @@ -36,7 +29,8 @@ if($maxX === 0 || $maxY === 0) { exit; } -try{ +try { + list($user, $file) = \OCA\Files_Versions\Storage::getUidAndFilename($file); $preview = new \OC\Preview($user, 'files_versions', $file.'.v'.$version); $mimetype = \OC_Helper::getFileNameMimeType($file); $preview->setMimetype($mimetype); diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index f268fa10b66..01c2e1ccdee 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -261,11 +261,12 @@ class Storage { /** * @brief get a list of all available versions of a file in descending chronological order - * @param $uid user id from the owner of the file - * @param $filename file to find versions of, relative to the user files dir + * @param string $uid user id from the owner of the file + * @param string $filename file to find versions of, relative to the user files dir + * @param string $userFullPath * @returns array */ - public static function getVersions($uid, $filename) { + public static function getVersions($uid, $filename, $userFullPath = '') { $versions = array(); // fetch for old versions $view = new \OC\Files\View('/' . $uid . '/' . self::VERSIONS_ROOT); @@ -286,7 +287,11 @@ class Storage { $versions[$key]['cur'] = 0; $versions[$key]['version'] = $version; $versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($version); - $versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $filename, 'version' => $version, 'user' => $uid)); + if (empty($userFullPath)) { + $versions[$key]['preview'] = ''; + } else { + $versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $userFullPath, 'version' => $version)); + } $versions[$key]['path'] = $filename; $versions[$key]['name'] = $versionedFile; $versions[$key]['size'] = $file['size']; @@ -508,8 +513,8 @@ class Storage { * @brief delete old version from a given list of versions * * @param array $versionsByFile list of versions ordered by files - * @param array $allVversions all versions accross multiple files - * @param $versionsFileview OC\Files\View on data/user/files_versions + * @param array $allVversions all versions across multiple files + * @param $versionsFileview \OC\Files\View on data/user/files_versions * @return size of releted versions */ private static function delOldVersions($versionsByFile, &$allVersions, $versionsFileview) { From 9efd07fbabf409900982abbd48edd85de7f3b4e7 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 20 Jan 2014 16:03:26 +0100 Subject: [PATCH 46/51] isolate getExpireList function to make it testable --- apps/files_versions/lib/versions.php | 153 +++++++++++++-------------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 01c2e1ccdee..8463bd9482c 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -417,6 +417,65 @@ class Storage { return $result; } + /** + * @brief get list of files we want to expire + * @param int $currentTime timestamp of current time + * @param array $versions list of versions + * @return array containing the list of to deleted versions and the size of them + */ + protected static function getExpireList($time, $versions) { + + $size = 0; + $toDelete = array(); // versions we want to delete + + $versions = array_reverse($versions); // newest version first + + $interval = 1; + $step = Storage::$max_versions_per_interval[$interval]['step']; + if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) { + $nextInterval = -1; + } else { + $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter']; + } + + $firstVersion = reset($versions); + $firstKey = key($versions); + $prevTimestamp = $firstVersion['version']; + $nextVersion = $firstVersion['version'] - $step; + unset($versions[$firstKey]); + + foreach ($versions as $key => $version) { + $newInterval = true; + while ($newInterval) { + if ($nextInterval == -1 || $prevTimestamp > $nextInterval) { + if ($version['version'] > $nextVersion) { + //distance between two version too small, mark to delete + $toDelete[$key] = $version['path'] . '.v' . $version['version']; + $size += $version['size']; + \OCP\Util::writeLog('files_versions', 'Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, \OCP\Util::DEBUG); + } else { + $nextVersion = $version['version'] - $step; + $prevTimestamp = $version['version']; + } + $newInterval = false; // version checked so we can move to the next one + } else { // time to move on to the next interval + $interval++; + $step = Storage::$max_versions_per_interval[$interval]['step']; + $nextVersion = $prevTimestamp - $step; + if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) { + $nextInterval = -1; + } else { + $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter']; + } + $newInterval = true; // we changed the interval -> check same version with new interval + } + } + } + + return array($toDelete, $size); + + } + /** * @brief Erase a file's versions which exceed the set quota */ @@ -461,33 +520,35 @@ class Storage { $availableSpace = $quota - $offset; } - - // with the probability of 0.1% we reduce the number of all versions not only for the current file - $random = rand(0, 1000); - if ($random == 0) { - $allFiles = true; - } else { - $allFiles = false; - } - $allVersions = Storage::getVersions($uid, $filename); - $versionsByFile[$filename] = $allVersions; - $sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview); + $time = time(); + list($toDelete, $sizeOfDeletedVersions) = self::getExpireList($time, $allVersions); + $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; // if still not enough free space we rearrange the versions from all files - if ($availableSpace <= 0 || $allFiles) { + if ($availableSpace <= 0) { $result = Storage::getAllVersions($uid); - $versionsByFile = $result['by_file']; $allVersions = $result['all']; - $sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview); + foreach ($result['by_file'] as $versions) { + list($toDeleteNew, $size) = self::getExpireList($time, $versions); + $toDelete = array_merge($toDelete, $toDeleteNew); + $sizeOfDeletedVersions += $size; + } $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; } + foreach($toDelete as $key => $path) { + \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $path)); + $versionsFileview->unlink($path); + unset($allVersions[$key]); // update array with the versions we keep + \OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG); + } + // Check if enough space is available after versions are rearranged. // If not we delete the oldest versions until we meet the size limit for versions, // but always keep the two latest versions @@ -497,6 +558,7 @@ class Storage { $version = current($allVersions); $versionsFileview->unlink($version['path'].'.v'.$version['version']); \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version'])); + \OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'] , \OCP\Util::DEBUG); $versionsSize -= $version['size']; $availableSpace += $version['size']; next($allVersions); @@ -509,69 +571,6 @@ class Storage { return false; } - /** - * @brief delete old version from a given list of versions - * - * @param array $versionsByFile list of versions ordered by files - * @param array $allVversions all versions across multiple files - * @param $versionsFileview \OC\Files\View on data/user/files_versions - * @return size of releted versions - */ - private static function delOldVersions($versionsByFile, &$allVersions, $versionsFileview) { - - $time = time(); - $size = 0; - - // delete old versions for every given file - foreach ($versionsByFile as $versions) { - $versions = array_reverse($versions); // newest version first - - $interval = 1; - $step = Storage::$max_versions_per_interval[$interval]['step']; - if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) { - $nextInterval = -1; - } else { - $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter']; - } - - $firstVersion = reset($versions); - $firstKey = key($versions); - $prevTimestamp = $firstVersion['version']; - $nextVersion = $firstVersion['version'] - $step; - unset($versions[$firstKey]); - - foreach ($versions as $key => $version) { - $newInterval = true; - while ($newInterval) { - if ($nextInterval == -1 || $version['version'] >= $nextInterval) { - if ($version['version'] > $nextVersion) { - //distance between two version too small, delete version - $versionsFileview->unlink($version['path'] . '.v' . $version['version']); - \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'] . '.v' . $version['version'])); - $size += $version['size']; - unset($allVersions[$key]); // update array with all versions - } else { - $nextVersion = $version['version'] - $step; - } - $newInterval = false; // version checked so we can move to the next one - } else { // time to move on to the next interval - $interval++; - $step = Storage::$max_versions_per_interval[$interval]['step']; - $nextVersion = $prevTimestamp - $step; - if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) { - $nextInterval = -1; - } else { - $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter']; - } - $newInterval = true; // we changed the interval -> check same version with new interval - } - } - $prevTimestamp = $version['version']; - } - } - return $size; - } - /** * @brief create recursively missing directories * @param string $filename $path to a file From 85269641db8ecbe7ec8bae30877a0f72db783d23 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 21 Jan 2014 12:10:24 +0100 Subject: [PATCH 47/51] add first unit test for the versioning app --- apps/files_versions/tests/versions.php | 188 +++++++++++++++++++++++++ tests/enable_all.php | 1 + 2 files changed, 189 insertions(+) create mode 100644 apps/files_versions/tests/versions.php diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php new file mode 100644 index 00000000000..713f7796c9b --- /dev/null +++ b/apps/files_versions/tests/versions.php @@ -0,0 +1,188 @@ + + * + * 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 . + * + */ + +require_once __DIR__ . '/../lib/versions.php'; + +/** + * Class Test_Files_versions + * @brief this class provide basic files versions test + */ +class Test_Files_Versioning extends \PHPUnit_Framework_TestCase { + + + /** + * @medium + * @brief test expire logic + * @dataProvider versionsProvider + */ + function testGetExpireList($versions, $sizeOfAllDeletedFiles) { + + // last interval enda at 2592000 + $startTime = 5000000; + + $testClass = new VersionStorageToTest(); + list($deleted, $size) = $testClass->callProtectedGetExpireList($startTime, array_reverse($versions)); + + // we should have deleted 16 files each of the size 1 + $this->assertEquals($sizeOfAllDeletedFiles, $size); + + // the deleted array should only contain versions which should be deleted + foreach($deleted as $key => $path) { + unset($versions[$key]); + $this->assertEquals("delete", substr($path, 0, strlen("delete"))); + } + + // the versions array should only contain versions which should be kept + foreach ($versions as $version) { + $this->assertEquals("keep", $version['path']); + } + + } + + public function versionsProvider() { + return array( + // first set of versions uniformly distributed versions + array( + array( + // first slice (10sec) keep one version every 2 seconds + array("version" => 4999999, "path" => "keep", "size" => 1), + array("version" => 4999998, "path" => "delete", "size" => 1), + array("version" => 4999997, "path" => "keep", "size" => 1), + array("version" => 4999995, "path" => "keep", "size" => 1), + array("version" => 4999994, "path" => "delete", "size" => 1), + //next slice (60sec) starts at 4999990 keep one version every 10 secons + array("version" => 4999988, "path" => "keep", "size" => 1), + array("version" => 4999978, "path" => "keep", "size" => 1), + array("version" => 4999975, "path" => "delete", "size" => 1), + array("version" => 4999972, "path" => "delete", "size" => 1), + array("version" => 4999967, "path" => "keep", "size" => 1), + array("version" => 4999958, "path" => "delete", "size" => 1), + array("version" => 4999957, "path" => "keep", "size" => 1), + //next slice (3600sec) start at 4999940 keep one version every 60 seconds + array("version" => 4999900, "path" => "keep", "size" => 1), + array("version" => 4999841, "path" => "delete", "size" => 1), + array("version" => 4999840, "path" => "keep", "size" => 1), + array("version" => 4999780, "path" => "keep", "size" => 1), + array("version" => 4996401, "path" => "keep", "size" => 1), + // next slice (86400sec) start at 4996400 keep one version every 3600 seconds + array("version" => 4996350, "path" => "delete", "size" => 1), + array("version" => 4992800, "path" => "keep", "size" => 1), + array("version" => 4989800, "path" => "delete", "size" => 1), + array("version" => 4989700, "path" => "delete", "size" => 1), + array("version" => 4989200, "path" => "keep", "size" => 1), + // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds + array("version" => 4913600, "path" => "keep", "size" => 1), + array("version" => 4852800, "path" => "delete", "size" => 1), + array("version" => 4827201, "path" => "delete", "size" => 1), + array("version" => 4827200, "path" => "keep", "size" => 1), + array("version" => 4777201, "path" => "delete", "size" => 1), + array("version" => 4777501, "path" => "delete", "size" => 1), + array("version" => 4740000, "path" => "keep", "size" => 1), + // final slice starts at 2408000 keep one version every 604800 secons + array("version" => 2408000, "path" => "keep", "size" => 1), + array("version" => 1803201, "path" => "delete", "size" => 1), + array("version" => 1803200, "path" => "keep", "size" => 1), + array("version" => 1800199, "path" => "delete", "size" => 1), + array("version" => 1800100, "path" => "delete", "size" => 1), + array("version" => 1198300, "path" => "keep", "size" => 1), + ), + 16 // size of all deleted files (every file has the size 1) + ), + // second set of versions, here we have only really old versions + array( + array( + // first slice (10sec) keep one version every 2 seconds + // next slice (60sec) starts at 4999990 keep one version every 10 secons + // next slice (3600sec) start at 4999940 keep one version every 60 seconds + // next slice (86400sec) start at 4996400 keep one version every 3600 seconds + array("version" => 4996400, "path" => "keep", "size" => 1), + array("version" => 4996350, "path" => "delete", "size" => 1), + array("version" => 4996350, "path" => "delete", "size" => 1), + array("version" => 4992800, "path" => "keep", "size" => 1), + array("version" => 4989800, "path" => "delete", "size" => 1), + array("version" => 4989700, "path" => "delete", "size" => 1), + array("version" => 4989200, "path" => "keep", "size" => 1), + // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds + array("version" => 4913600, "path" => "keep", "size" => 1), + array("version" => 4852800, "path" => "delete", "size" => 1), + array("version" => 4827201, "path" => "delete", "size" => 1), + array("version" => 4827200, "path" => "keep", "size" => 1), + array("version" => 4777201, "path" => "delete", "size" => 1), + array("version" => 4777501, "path" => "delete", "size" => 1), + array("version" => 4740000, "path" => "keep", "size" => 1), + // final slice starts at 2408000 keep one version every 604800 secons + array("version" => 2408000, "path" => "keep", "size" => 1), + array("version" => 1803201, "path" => "delete", "size" => 1), + array("version" => 1803200, "path" => "keep", "size" => 1), + array("version" => 1800199, "path" => "delete", "size" => 1), + array("version" => 1800100, "path" => "delete", "size" => 1), + array("version" => 1198300, "path" => "keep", "size" => 1), + ), + 11 // size of all deleted files (every file has the size 1) + ), + // third set of versions, with some gaps inbetween + array( + array( + // first slice (10sec) keep one version every 2 seconds + array("version" => 4999999, "path" => "keep", "size" => 1), + array("version" => 4999998, "path" => "delete", "size" => 1), + array("version" => 4999997, "path" => "keep", "size" => 1), + array("version" => 4999995, "path" => "keep", "size" => 1), + array("version" => 4999994, "path" => "delete", "size" => 1), + //next slice (60sec) starts at 4999990 keep one version every 10 secons + array("version" => 4999988, "path" => "keep", "size" => 1), + array("version" => 4999978, "path" => "keep", "size" => 1), + //next slice (3600sec) start at 4999940 keep one version every 60 seconds + // next slice (86400sec) start at 4996400 keep one version every 3600 seconds + array("version" => 4989200, "path" => "keep", "size" => 1), + // next slice (2592000sec) start at 4913600 keep one version every 86400 seconds + array("version" => 4913600, "path" => "keep", "size" => 1), + array("version" => 4852800, "path" => "delete", "size" => 1), + array("version" => 4827201, "path" => "delete", "size" => 1), + array("version" => 4827200, "path" => "keep", "size" => 1), + array("version" => 4777201, "path" => "delete", "size" => 1), + array("version" => 4777501, "path" => "delete", "size" => 1), + array("version" => 4740000, "path" => "keep", "size" => 1), + // final slice starts at 2408000 keep one version every 604800 secons + array("version" => 2408000, "path" => "keep", "size" => 1), + array("version" => 1803201, "path" => "delete", "size" => 1), + array("version" => 1803200, "path" => "keep", "size" => 1), + array("version" => 1800199, "path" => "delete", "size" => 1), + array("version" => 1800100, "path" => "delete", "size" => 1), + array("version" => 1198300, "path" => "keep", "size" => 1), + ), + 9 // size of all deleted files (every file has the size 1) + ), + + ); + } + +} + +// extend the original class to make it possible to test protected methods +class VersionStorageToTest extends \OCA\Files_Versions\Storage { + + public function callProtectedGetExpireList($time, $versions) { + return self::getExpireList($time, $versions); + + } +} diff --git a/tests/enable_all.php b/tests/enable_all.php index d54418ff8e4..efb43cae508 100644 --- a/tests/enable_all.php +++ b/tests/enable_all.php @@ -20,4 +20,5 @@ enableApp('files_sharing'); enableApp('files_encryption'); //enableApp('files_external'); enableApp('user_ldap'); +enableApp('files_versions'); From f09c19c31607ed212afd031fbbd582657f30dcc8 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 21 Jan 2014 16:19:26 +0100 Subject: [PATCH 48/51] Replaced time() with uniqid() to make sure the file name is unique The cache isn't cleared properly because unlink() doesn't remove the cache entry which caused side-effects when reusing the same file name (which randomly happens when time() returns the same value) This fix first makes sure the unit tests don't fail any more. The unlink() case with the cache will be investigated separately. --- apps/files_encryption/tests/crypt.php | 34 +++++++++++----------- apps/files_encryption/tests/keymanager.php | 4 +-- apps/files_encryption/tests/proxy.php | 2 +- apps/files_encryption/tests/stream.php | 12 ++++---- apps/files_encryption/tests/trashbin.php | 4 +-- apps/files_encryption/tests/util.php | 12 ++++---- apps/files_encryption/tests/webdav.php | 2 +- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index ca14e3e2ccb..388980ad4fd 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -155,7 +155,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testSymmetricStreamEncryptShortFileContent() { - $filename = 'tmp-' . time() . '.test'; + $filename = 'tmp-' . uniqid() . '.test'; $util = new Encryption\Util(new \OC_FilesystemView(), $this->userId); @@ -214,7 +214,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { function testSymmetricStreamEncryptLongFileContent() { // Generate a a random filename - $filename = 'tmp-' . time() . '.test'; + $filename = 'tmp-' . uniqid() . '.test'; $util = new Encryption\Util(new \OC_FilesystemView(), $this->userId); @@ -297,7 +297,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testSymmetricStreamDecryptShortFileContent() { - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///'. $this->userId . '/files/' . $filename, $this->dataShort); @@ -327,7 +327,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testSymmetricStreamDecryptLongFileContent() { - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); @@ -418,7 +418,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testRenameFile() { - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); @@ -431,7 +431,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $this->assertEquals($this->dataLong, $decrypt); - $newFilename = 'tmp-new-' . time(); + $newFilename = 'tmp-new-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); $view->rename($filename, $newFilename); @@ -449,7 +449,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testMoveFileIntoFolder() { - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); @@ -462,8 +462,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $this->assertEquals($this->dataLong, $decrypt); - $newFolder = '/newfolder' . time(); - $newFilename = 'tmp-new-' . time(); + $newFolder = '/newfolder' . uniqid(); + $newFilename = 'tmp-new-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); $view->mkdir($newFolder); $view->rename($filename, $newFolder . '/' . $newFilename); @@ -484,8 +484,8 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $view = new \OC\Files\View('/' . $this->userId . '/files'); - $filename = '/tmp-' . time(); - $folder = '/folder' . time(); + $filename = '/tmp-' . uniqid(); + $folder = '/folder' . uniqid(); $view->mkdir($folder); @@ -500,7 +500,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $this->assertEquals($this->dataLong, $decrypt); - $newFolder = '/newfolder/subfolder' . time(); + $newFolder = '/newfolder/subfolder' . uniqid(); $view->mkdir('/newfolder'); $view->rename($folder, $newFolder); @@ -519,7 +519,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { * @medium */ function testChangePassphrase() { - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); @@ -557,7 +557,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { */ function testViewFilePutAndGetContents() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -590,7 +590,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { * @large */ function testTouchExistingFile() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -614,7 +614,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { * @medium */ function testTouchFile() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); $view->touch($filename); @@ -638,7 +638,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { * @medium */ function testFopenFile() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index 1467979f005..58a57ee5af4 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -143,7 +143,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $key = $this->randomKey; - $file = 'unittest-' . time() . '.txt'; + $file = 'unittest-' . uniqid() . '.txt'; $util = new Encryption\Util($this->view, $this->userId); @@ -196,7 +196,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { function testRecursiveDelShareKeys() { // generate filename - $filename = '/tmp-' . time() . '.txt'; + $filename = '/tmp-' . uniqid() . '.txt'; // create folder structure $this->view->mkdir('/'.Test_Encryption_Keymanager::TEST_USER.'/files/folder1'); diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 419f95e1a38..c3006274d6d 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -80,7 +80,7 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase { // init short data $this->data = 'hats'; - $this->filename = 'enc_proxy_tests-' . time() . '.txt'; + $this->filename = 'enc_proxy_tests-' . uniqid() . '.txt'; } diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php index 2767bbe512b..fed2e7d89d1 100644 --- a/apps/files_encryption/tests/stream.php +++ b/apps/files_encryption/tests/stream.php @@ -99,7 +99,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { } function testStreamOptions() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -122,7 +122,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { } function testStreamSetBlocking() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -144,7 +144,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { * @medium */ function testStreamSetTimeout() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -163,7 +163,7 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { } function testStreamSetWriteBuffer() { - $filename = '/tmp-' . time(); + $filename = '/tmp-' . uniqid(); $view = new \OC\Files\View('/' . $this->userId . '/files'); // Save short data as encrypted file using stream wrapper @@ -187,9 +187,9 @@ class Test_Encryption_Stream extends \PHPUnit_Framework_TestCase { */ function testStreamFromLocalFile() { - $filename = '/' . $this->userId . '/files/' . 'tmp-' . time().'.txt'; + $filename = '/' . $this->userId . '/files/' . 'tmp-' . uniqid().'.txt'; - $tmpFilename = "/tmp/" . time() . ".txt"; + $tmpFilename = "/tmp/" . uniqid() . ".txt"; // write an encrypted file $cryptedFile = $this->view->file_put_contents($filename, $this->dataShort); diff --git a/apps/files_encryption/tests/trashbin.php b/apps/files_encryption/tests/trashbin.php index 2a41ace4015..2f9ecfd9d5d 100755 --- a/apps/files_encryption/tests/trashbin.php +++ b/apps/files_encryption/tests/trashbin.php @@ -119,7 +119,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { function testDeleteFile() { // generate filename - $filename = 'tmp-' . time() . '.txt'; + $filename = 'tmp-' . uniqid() . '.txt'; // save file with content $cryptedFile = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort); @@ -223,7 +223,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { function testPermanentDeleteFile() { // generate filename - $filename = 'tmp-' . time() . '.txt'; + $filename = 'tmp-' . uniqid() . '.txt'; // save file with content $cryptedFile = file_put_contents('crypt:///' .$this->userId. '/files/' . $filename, $this->dataShort); diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index b1904cbadc7..97e3c518dac 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -142,8 +142,8 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { self::loginHelper($this->userId); - $unencryptedFile = '/tmpUnencrypted-' . time() . '.txt'; - $encryptedFile = '/tmpEncrypted-' . time() . '.txt'; + $unencryptedFile = '/tmpUnencrypted-' . uniqid() . '.txt'; + $encryptedFile = '/tmpEncrypted-' . uniqid() . '.txt'; // Disable encryption proxy to write a unencrypted file $proxyStatus = \OC_FileProxy::$enabled; @@ -254,7 +254,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { \OC_User::setUserId(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); - $filename = '/tmp-' . time() . '.test'; + $filename = '/tmp-' . uniqid() . '.test'; // Disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; @@ -282,7 +282,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { function testGetFileSize() { \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1); - $filename = 'tmp-' . time(); + $filename = 'tmp-' . uniqid(); $externalFilename = '/' . $this->userId . '/files/' . $filename; // Test for 0 byte files @@ -318,7 +318,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { function testEncryptAll() { - $filename = "/encryptAll" . time() . ".txt"; + $filename = "/encryptAll" . uniqid() . ".txt"; $util = new Encryption\Util($this->view, $this->userId); // disable encryption to upload a unencrypted file @@ -350,7 +350,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { function testDecryptAll() { - $filename = "/decryptAll" . time() . ".txt"; + $filename = "/decryptAll" . uniqid() . ".txt"; $util = new Encryption\Util($this->view, $this->userId); $this->view->file_put_contents($this->userId . '/files/' . $filename, $this->dataShort); diff --git a/apps/files_encryption/tests/webdav.php b/apps/files_encryption/tests/webdav.php index a2a8ce6e34f..8e8b9c53cee 100755 --- a/apps/files_encryption/tests/webdav.php +++ b/apps/files_encryption/tests/webdav.php @@ -113,7 +113,7 @@ class Test_Encryption_Webdav extends \PHPUnit_Framework_TestCase { function testWebdavPUT() { // generate filename - $filename = '/tmp-' . time() . '.txt'; + $filename = '/tmp-' . uniqid() . '.txt'; // set server vars $_SERVER['REQUEST_METHOD'] = 'OPTIONS'; From 0b89a45f11b820d7d40e5f4a3c476d42a0577f58 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jan 2014 11:10:23 +0100 Subject: [PATCH 49/51] fix size calculation of getAllVersions() --- apps/files_versions/lib/versions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 8463bd9482c..3dd0c5985e6 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -402,7 +402,7 @@ class Storage { $result = array(); foreach ($versions as $key => $value) { - $size = $view->filesize($value['path']); + $size = $view->filesize(self::VERSIONS_ROOT.'/'.$value['path'].'.v'.$value['timestamp']); $filename = $value['path']; $result['all'][$key]['version'] = $value['timestamp']; From 8d36ddcf0397facb43ae871ef0fba564e50c92bf Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jan 2014 11:10:32 +0100 Subject: [PATCH 50/51] code clean-up --- apps/files_versions/ajax/getVersions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files_versions/ajax/getVersions.php b/apps/files_versions/ajax/getVersions.php index df29f401629..4cc1c428898 100644 --- a/apps/files_versions/ajax/getVersions.php +++ b/apps/files_versions/ajax/getVersions.php @@ -5,7 +5,8 @@ $source = $_GET['source']; $start = $_GET['start']; list ($uid, $filename) = OCA\Files_Versions\Storage::getUidAndFilename($source); $count = 5; //show the newest revisions -if( ($versions = OCA\Files_Versions\Storage::getVersions($uid, $filename, $source)) ) { +$versions = OCA\Files_Versions\Storage::getVersions($uid, $filename, $source); +if( $versions ) { $endReached = false; if (count($versions) <= $start+$count) { From a567f74d868df0ad70be18265876169e296ce0d9 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 22 Jan 2014 11:13:15 +0100 Subject: [PATCH 51/51] fix array order --- apps/files_versions/lib/versions.php | 7 +++---- apps/files_versions/tests/versions.php | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 3dd0c5985e6..328ed4305f4 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -264,7 +264,7 @@ class Storage { * @param string $uid user id from the owner of the file * @param string $filename file to find versions of, relative to the user files dir * @param string $userFullPath - * @returns array + * @returns array versions newest version first */ public static function getVersions($uid, $filename, $userFullPath = '') { $versions = array(); @@ -397,7 +397,8 @@ class Storage { } } - ksort($versions); + // newest version first + krsort($versions); $result = array(); @@ -428,8 +429,6 @@ class Storage { $size = 0; $toDelete = array(); // versions we want to delete - $versions = array_reverse($versions); // newest version first - $interval = 1; $step = Storage::$max_versions_per_interval[$interval]['step']; if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) { diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php index 713f7796c9b..25490aa1a04 100644 --- a/apps/files_versions/tests/versions.php +++ b/apps/files_versions/tests/versions.php @@ -40,7 +40,7 @@ class Test_Files_Versioning extends \PHPUnit_Framework_TestCase { $startTime = 5000000; $testClass = new VersionStorageToTest(); - list($deleted, $size) = $testClass->callProtectedGetExpireList($startTime, array_reverse($versions)); + list($deleted, $size) = $testClass->callProtectedGetExpireList($startTime, $versions); // we should have deleted 16 files each of the size 1 $this->assertEquals($sizeOfAllDeletedFiles, $size);