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 957daeb4d1..6baaabe11b 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 b4be1c1dc4..068c2c13c6 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 886c324e33..895f97bd2c 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 f0fd8e1ab1..eb1dd8d1c9 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 84e2e5c63e..2fe2837019 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 c0e618cc86..9b37dccb50 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 1d527dca8e..a427e3d8f2 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 a427e3d8f2..8b5e097641 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 060d4dfedc..be53a7d8a8 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 eacd4096ed..88dbac9c88 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 f380234af0..92f2ac484e 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 c02ab70ce8..30aea9c8c8 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 92f2ac484e..e84f482d67 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 90d07d4336..2a0df62276 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 567f88b91b..322a6aab9c 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 41f352d853..4fe76b9771 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 322a6aab9c..769fd8d899 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 8375b231e9..835b6b4c01 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 4f2fe5cdb6..0267c4e245 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 5ae157b07c..6886db668b 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 be53a7d8a8..f4121430b9 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 9d495916d2..ee05b65136 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 0f8034e57d..f6f4cb16e8 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 0267c4e245..d54418ff8e 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 7d9329328a..5d87693247 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 2f630e1f01..f4fb96a7a7 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 f30575c7b1..d320f6f241 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 caf7b1d706..8a9d5ca615 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 c457979113..ab67c8d302 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 a4b3761dbd..be8b543954 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 ee05b65136..b6d9d6bb0a 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 34c00e97fb..0c60557914 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 a93c675d46..8a96885b78 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 a55c55e24c..1d05d01e1f 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 0b76f775fe..ce48ef77d1 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 8a96885b78..3f5d59e56e 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 1d05d01e1f..ce81dff448 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 ce48ef77d1..be1cf0387b 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 fdaa3aa334..999d3eee0c 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 473bcf25f2..3857ba10fa 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 43016e0892..a430e3e461 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 9b14335782..87bafb64d4 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 faeedfcc05..7c2c94c904 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 e26daa2582..8e7831ca54 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 bfff214334..d98066c4b7 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 d320f6f241..0597183adc 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 c40cf6911b..285b1a58c6 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 58f624c899..251ecbe707 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 8893911ed5..d97544b865 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 769fd8d899..7544980e07 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 7e6cc818ef..f268fa10b6 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 fdaa3aa334..12e870f141 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 d050efd5b3..100379047d 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 eb1dd8d1c9..4573fe8d8d 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 4573fe8d8d..ddc9e1e066 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 0e905f993a..bdaf6a77d1 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 0e29edbba3..a37b9823ad 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 54a9806e8b..a52f522afa 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 0d827da28e..4b716e764f 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 d050efd5b3..80dd708ee5 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 6a9e5a2df5..5c5d7e3a3d 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 72afa6f947..8aa7a074d0 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 831e3ef1cf..cd5d233ef9 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 09f646921e..9727d847d2 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 ddc9e1e066..f832d04a70 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 2fe2837019..d6acee6c92 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 e6c81d58bd..8ce632013c 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 4f48f71d8c..df29f40162 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 31525028ef..bd9b7366ab 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 f268fa10b6..01c2e1ccde 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 01c2e1ccde..8463bd9482 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 0000000000..713f7796c9 --- /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 d54418ff8e..efb43cae50 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 ca14e3e2cc..388980ad4f 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 1467979f00..58a57ee5af 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 419f95e1a3..c3006274d6 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 2767bbe512..fed2e7d89d 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 2a41ace401..2f9ecfd9d5 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 b1904cbadc..97e3c518da 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 a2a8ce6e34..8e8b9c53ce 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 8463bd9482..3dd0c5985e 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 df29f40162..4cc1c42889 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 3dd0c5985e..328ed4305f 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 713f7796c9..25490aa1a0 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);