Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2014-02-07 17:21:10 +0400
committerThomas Müller <thomas.mueller@tmit.eu>2014-02-07 17:21:10 +0400
commit5edc4c95bc686a702b37e5a2b93e0557d50b86ec (patch)
tree1c23d3ad914c945a1f6dbe2c71d949018e8903d7 /apps
parent379ddd88d6483b4b5cf43b149e08d9bc7b893d92 (diff)
parentf9bd4c5d24b87d61803e9706d2d1c5babfa35bf9 (diff)
Merge branch 'stable6' into backport_6777_stable6
Conflicts: apps/files_sharing/css/public.css apps/files_sharing/templates/public.php
Diffstat (limited to 'apps')
-rw-r--r--apps/files/css/upload.css8
-rw-r--r--apps/files/templates/index.php2
-rw-r--r--apps/files_encryption/hooks/hooks.php64
-rwxr-xr-xapps/files_encryption/lib/helper.php2
-rwxr-xr-xapps/files_encryption/lib/keymanager.php55
-rw-r--r--apps/files_encryption/lib/proxy.php44
-rw-r--r--apps/files_encryption/lib/util.php2
-rw-r--r--apps/files_encryption/tests/hooks.php271
-rw-r--r--apps/files_encryption/tests/keymanager.php20
-rw-r--r--apps/files_encryption/tests/proxy.php50
-rwxr-xr-xapps/files_encryption/tests/share.php44
-rw-r--r--apps/files_sharing/css/authenticate.css7
-rw-r--r--apps/files_sharing/css/public.css2
-rw-r--r--apps/files_sharing/lib/cache.php39
-rw-r--r--apps/files_sharing/templates/authenticate.php2
-rw-r--r--apps/files_sharing/tests/cache.php134
16 files changed, 599 insertions, 147 deletions
diff --git a/apps/files/css/upload.css b/apps/files/css/upload.css
index ef043569094..d44967c7ae0 100644
--- a/apps/files/css/upload.css
+++ b/apps/files/css/upload.css
@@ -18,9 +18,6 @@
margin: -5px -3px;
cursor: pointer;
z-index: 10;
- background-image: url('%webroot%/core/img/actions/upload.svg');
- background-repeat: no-repeat;
- background-position: center;
opacity: .65;
}
.file_upload_target { display:none; }
@@ -119,11 +116,6 @@
.oc-dialog .fileexists .conflict input[type='checkbox'] {
float: left;
}
-.oc-dialog .fileexists .toggle {
- background-image: url('%webroot%/core/img/actions/triangle-e.png');
- width: 16px;
- height: 16px;
-}
.oc-dialog .fileexists #allfileslabel {
float:right;
}
diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php
index 5188ca56281..ff78f0ca551 100644
--- a/apps/files/templates/index.php
+++ b/apps/files/templates/index.php
@@ -29,7 +29,7 @@
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
<input type="file" id="file_upload_start" name='files[]'
data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
- <a href="#" class="svg"></a>
+ <a href="#" class="svg icon icon-upload"></a>
</div>
<?php if ($_['trash']): ?>
<input id="trash" type="button" value="<?php p($l->t('Deleted files'));?>" class="button" <?php $_['trashEmpty'] ? p('disabled') : '' ?> />
diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php
index 09d5687e226..4c4b3f2040f 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -32,6 +32,8 @@ class Hooks {
// file for which we want to rename the keys after the rename operation was successful
private static $renamedFiles = array();
+ // file for which we want to delete the keys after the delete operation was successful
+ private static $deleteFiles = array();
/**
* @brief Startup encryption backend upon user login
@@ -630,4 +632,66 @@ class Hooks {
}
}
+ /**
+ * @brief if the file was really deleted we remove the encryption keys
+ * @param array $params
+ * @return boolean
+ */
+ public static function postDelete($params) {
+
+ if (!isset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]])) {
+ return true;
+ }
+
+ $deletedFile = self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]];
+ $path = $deletedFile['path'];
+ $user = $deletedFile['uid'];
+
+ // we don't need to remember the file any longer
+ unset(self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]]);
+
+ $view = new \OC\Files\View('/');
+
+ // return if the file still exists and wasn't deleted correctly
+ if ($view->file_exists('/' . $user . '/files/' . $path)) {
+ return true;
+ }
+
+ // Disable encryption proxy to prevent recursive calls
+ $proxyStatus = \OC_FileProxy::$enabled;
+ \OC_FileProxy::$enabled = false;
+
+ // Delete keyfile & shareKey so it isn't orphaned
+ if (!Keymanager::deleteFileKey($view, $path, $user)) {
+ \OCP\Util::writeLog('Encryption library',
+ 'Keyfile or shareKey could not be deleted for file "' . $user.'/files/'.$path . '"', \OCP\Util::ERROR);
+ }
+
+ Keymanager::delAllShareKeys($view, $user, $path);
+
+ \OC_FileProxy::$enabled = $proxyStatus;
+ }
+
+ /**
+ * @brief remember the file which should be deleted and it's owner
+ * @param array $params
+ * @return boolean
+ */
+ public static function preDelete($params) {
+ $path = $params[\OC\Files\Filesystem::signal_param_path];
+
+ // skip this method if the trash bin is enabled or if we delete a file
+ // outside of /data/user/files
+ if (\OCP\App::isEnabled('files_trashbin')) {
+ return true;
+ }
+
+ $util = new Util(new \OC_FilesystemView('/'), \OCP\USER::getUser());
+ list($owner, $ownerPath) = $util->getUidAndFilename($path);
+
+ self::$deleteFiles[$params[\OC\Files\Filesystem::signal_param_path]] = array(
+ 'uid' => $owner,
+ 'path' => $ownerPath);
+ }
+
}
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php
index 67facb761ff..584935f6139 100755
--- a/apps/files_encryption/lib/helper.php
+++ b/apps/files_encryption/lib/helper.php
@@ -61,6 +61,8 @@ class Helper {
\OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Encryption\Hooks', 'preRename');
\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Encryption\Hooks', 'postRename');
+ \OCP\Util::connectHook('OC_Filesystem', 'post_delete', 'OCA\Encryption\Hooks', 'postDelete');
+ \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Encryption\Hooks', 'preDelete');
}
/**
diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php
index b2c756894b4..7abc565f609 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -214,15 +214,24 @@ class Keymanager {
*
* @param \OC_FilesystemView $view
* @param string $path path of the file the key belongs to
+ * @param string $userId the user to whom the file belongs
* @return bool Outcome of unlink operation
* @note $path must be relative to data/user/files. e.g. mydoc.txt NOT
* /data/admin/files/mydoc.txt
*/
- public static function deleteFileKey(\OC_FilesystemView $view, $path) {
+ public static function deleteFileKey($view, $path, $userId=null) {
$trimmed = ltrim($path, '/');
- $userId = Helper::getUser($path);
+ if ($trimmed === '') {
+ \OCP\Util::writeLog('Encryption library',
+ 'Can\'t delete file-key empty path given!', \OCP\Util::ERROR);
+ return false;
+ }
+
+ if ($userId === null) {
+ $userId = Helper::getUser($path);
+ }
$util = new Util($view, $userId);
if($util->isSystemWideMountPoint($path)) {
@@ -402,7 +411,15 @@ class Keymanager {
* @param string $userId owner of the file
* @param string $filePath path to the file, relative to the owners file dir
*/
- public static function delAllShareKeys(\OC_FilesystemView $view, $userId, $filePath) {
+ public static function delAllShareKeys($view, $userId, $filePath) {
+
+ $filePath = ltrim($filePath, '/');
+
+ if ($filePath === '') {
+ \OCP\Util::writeLog('Encryption library',
+ 'Can\'t delete share-keys empty path given!', \OCP\Util::ERROR);
+ return false;
+ }
$util = new util($view, $userId);
@@ -413,17 +430,15 @@ class Keymanager {
}
- if ($view->is_dir($userId . '/files/' . $filePath)) {
+ if ($view->is_dir($baseDir . $filePath)) {
$view->unlink($baseDir . $filePath);
} else {
- $localKeyPath = $view->getLocalFile($baseDir . $filePath);
- $escapedPath = Helper::escapeGlobPattern($localKeyPath);
- $matches = glob($escapedPath . '*.shareKey');
- foreach ($matches as $ma) {
- $result = unlink($ma);
- if (!$result) {
- \OCP\Util::writeLog('Encryption library',
- 'Keyfile or shareKey could not be deleted for file "' . $filePath . '"', \OCP\Util::ERROR);
+ $parentDir = dirname($baseDir . $filePath);
+ $filename = pathinfo($filePath, PATHINFO_BASENAME);
+ foreach($view->getDirectoryContent($parentDir) as $content) {
+ $path = $content['path'];
+ if (self::getFilenameFromShareKey($content['name']) === $filename) {
+ $view->unlink('/' . $userId . '/' . $path);
}
}
}
@@ -523,4 +538,20 @@ class Keymanager {
return $targetPath;
}
+
+ /**
+ * @brief extract filename from share key name
+ * @param string $shareKey (filename.userid.sharekey)
+ * @return mixed filename or false
+ */
+ protected static function getFilenameFromShareKey($shareKey) {
+ $parts = explode('.', $shareKey);
+
+ $filename = false;
+ if(count($parts) > 2) {
+ $filename = implode('.', array_slice($parts, 0, count($parts)-2));
+ }
+
+ return $filename;
+ }
}
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index 5e48f8c8540..11048005969 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -204,50 +204,6 @@ class Proxy extends \OC_FileProxy {
}
/**
- * @brief When a file is deleted, remove its keyfile also
- */
- public function preUnlink($path) {
-
- $relPath = Helper::stripUserFilesPath($path);
-
- // skip this method if the trash bin is enabled or if we delete a file
- // outside of /data/user/files
- if (\OCP\App::isEnabled('files_trashbin') || $relPath === false) {
- return true;
- }
-
- // Disable encryption proxy to prevent recursive calls
- $proxyStatus = \OC_FileProxy::$enabled;
- \OC_FileProxy::$enabled = false;
-
- $view = new \OC_FilesystemView('/');
-
- $userId = \OCP\USER::getUser();
-
- $util = new Util($view, $userId);
-
- // get relative path
- $relativePath = \OCA\Encryption\Helper::stripUserFilesPath($path);
-
- list($owner, $ownerPath) = $util->getUidAndFilename($relativePath);
-
- // Delete keyfile & shareKey so it isn't orphaned
- if (!Keymanager::deleteFileKey($view, $ownerPath)) {
- \OCP\Util::writeLog('Encryption library',
- 'Keyfile or shareKey could not be deleted for file "' . $ownerPath . '"', \OCP\Util::ERROR);
- }
-
- Keymanager::delAllShareKeys($view, $owner, $ownerPath);
-
- \OC_FileProxy::$enabled = $proxyStatus;
-
- // If we don't return true then file delete will fail; better
- // to leave orphaned keyfiles than to disallow file deletion
- return true;
-
- }
-
- /**
* @param $path
* @return bool
*/
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index d011e677a41..4d6a084908e 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -57,7 +57,7 @@ class Util {
* @param $userId
* @param bool $client
*/
- public function __construct(\OC_FilesystemView $view, $userId, $client = false) {
+ public function __construct($view, $userId, $client = false) {
$this->view = $view;
$this->client = $client;
diff --git a/apps/files_encryption/tests/hooks.php b/apps/files_encryption/tests/hooks.php
new file mode 100644
index 00000000000..c26cba6406d
--- /dev/null
+++ b/apps/files_encryption/tests/hooks.php
@@ -0,0 +1,271 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bjoern Schiessle
+ * @copyright 2014 Bjoern Schiessle <schiessle@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+require_once __DIR__ . '/../../../lib/base.php';
+require_once __DIR__ . '/../lib/crypt.php';
+require_once __DIR__ . '/../lib/keymanager.php';
+require_once __DIR__ . '/../lib/stream.php';
+require_once __DIR__ . '/../lib/util.php';
+require_once __DIR__ . '/../appinfo/app.php';
+require_once __DIR__ . '/util.php';
+
+use OCA\Encryption;
+
+/**
+ * Class Test_Encryption_Hooks
+ * @brief this class provide basic hook app tests
+ */
+class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
+
+ const TEST_ENCRYPTION_HOOKS_USER1 = "test-proxy-user1";
+ const TEST_ENCRYPTION_HOOKS_USER2 = "test-proxy-user2";
+
+ /**
+ * @var \OC_FilesystemView
+ */
+ public $user1View; // view on /data/user1/files
+ public $user2View; // view on /data/user2/files
+ public $rootView; // view on /data/user
+ public $data;
+ public $filename;
+
+ public static function setUpBeforeClass() {
+ // reset backend
+ \OC_User::clearBackends();
+ \OC_User::useBackend('database');
+
+ \OC_Hook::clear('OC_Filesystem');
+ \OC_Hook::clear('OC_User');
+
+ // clear share hooks
+ \OC_Hook::clear('OCP\\Share');
+ \OC::registerShareHooks();
+ \OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup');
+
+ // Filesystem related hooks
+ \OCA\Encryption\Helper::registerFilesystemHooks();
+
+ // Sharing related hooks
+ \OCA\Encryption\Helper::registerShareHooks();
+
+ // clear and register proxies
+ \OC_FileProxy::clearProxies();
+ \OC_FileProxy::register(new OCA\Encryption\Proxy());
+
+ // create test user
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1, true);
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2, true);
+ }
+
+ function setUp() {
+ // set user id
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+ \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+
+ // init filesystem view
+ $this->user1View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '/files');
+ $this->user2View = new \OC_FilesystemView('/'. \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '/files');
+ $this->rootView = new \OC_FilesystemView('/');
+
+ // init short data
+ $this->data = 'hats';
+ $this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
+
+ }
+
+ public static function tearDownAfterClass() {
+ // cleanup test user
+ \OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+ \OC_User::deleteUser(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
+ }
+
+ function testDeleteHooks() {
+
+ // remember files_trashbin state
+ $stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
+
+ // we want to tests with app files_trashbin disabled
+ \OC_App::disable('files_trashbin');
+
+ // make sure that the trash bin is disabled
+ $this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
+
+ $this->user1View->file_put_contents($this->filename, $this->data);
+
+ // check if all keys are generated
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+
+ \Test_Encryption_Util::logoutHelper();
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
+ \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
+
+
+ $this->user2View->file_put_contents($this->filename, $this->data);
+
+ // check if all keys are generated
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+
+ // create a dummy file that we can delete something outside of data/user/files
+ // in this case no share or file keys should be deleted
+ $this->rootView->file_put_contents(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename, $this->data);
+
+ // delete dummy file outside of data/user/files
+ $this->rootView->unlink(self::TEST_ENCRYPTION_HOOKS_USER2 . "/" . $this->filename);
+
+ // all keys should still exist
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+
+ // delete the file in data/user/files
+ // now the correspondig share and file keys from user2 should be deleted
+ $this->user2View->unlink($this->filename);
+
+ // check if keys from user2 are really deleted
+ $this->assertFalse($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertFalse($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ // but user1 keys should still exist
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ if ($stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+ function testDeleteHooksForSharedFiles() {
+
+ \Test_Encryption_Util::logoutHelper();
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+ \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+
+ // remember files_trashbin state
+ $stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
+
+ // we want to tests with app files_trashbin disabled
+ \OC_App::disable('files_trashbin');
+
+ // make sure that the trash bin is disabled
+ $this->assertFalse(\OC_APP::isEnabled('files_trashbin'));
+
+ $this->user1View->file_put_contents($this->filename, $this->data);
+
+ // check if all keys are generated
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ // get the file info from previous created file
+ $fileInfo = $this->user1View->getFileInfo($this->filename);
+
+ // check if we have a valid file info
+ $this->assertTrue(is_array($fileInfo));
+
+ // share the file with user2
+ \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2, OCP\PERMISSION_ALL);
+
+ // check if new share key exists
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+
+ \Test_Encryption_Util::logoutHelper();
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
+ \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2);
+
+ // user2 has a local file with the same name
+ $this->user2View->file_put_contents($this->filename, $this->data);
+
+ // check if all keys are generated
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ // delete the Shared file from user1 in data/user2/files/Shared
+ $this->user2View->unlink('/Shared/' . $this->filename);
+
+ // now keys from user1s home should be gone
+ $this->assertFalse($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
+ $this->assertFalse($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertFalse($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ // but user2 keys should still exist
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/share-keys/'
+ . $this->filename . '.' . \Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER2 . '.shareKey'));
+ $this->assertTrue($this->rootView->file_exists(
+ self::TEST_ENCRYPTION_HOOKS_USER2 . '/files_encryption/keyfiles/' . $this->filename . '.key'));
+
+ // cleanup
+
+ $this->user2View->unlink($this->filename);
+
+ \Test_Encryption_Util::logoutHelper();
+ \Test_Encryption_Util::loginHelper(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+ \OC_User::setUserId(\Test_Encryption_Hooks::TEST_ENCRYPTION_HOOKS_USER1);
+
+ // unshare the file
+ \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, self::TEST_ENCRYPTION_HOOKS_USER2);
+
+ $this->user1View->unlink($this->filename);
+
+ if ($stateFilesTrashbin) {
+ OC_App::enable('files_trashbin');
+ }
+ else {
+ OC_App::disable('files_trashbin');
+ }
+ }
+
+}
diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php
index 58a57ee5af4..6f32c50743c 100644
--- a/apps/files_encryption/tests/keymanager.php
+++ b/apps/files_encryption/tests/keymanager.php
@@ -137,6 +137,17 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
}
/**
+ * @small
+ */
+ function testGetFilenameFromShareKey() {
+ $this->assertEquals("file",
+ \TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.user.shareKey"));
+ $this->assertEquals("file.name.with.dots",
+ \TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.name.with.dots.user.shareKey"));
+ $this->assertFalse(\TestProtectedKeymanagerMethods::testGetFilenameFromShareKey("file.txt"));
+ }
+
+ /**
* @medium
*/
function testSetFileKey() {
@@ -234,3 +245,12 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase {
\OC_FileProxy::$enabled = $proxyStatus;
}
}
+
+/**
+ * dummy class to access protected methods of \OCA\Encryption\Keymanager for testing
+ */
+class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager {
+ public static function testGetFilenameFromShareKey($sharekey) {
+ return self::getFilenameFromShareKey($sharekey);
+ }
+} \ No newline at end of file
diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php
index c3006274d6d..51cc0b795e3 100644
--- a/apps/files_encryption/tests/proxy.php
+++ b/apps/files_encryption/tests/proxy.php
@@ -112,54 +112,4 @@ class Test_Encryption_Proxy extends \PHPUnit_Framework_TestCase {
}
- function testPreUnlinkWithoutTrash() {
-
- // remember files_trashbin state
- $stateFilesTrashbin = OC_App::isEnabled('files_trashbin');
-
- // we want to tests with app files_trashbin enabled
- \OC_App::disable('files_trashbin');
-
- $this->view->file_put_contents($this->filename, $this->data);
-
- // create a dummy file that we can delete something outside of data/user/files
- $this->rootView->file_put_contents("dummy.txt", $this->data);
-
- // check if all keys are generated
- $this->assertTrue($this->rootView->file_exists(
- '/files_encryption/share-keys/'
- . $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
- $this->assertTrue($this->rootView->file_exists(
- '/files_encryption/keyfiles/' . $this->filename . '.key'));
-
-
- // delete dummy file outside of data/user/files
- $this->rootView->unlink("dummy.txt");
-
- // all keys should still exist
- $this->assertTrue($this->rootView->file_exists(
- '/files_encryption/share-keys/'
- . $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
- $this->assertTrue($this->rootView->file_exists(
- '/files_encryption/keyfiles/' . $this->filename . '.key'));
-
-
- // delete the file in data/user/files
- $this->view->unlink($this->filename);
-
- // now also the keys should be gone
- $this->assertFalse($this->rootView->file_exists(
- '/files_encryption/share-keys/'
- . $this->filename . '.' . \Test_Encryption_Proxy::TEST_ENCRYPTION_PROXY_USER1 . '.shareKey'));
- $this->assertFalse($this->rootView->file_exists(
- '/files_encryption/keyfiles/' . $this->filename . '.key'));
-
- if ($stateFilesTrashbin) {
- OC_App::enable('files_trashbin');
- }
- else {
- OC_App::disable('files_trashbin');
- }
- }
-
}
diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php
index e55427620a6..acf408a07f0 100755
--- a/apps/files_encryption/tests/share.php
+++ b/apps/files_encryption/tests/share.php
@@ -194,8 +194,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
- $this->view->unlink(
- '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -265,8 +266,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
- $this->view->unlink(
- '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -352,7 +354,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
+ $this->view->unlink($this->folder1);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -482,9 +486,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
// cleanup
- $this->view->unlink(
- '/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files' . $this->folder1 . $this->subfolder
- . $this->subsubfolder . '/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files');
+ $this->view->unlink($this->folder1 . $this->subfolder . $this->subsubfolder . '/' . $this->filename);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -559,7 +563,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . $publicShareKeyId . '.shareKey'));
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -636,7 +642,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4 . '.shareKey'));
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
// check if share key not exists
$this->assertFalse($this->view->file_exists(
@@ -731,8 +739,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . $recoveryKeyId . '.shareKey'));
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->folder1);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->unlink($this->folder1);
+ $this->view->chroot('/');
// check if share key for recovery not exists
$this->assertFalse($this->view->file_exists(
@@ -828,8 +838,10 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
$this->assertEquals($this->dataShort, $retrievedCryptedFile2);
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->folder1);
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/');
+ $this->view->unlink($this->folder1);
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
// check if share key for user and recovery exists
$this->assertFalse($this->view->file_exists(
@@ -930,7 +942,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'));
// cleanup
- $this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
+ $this->view->chroot('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/');
+ $this->view->unlink($this->filename);
+ $this->view->chroot('/');
}
}
diff --git a/apps/files_sharing/css/authenticate.css b/apps/files_sharing/css/authenticate.css
index cebe906dd59..ef963ba7c65 100644
--- a/apps/files_sharing/css/authenticate.css
+++ b/apps/files_sharing/css/authenticate.css
@@ -11,16 +11,13 @@
margin: 6px;
}
-input[type="submit"]{
+input[type='submit'] {
width: 45px;
height: 45px;
margin: 6px;
- background-image: url('%webroot%/core/img/actions/confirm.svg');
- background-repeat: no-repeat;
- background-position: center;
}
-#body-login input[type="submit"] {
+#body-login input[type='submit'] {
position: absolute;
top: 0px;
}
diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css
index 5f1cc524162..8d03868a972 100644
--- a/apps/files_sharing/css/public.css
+++ b/apps/files_sharing/css/public.css
@@ -3,7 +3,7 @@ body {
}
#header {
- background: #1d2d44 url('%webroot%/core/img/noise.png') repeat;
+ background-color: #1d2d44;
height:32px;
left:0;
line-height:32px;
diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php
index 425d51113b1..86e324409fe 100644
--- a/apps/files_sharing/lib/cache.php
+++ b/apps/files_sharing/lib/cache.php
@@ -259,17 +259,38 @@ class Shared_Cache extends Cache {
* @return array
*/
public function searchByMime($mimetype) {
-
- if (strpos($mimetype, '/')) {
- $where = '`mimetype` = ? AND ';
- } else {
- $where = '`mimepart` = ? AND ';
+ $mimepart = null;
+ if (strpos($mimetype, '/') === false) {
+ $mimepart = $mimetype;
+ $mimetype = null;
}
- $value = $this->getMimetypeId($mimetype);
-
- return $this->searchWithWhere($where, $value);
-
+ // note: searchWithWhere is currently broken as it doesn't
+ // recurse into subdirs nor returns the correct
+ // file paths, so using getFolderContents() for now
+
+ $result = array();
+ $exploreDirs = array('');
+ while (count($exploreDirs) > 0) {
+ $dir = array_pop($exploreDirs);
+ $files = $this->getFolderContents($dir);
+ // no results?
+ if (!$files) {
+ continue;
+ }
+ foreach ($files as $file) {
+ if ($file['mimetype'] === 'httpd/unix-directory') {
+ $exploreDirs[] = ltrim($dir . '/' . $file['name'], '/');
+ }
+ else if (($mimepart && $file['mimepart'] === $mimepart) || ($mimetype && $file['mimetype'] === $mimetype)) {
+ // usersPath not reliable
+ //$file['path'] = $file['usersPath'];
+ $file['path'] = ltrim($dir . '/' . $file['name'], '/');
+ $result[] = $file;
+ }
+ }
+ }
+ return $result;
}
/**
diff --git a/apps/files_sharing/templates/authenticate.php b/apps/files_sharing/templates/authenticate.php
index 6b98e6c9f34..928be93fc96 100644
--- a/apps/files_sharing/templates/authenticate.php
+++ b/apps/files_sharing/templates/authenticate.php
@@ -9,7 +9,7 @@
<p class="infield">
<label for="password" class="infield"><?php p($l->t('Password')); ?></label>
<input type="password" name="password" id="password" placeholder="" value="" autofocus />
- <input type="submit" value="" class="svg" />
+ <input type="submit" value="" class="svg icon icon-confirm" />
</p>
</fieldset>
</form>
diff --git a/apps/files_sharing/tests/cache.php b/apps/files_sharing/tests/cache.php
new file mode 100644
index 00000000000..56a51c83f6b
--- /dev/null
+++ b/apps/files_sharing/tests/cache.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Vincent Petry
+ * @copyright 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+require_once __DIR__ . '/base.php';
+
+class Test_Files_Sharing_Cache extends Test_Files_Sharing_Base {
+
+ function setUp() {
+ parent::setUp();
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ // prepare user1's dir structure
+ $textData = "dummy file data\n";
+ $this->view->mkdir('container');
+ $this->view->mkdir('container/shareddir');
+ $this->view->mkdir('container/shareddir/subdir');
+ $this->view->mkdir('container/shareddir/emptydir');
+
+ $textData = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ $this->view->file_put_contents('container/not shared.txt', $textData);
+ $this->view->file_put_contents('container/shared single file.txt', $textData);
+ $this->view->file_put_contents('container/shareddir/bar.txt', $textData);
+ $this->view->file_put_contents('container/shareddir/subdir/another.txt', $textData);
+ $this->view->file_put_contents('container/shareddir/subdir/another too.txt', $textData);
+ $this->view->file_put_contents('container/shareddir/subdir/not a text file.xml', '<xml></xml>');
+
+ list($this->ownerStorage, $internalPath) = $this->view->resolvePath('');
+ $this->ownerCache = $this->ownerStorage->getCache();
+ $this->ownerStorage->getScanner()->scan('');
+
+ // share "shareddir" with user2
+ $fileinfo = $this->view->getFileInfo('container/shareddir');
+ \OCP\Share::shareItem('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2, 31);
+
+ $fileinfo = $this->view->getFileInfo('container/shared single file.txt');
+ \OCP\Share::shareItem('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2, 31);
+
+ // login as user2
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
+
+ // retrieve the shared storage
+ $secondView = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2);
+ list($this->sharedStorage, $internalPath) = $secondView->resolvePath('files/Shared/shareddir');
+ $this->sharedCache = $this->sharedStorage->getCache();
+ }
+
+ function tearDown() {
+ $this->sharedCache->clear();
+
+ self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
+
+ $fileinfo = $this->view->getFileInfo('container/shareddir');
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2);
+
+ $fileinfo = $this->view->getFileInfo('container/shared single file.txt');
+ \OCP\Share::unshare('file', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2);
+
+ $this->view->deleteAll('container');
+
+ $this->ownerCache->clear();
+
+ parent::tearDown();
+ }
+
+ /**
+ * Test searching by mime type
+ */
+ function testSearchByMime() {
+ $results = $this->sharedStorage->getCache()->searchByMime('text');
+ $check = array(
+ array(
+ 'name' => 'shared single file.txt',
+ 'path' => 'shared single file.txt'
+ ),
+ array(
+ 'name' => 'bar.txt',
+ 'path' => 'shareddir/bar.txt'
+ ),
+ array(
+ 'name' => 'another too.txt',
+ 'path' => 'shareddir/subdir/another too.txt'
+ ),
+ array(
+ 'name' => 'another.txt',
+ 'path' => 'shareddir/subdir/another.txt'
+ ),
+ );
+ $this->verifyFiles($check, $results);
+
+ $results2 = $this->sharedStorage->getCache()->searchByMime('text/plain');
+
+ $this->verifyFiles($check, $results);
+ }
+
+ /**
+ * Checks that all provided attributes exist in the files list,
+ * only the values provided in $examples will be used to check against
+ * the file list. The files order also needs to be the same.
+ *
+ * @param array $examples array of example files
+ * @param array $files array of files
+ */
+ private function verifyFiles($examples, $files) {
+ $this->assertEquals(count($examples), count($files));
+ foreach ($files as $i => $file) {
+ foreach ($examples[$i] as $key => $value) {
+ $this->assertEquals($value, $file[$key]);
+ }
+ }
+ }
+}