diff options
60 files changed, 965 insertions, 378 deletions
diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 46629e1b602..392fc5bd1c8 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -46,6 +46,7 @@ function progress($notification_code, $severity, $message, $message_code, $bytes } } + $l10n = \OC::$server->getL10N('files'); $result = array( @@ -93,7 +94,8 @@ if (\OC\Files\Filesystem::file_exists($target)) { } if($source) { - if(substr($source, 0, 8)!='https://' and substr($source, 0, 7)!='http://') { + $httpHelper = \OC::$server->getHTTPHelper(); + if(!$httpHelper->isHTTPURL($source)) { OCP\JSON::error(array('data' => array('message' => $l10n->t('Not a valid source')))); exit(); } @@ -104,7 +106,10 @@ if($source) { exit(); } - $ctx = stream_context_create(null, array('notification' =>'progress')); + $source = $httpHelper->getFinalLocationOfURL($source); + + $ctx = stream_context_create(\OC::$server->getHTTPHelper()->getDefaultContextArray(), array('notification' =>'progress')); + $sourceStream=@fopen($source, 'rb', false, $ctx); $result = 0; if (is_resource($sourceStream)) { diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index 372b412fc00..d44a5bd01b2 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -5,6 +5,7 @@ $TRANSLATIONS = array( "Unknown error" => "Erro Desconhecido", "Could not move %s - File with this name already exists" => "Não foi possível mover %s - Já existe um ficheiro com este nome", "Could not move %s" => "Não foi possível mover %s", +"Permission denied" => "Permissão negada", "File name cannot be empty." => "O nome do ficheiro não pode estar em branco.", "\"%s\" is an invalid file name." => "\"%s\" é um nome de ficheiro inválido.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome Inválido, Não são permitidos os carateres '\\', '/', '<', '>', ':', '\"', '|', '?' e '*'.", diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index a6b4882083b..e004d4a1d63 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -191,13 +191,12 @@ class Hooks { if (Crypt::mode() === 'server') {
$view = new \OC\Files\View('/');
+ $session = new \OCA\Encryption\Session($view);
- if ($params['uid'] === \OCP\User::getUser()) {
+ // Get existing decrypted private key
+ $privateKey = $session->getPrivateKey();
- $session = new \OCA\Encryption\Session($view);
-
- // Get existing decrypted private key
- $privateKey = $session->getPrivateKey();
+ if ($params['uid'] === \OCP\User::getUser() && $privateKey) {
// Encrypt private key with new user pwd as passphrase
$encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password'], Helper::getCipher());
@@ -524,7 +523,13 @@ class Hooks { $newKeyfilePath .= '.key';
// handle share-keys
- $matches = Helper::findShareKeys($oldShareKeyPath, $view);
+ $matches = Helper::findShareKeys($pathOld, $oldShareKeyPath, $view);
+ if (count($matches) === 0) {
+ \OC_Log::write(
+ 'Encryption library', 'No share keys found for "' . $pathOld . '"',
+ \OC_Log::WARN
+ );
+ }
foreach ($matches as $src) {
$dst = \OC\Files\Filesystem::normalizePath(str_replace($pathOld, $pathNew, $src));
$view->$operation($src, $dst);
diff --git a/apps/files_encryption/l10n/bn_BD.php b/apps/files_encryption/l10n/bn_BD.php index 8d034c83a15..3d4c848d6ef 100644 --- a/apps/files_encryption/l10n/bn_BD.php +++ b/apps/files_encryption/l10n/bn_BD.php @@ -9,6 +9,7 @@ $TRANSLATIONS = array( "Initial encryption running... Please try again later." => "প্রাথমিক এনক্রিপসন চলছে.... দয়া করে পরে আবার চেষ্টা করুন।", "Go directly to your %spersonal settings%s." => "সরাসরি আপনার %spersonal settings%s এ যান।", "Encryption" => "সংকেতায়ন", +"Repeat Recovery key password" => "পূণরূদ্ধার কি এর কুটশব্দ পূণরায় দিন", "Enabled" => "কার্যকর", "Disabled" => "অকার্যকর", "Change recovery key password:" => "পূণরূদ্ধার কি এর কুটশব্দ পরিবর্তন করুন:", diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index d427c51732f..ab19938d633 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -431,24 +431,40 @@ class Helper { /** * find all share keys for a given file - * @param string $path to the file - * @param \OC\Files\View $view view, relative to data/ - * @return array list of files, path relative to data/ + * + * @param string $filePath path to the file name relative to the user's files dir + * for example "subdir/filename.txt" + * @param string $shareKeyPath share key prefix path relative to the user's data dir + * for example "user1/files_encryption/share-keys/subdir/filename.txt" + * @param \OC\Files\View $rootView root view, relative to data/ + * @return array list of share key files, path relative to data/$user */ - public static function findShareKeys($path, $view) { + public static function findShareKeys($filePath, $shareKeyPath, $rootView) { $result = array(); - $pathinfo = pathinfo($path); - $dirContent = $view->opendir($pathinfo['dirname']); - - if (is_resource($dirContent)) { - while (($file = readdir($dirContent)) !== false) { - if (!\OC\Files\Filesystem::isIgnoredDir($file)) { - if (preg_match("/" . $pathinfo['filename'] . ".(.*).shareKey/", $file)) { - $result[] = $pathinfo['dirname'] . '/' . $file; - } - } + + $user = \OCP\User::getUser(); + $util = new Util($rootView, $user); + // get current sharing state + $sharingEnabled = \OCP\Share::isEnabled(); + + // get users sharing this file + $usersSharing = $util->getSharingUsersArray($sharingEnabled, $filePath); + + $pathinfo = pathinfo($shareKeyPath); + + $baseDir = $pathinfo['dirname'] . '/'; + $fileName = $pathinfo['basename']; + foreach ($usersSharing as $user) { + $keyName = $fileName . '.' . $user . '.shareKey'; + if ($rootView->file_exists($baseDir . $keyName)) { + $result[] = $baseDir . $keyName; + } else { + \OC_Log::write( + 'Encryption library', + 'No share key found for user "' . $user . '" for file "' . $pathOld . '"', + \OC_Log::WARN + ); } - closedir($dirContent); } return $result; diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 931469f4b74..9560126ef33 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -459,13 +459,17 @@ class Keymanager { \OCP\Util::writeLog('files_encryption', 'delAllShareKeys: delete share keys: ' . $baseDir . $filePath, \OCP\Util::DEBUG); $result = $view->unlink($baseDir . $filePath); } else { - $parentDir = dirname($baseDir . $filePath); - $filename = pathinfo($filePath, PATHINFO_BASENAME); - foreach($view->getDirectoryContent($parentDir) as $content) { - $path = $content['path']; - if (self::getFilenameFromShareKey($content['name']) === $filename) { - \OCP\Util::writeLog('files_encryption', 'dellAllShareKeys: delete share keys: ' . '/' . $userId . '/' . $path, \OCP\Util::DEBUG); - $result &= $view->unlink('/' . $userId . '/' . $path); + $sharingEnabled = \OCP\Share::isEnabled(); + $users = $util->getSharingUsersArray($sharingEnabled, $filePath); + foreach($users as $user) { + $keyName = $baseDir . $filePath . '.' . $user . '.shareKey'; + if ($view->file_exists($keyName)) { + \OCP\Util::writeLog( + 'files_encryption', + 'dellAllShareKeys: delete share keys: "' . $keyName . '"', + \OCP\Util::DEBUG + ); + $result &= $view->unlink($keyName); } } } @@ -539,17 +543,20 @@ class Keymanager { if ($view->is_dir($dir . '/' . $file)) { self::recursiveDelShareKeys($dir . '/' . $file, $userIds, $owner, $view); } else { - $realFile = $realFileDir . self::getFilenameFromShareKey($file); foreach ($userIds as $userId) { - if (preg_match("/(.*)." . $userId . ".shareKey/", $file)) { - if ($userId === $owner && - $view->file_exists($realFile)) { - \OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR); - continue; - } - \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); - $view->unlink($dir . '/' . $file); + $fileNameFromShareKey = self::getFilenameFromShareKey($file, $userId); + if (!$fileNameFromShareKey) { + continue; } + $realFile = $realFileDir . $fileNameFromShareKey; + + if ($userId === $owner && + $view->file_exists($realFile)) { + \OCP\Util::writeLog('files_encryption', 'original file still exists, keep owners share key!', \OCP\Util::ERROR); + continue; + } + \OCP\Util::writeLog('files_encryption', 'recursiveDelShareKey: delete share key: ' . $file, \OCP\Util::DEBUG); + $view->unlink($dir . '/' . $file); } } } @@ -591,16 +598,19 @@ class Keymanager { /** * extract filename from share key name * @param string $shareKey (filename.userid.sharekey) + * @param string $userId * @return string|false filename or false */ - protected static function getFilenameFromShareKey($shareKey) { - $parts = explode('.', $shareKey); + protected static function getFilenameFromShareKey($shareKey, $userId) { + $expectedSuffix = '.' . $userId . '.' . 'shareKey'; + $suffixLen = strlen($expectedSuffix); - $filename = false; - if(count($parts) > 2) { - $filename = implode('.', array_slice($parts, 0, count($parts)-2)); + $suffix = substr($shareKey, -$suffixLen); + + if ($suffix !== $expectedSuffix) { + return false; } - return $filename; + return substr($shareKey, 0, -$suffixLen); } } diff --git a/apps/files_encryption/tests/helper.php b/apps/files_encryption/tests/helper.php index 582d8149a8a..b94fdeb4d6c 100644 --- a/apps/files_encryption/tests/helper.php +++ b/apps/files_encryption/tests/helper.php @@ -108,4 +108,60 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase { \Test_Encryption_Util::loginHelper(\Test_Encryption_Helper::TEST_ENCRYPTION_HELPER_USER1); } + function userNamesProvider() { + return array( + array('testuser' . uniqid()), + array('user.name.with.dots'), + ); + } + + /** + * Tests whether share keys can be found + * + * @dataProvider userNamesProvider + */ + function testFindShareKeys($userName) { + // note: not using dataProvider as we want to make + // sure that the correct keys are match and not any + // other ones that might happen to have similar names + \Test_Encryption_Util::setupHooks(); + \Test_Encryption_Util::loginHelper($userName, true); + $testDir = 'testFindShareKeys' . uniqid() . '/'; + $baseDir = $userName . '/files/' . $testDir; + $fileList = array( + 't est.txt', + 't est_.txt', + 't est.doc.txt', + 't est(.*).txt', // make sure the regexp is escaped + 'multiple.dots.can.happen.too.txt', + 't est.' . $userName . '.txt', + 't est_.' . $userName . '.shareKey.txt', + 'who would upload their.shareKey', + 'user ones file.txt', + 'user ones file.txt.backup', + '.t est.txt' + ); + + $rootView = new \OC\Files\View('/'); + $rootView->mkdir($baseDir); + foreach ($fileList as $fileName) { + $rootView->file_put_contents($baseDir . $fileName, 'dummy'); + } + + $shareKeysDir = $userName . '/files_encryption/share-keys/' . $testDir; + foreach ($fileList as $fileName) { + // make sure that every file only gets its correct respective keys + $result = Encryption\Helper::findShareKeys($baseDir . $fileName, $shareKeysDir . $fileName, $rootView); + $this->assertEquals( + array($shareKeysDir . $fileName . '.' . $userName . '.shareKey'), + $result + ); + } + + // clean up + $rootView->unlink($baseDir); + \Test_Encryption_Util::logoutHelper(); + \OC_User::deleteUser($userName); + } + } diff --git a/apps/files_encryption/tests/hooks.php b/apps/files_encryption/tests/hooks.php index cc5b6d5b6f6..14d44fe5bb3 100644 --- a/apps/files_encryption/tests/hooks.php +++ b/apps/files_encryption/tests/hooks.php @@ -36,8 +36,8 @@ use OCA\Encryption; */ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { - const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1"; - const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2"; + const TEST_ENCRYPTION_HOOKS_USER1 = "test-encryption-hooks-user1.dot"; + const TEST_ENCRYPTION_HOOKS_USER2 = "test-encryption-hooks-user2.dot"; /** * @var \OC\Files\View @@ -49,7 +49,26 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { public $filename; public $folder; + private static $testFiles; + public static function setUpBeforeClass() { + // note: not using a data provider because these + // files all need to coexist to make sure the + // share keys are found properly (pattern matching) + self::$testFiles = array( + 't est.txt', + 't est_.txt', + 't est.doc.txt', + 't est(.*).txt', // make sure the regexp is escaped + 'multiple.dots.can.happen.too.txt', + 't est.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.txt', + 't est_.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey.txt', + 'who would upload their.shareKey', + 'user ones file.txt', + 'user ones file.txt.backup', + '.t est.txt' + ); + // reset backend \OC_User::clearBackends(); \OC_User::useBackend('database'); @@ -281,25 +300,33 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { } } - /** - * test rename operation - */ function testRenameHook() { + // create all files to make sure all keys can coexist properly + foreach (self::$testFiles as $file) { + // save file with content + $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $file, $this->data); - // save file with content - $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data); + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + } - // test that data was successfully written - $this->assertTrue(is_int($cryptedFile)); + foreach (self::$testFiles as $file) { + $this->doTestRenameHook($file); + } + } + /** + * test rename operation + */ + function doTestRenameHook($filename) { // check if keys exists $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' - . $this->filename . '.key')); + . $filename . '.key')); // make subfolder and sub-subfolder $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); @@ -310,50 +337,58 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { // move the file to the sub-subfolder $root = $this->rootView->getRoot(); $this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/'); - $this->rootView->rename($this->filename, '/' . $this->folder . '/' . $this->folder . '/' . $this->filename); + $this->rootView->rename($filename, '/' . $this->folder . '/' . $this->folder . '/' . $filename); $this->rootView->chroot($root); - $this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename)); - $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $this->filename)); + $this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename)); + $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $filename)); // keys should be renamed too $this->assertFalse($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertFalse($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' - . $this->filename . '.key')); + . $filename . '.key')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' . $this->folder . '/' - . $this->filename . '.key')); + . $filename . '.key')); // cleanup $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); } - /** - * test rename operation - */ function testCopyHook() { + // create all files to make sure all keys can coexist properly + foreach (self::$testFiles as $file) { + // save file with content + $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $file, $this->data); - // save file with content - $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data); + // test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + } - // test that data was successfully written - $this->assertTrue(is_int($cryptedFile)); + foreach (self::$testFiles as $file) { + $this->doTestCopyHook($file); + } + } + /** + * test rename operation + */ + function doTestCopyHook($filename) { // check if keys exists $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' - . $this->filename . '.key')); + . $filename . '.key')); // make subfolder and sub-subfolder $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); @@ -362,29 +397,29 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase { $this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder)); // copy the file to the sub-subfolder - \OC\Files\Filesystem::copy($this->filename, '/' . $this->folder . '/' . $this->folder . '/' . $this->filename); + \OC\Files\Filesystem::copy($filename, '/' . $this->folder . '/' . $this->folder . '/' . $filename); - $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename)); - $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $this->filename)); + $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename)); + $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $filename)); // keys should be copied too $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' - . $this->filename . '.key')); + . $filename . '.key')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/' - . $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); + . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' . $this->folder . '/' - . $this->filename . '.key')); + . $filename . '.key')); // cleanup $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); - $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename); + $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename); } /** diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index f90832280a2..e8a9d7dda53 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -23,7 +23,7 @@ use OCA\Encryption; */ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { - const TEST_USER = "test-keymanager-user"; + const TEST_USER = "test-keymanager-user.dot"; public $userId; public $pass; @@ -135,15 +135,25 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->assertArrayHasKey('key', $sslInfo); } + function fileNameFromShareKeyProvider() { + return array( + array('file.user.shareKey', 'user', 'file'), + array('file.name.with.dots.user.shareKey', 'user', 'file.name.with.dots'), + array('file.name.user.with.dots.shareKey', 'user.with.dots', 'file.name'), + array('file.txt', 'user', false), + array('user.shareKey', 'user', false), + ); + } + /** * @small + * + * @dataProvider fileNameFromShareKeyProvider */ - 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")); + function testGetFilenameFromShareKey($fileName, $user, $expectedFileName) { + $this->assertEquals($expectedFileName, + \TestProtectedKeymanagerMethods::testGetFilenameFromShareKey($fileName, $user) + ); } /** @@ -249,6 +259,12 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user1.shareKey', 'data'); $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data'); $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.test.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.test-keymanager-userxdot.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.userx.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.userx.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey', 'data'); + $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.user1.shareKey', 'data'); $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user2.shareKey', 'data'); $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file2.user3.shareKey', 'data'); $this->view->file_put_contents('/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/file2.user3.shareKey', 'data'); @@ -279,6 +295,23 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/subfolder/file2.user3.shareKey')); + // check if share keys for user or file with similar name + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.test.shareKey')); + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.test-keymanager-userxdot.shareKey')); + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.userx.shareKey')); + // FIXME: this case currently cannot be distinguished, needs further fixing + /* + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.userx.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.user1.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); + $this->assertTrue($this->view->file_exists( + '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/file1.' . Test_Encryption_Keymanager::TEST_USER . '.user1.shareKey')); + */ + // owner key from existing file should still exists because the file is still there $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); @@ -432,18 +465,19 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/existingFile.txt.user3.shareKey')); - // try to del all share keys froma file, should fail because the file still exists + // try to del all share keys from file, should succeed because the does not exist any more $result2 = Encryption\Keymanager::delAllShareKeys($this->view, Test_Encryption_Keymanager::TEST_USER, 'folder1/nonexistingFile.txt'); $this->assertTrue($result2); // check if share keys are really gone $this->assertFalse($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.' . Test_Encryption_Keymanager::TEST_USER . '.shareKey')); - $this->assertFalse($this->view->file_exists( + // check that it only deleted keys or users who had access, others remain + $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user1.shareKey')); - $this->assertFalse($this->view->file_exists( + $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user2.shareKey')); - $this->assertFalse($this->view->file_exists( + $this->assertTrue($this->view->file_exists( '/'.Test_Encryption_Keymanager::TEST_USER.'/files_encryption/share-keys/folder1/nonexistingFile.txt.user3.shareKey')); // cleanup @@ -479,8 +513,8 @@ class TestProtectedKeymanagerMethods extends \OCA\Encryption\Keymanager { /** * @param string $sharekey */ - public static function testGetFilenameFromShareKey($sharekey) { - return self::getFilenameFromShareKey($sharekey); + public static function testGetFilenameFromShareKey($sharekey, $user) { + return self::getFilenameFromShareKey($sharekey, $user); } /** diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 1f1304bb527..1cd7cfc738b 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -1058,9 +1058,66 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { // check if additional share key for user2 exists $this->assertTrue($view->file_exists('files_encryption/share-keys' . $newFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + // check that old keys were removed/moved properly + $this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + // tear down \OC\Files\Filesystem::unlink($newFolder); \OC\Files\Filesystem::unlink('/newfolder'); } + function testMoveFileToFolder() { + + $view = new \OC\Files\View('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1); + + $filename = '/tmp-' . uniqid(); + $folder = '/folder' . uniqid(); + + \OC\Files\Filesystem::mkdir($folder); + + // Save long data as encrypted file using stream wrapper + $cryptedFile = \OC\Files\Filesystem::file_put_contents($folder . $filename, $this->dataShort); + + // Test that data was successfully written + $this->assertTrue(is_int($cryptedFile)); + + // Get file decrypted contents + $decrypt = \OC\Files\Filesystem::file_get_contents($folder . $filename); + + $this->assertEquals($this->dataShort, $decrypt); + + $subFolder = $folder . '/subfolder' . uniqid(); + \OC\Files\Filesystem::mkdir($subFolder); + + // get the file info from previous created file + $fileInfo = \OC\Files\Filesystem::getFileInfo($folder); + $this->assertTrue($fileInfo instanceof \OC\Files\FileInfo); + + // share the folder + \OCP\Share::shareItem('folder', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL); + + // check that the share keys exist + $this->assertTrue($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey')); + $this->assertTrue($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + + // move the file into the subfolder + \OC\Files\Filesystem::rename($folder . $filename, $subFolder . $filename); + + // Get file decrypted contents + $newDecrypt = \OC\Files\Filesystem::file_get_contents($subFolder . $filename); + $this->assertEquals($this->dataShort, $newDecrypt); + + // check if additional share key for user2 exists + $this->assertTrue($view->file_exists('files_encryption/share-keys' . $subFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey')); + $this->assertTrue($view->file_exists('files_encryption/share-keys' . $subFolder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + + // check that old keys were removed/moved properly + $this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '.shareKey')); + $this->assertFalse($view->file_exists('files_encryption/share-keys' . $folder . '/' . $filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey')); + + // tear down + \OC\Files\Filesystem::unlink($subFolder); + \OC\Files\Filesystem::unlink($folder); + } + } diff --git a/apps/files_encryption/tests/trashbin.php b/apps/files_encryption/tests/trashbin.php index a5479de1b8d..ae0974431be 100755 --- a/apps/files_encryption/tests/trashbin.php +++ b/apps/files_encryption/tests/trashbin.php @@ -120,24 +120,33 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { // generate filename $filename = 'tmp-' . uniqid() . '.txt'; + $filename2 = $filename . '.backup'; // a second file with similar name // save file with content $cryptedFile = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort); + $cryptedFile2 = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename2, $this->dataShort); // test that data was successfully written $this->assertTrue(is_int($cryptedFile)); + $this->assertTrue(is_int($cryptedFile2)); // check if key for admin exists $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename . '.key')); + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename2 + . '.key')); // check if share key for admin exists $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' + . $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); - // delete file + // delete first file \OC\FIles\Filesystem::unlink($filename); // check if file not exists @@ -154,6 +163,20 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); + // check that second file still exists + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2)); + + // check that key for second file still exists + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' . $filename2 + . '.key')); + + // check that share key for second file still exists + $this->assertTrue($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' + . $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); + // get files $trashFiles = $this->view->getDirectoryContent( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/'); @@ -179,41 +202,75 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/share-keys/' . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey.' . $trashFileSuffix)); - - // return filename for next test - return $filename . '.' . $trashFileSuffix; } /** * @medium * test restore file - * - * @depends testDeleteFile */ - function testRestoreFile($filename) { + function testRestoreFile() { + // generate filename + $filename = 'tmp-' . uniqid() . '.txt'; + $filename2 = $filename . '.backup'; // a second file with similar name + + // save file with content + $cryptedFile = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename, $this->dataShort); + $cryptedFile2 = file_put_contents('crypt:///' .\Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1. '/files/'. $filename2, $this->dataShort); + + // delete both files + \OC\Files\Filesystem::unlink($filename); + \OC\Files\Filesystem::unlink($filename2); + + $trashFiles = $this->view->getDirectoryContent( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_trashbin/files/'); + + $trashFileSuffix = null; + $trashFileSuffix2 = null; + // find created file with timestamp + foreach ($trashFiles as $file) { + if (strncmp($file['path'], $filename, strlen($filename))) { + $path_parts = pathinfo($file['name']); + $trashFileSuffix = $path_parts['extension']; + } + if (strncmp($file['path'], $filename2, strlen($filename2))) { + $path_parts = pathinfo($file['name']); + $trashFileSuffix2 = $path_parts['extension']; + } + } // prepare file information - $path_parts = pathinfo($filename); - $trashFileSuffix = $path_parts['extension']; $timestamp = str_replace('d', '', $trashFileSuffix); - $fileNameWithoutSuffix = str_replace('.' . $trashFileSuffix, '', $filename); - // restore file - $this->assertTrue(\OCA\Files_Trashbin\Trashbin::restore($filename, $fileNameWithoutSuffix, $timestamp)); + // restore first file + $this->assertTrue(\OCA\Files_Trashbin\Trashbin::restore($filename . '.' . $trashFileSuffix, $filename, $timestamp)); // check if file exists $this->assertTrue($this->view->file_exists( - '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $fileNameWithoutSuffix)); + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename)); // check if key for admin exists $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' - . $fileNameWithoutSuffix . '.key')); + . $filename . '.key')); // check if share key for admin exists $this->assertTrue($this->view->file_exists( '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' - . $fileNameWithoutSuffix . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); + . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); + + // check that second file was NOT restored + $this->assertFalse($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files/' . $filename2)); + + // check if key for admin exists + $this->assertFalse($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/keyfiles/' + . $filename2 . '.key')); + + // check if share key for admin exists + $this->assertFalse($this->view->file_exists( + '/' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '/files_encryption/share-keys/' + . $filename2 . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); } /** @@ -242,7 +299,7 @@ class Test_Encryption_Trashbin extends \PHPUnit_Framework_TestCase { . $filename . '.' . \Test_Encryption_Trashbin::TEST_ENCRYPTION_TRASHBIN_USER1 . '.shareKey')); // delete file - \OC\FIles\Filesystem::unlink($filename); + \OC\Files\Filesystem::unlink($filename); // check if file not exists $this->assertFalse($this->view->file_exists( diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index f2db21be4c2..811530546e8 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -53,12 +53,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { \OC_User::clearBackends(); \OC_User::useBackend('database'); - // Filesystem related hooks - \OCA\Encryption\Helper::registerFilesystemHooks(); - - // clear and register hooks - \OC_FileProxy::clearProxies(); - \OC_FileProxy::register(new OCA\Encryption\Proxy()); + self::setupHooks(); // create test user \Test_Encryption_Util::loginHelper(\Test_Encryption_Util::TEST_ENCRYPTION_UTIL_USER1, true); @@ -134,6 +129,15 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { \OC_Group::deleteGroup(self::TEST_ENCRYPTION_UTIL_GROUP2); } + public static function setupHooks() { + // Filesystem related hooks + \OCA\Encryption\Helper::registerFilesystemHooks(); + + // clear and register hooks + \OC_FileProxy::clearProxies(); + \OC_FileProxy::register(new OCA\Encryption\Proxy()); + } + /** * @medium * test that paths set during User construction are correct diff --git a/apps/files_sharing/l10n/bn_BD.php b/apps/files_sharing/l10n/bn_BD.php index 5411b5b2785..fdd3f5233bf 100644 --- a/apps/files_sharing/l10n/bn_BD.php +++ b/apps/files_sharing/l10n/bn_BD.php @@ -15,6 +15,7 @@ $TRANSLATIONS = array( "Password" => "কূটশব্দ", "Name" => "নাম", "Share time" => "ভাগাভাগির সময়", +"Sorry, this link doesn’t seem to work anymore." => "দুঃখিত, এই লিঙ্কটি আর কার্যকর নয়।", "Reasons might be:" => "কারণসমূহ হতে পারে:", "the item was removed" => "আইটেমটি অপসারণ করা হয়েছিল", "the link expired" => "মেয়াদোত্তীর্ন লিঙ্ক", diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index ca7e58d93bd..3fe0ef0b7de 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -318,12 +318,8 @@ class Trashbin { } $rootView->rename($sharekeys, $user . '/files_trashbin/share-keys/' . $filename . '.d' . $timestamp); } else { - // get local path to share-keys - $localShareKeysPath = $rootView->getLocalFile($sharekeys); - $escapedLocalShareKeysPath = preg_replace('/(\*|\?|\[)/', '[$1]', $localShareKeysPath); - // handle share-keys - $matches = glob($escapedLocalShareKeysPath . '*.shareKey'); + $matches = \OCA\Encryption\Helper::findShareKeys($ownerPath, $sharekeys, $rootView); foreach ($matches as $src) { // get source file parts $pathinfo = pathinfo($src); diff --git a/autotest.sh b/autotest.sh index d6b975c62d2..e86240e4e56 100755 --- a/autotest.sh +++ b/autotest.sh @@ -26,12 +26,12 @@ function print_syntax { echo -e "\nIf no arguments are specified, all tests will be run with all database configs" >&2 } -if ! [ -x $PHPUNIT ]; then +if ! [ -x "$PHPUNIT" ]; then echo "phpunit executable not found, please install phpunit version >= 3.7" >&2 exit 3 fi -PHPUNIT_VERSION=$($PHPUNIT --version | cut -d" " -f2) +PHPUNIT_VERSION=$("$PHPUNIT" --version | cut -d" " -f2) PHPUNIT_MAJOR_VERSION=$(echo $PHPUNIT_VERSION | cut -d"." -f1) PHPUNIT_MINOR_VERSION=$(echo $PHPUNIT_VERSION | cut -d"." -f2) @@ -45,10 +45,10 @@ if ! [ -w config -a -w config/config.php ]; then exit 1 fi -if [ $1 ]; then +if [ "$1" ]; then FOUND=0 for DBCONFIG in $DBCONFIGS; do - if [ $1 = $DBCONFIG ]; then + if [ "$1" = $DBCONFIG ]; then FOUND=1 break fi @@ -148,14 +148,14 @@ DELIM function execute_tests { echo "Setup environment for $1 testing ..." # back to root folder - cd $BASEDIR + cd "$BASEDIR" # revert changes to tests/data git checkout tests/data # reset data directory - rm -rf $DATADIR - mkdir $DATADIR + rm -rf "$DATADIR" + mkdir "$DATADIR" # remove the old config file #rm -rf config/config.php @@ -194,7 +194,7 @@ EOF fi # copy autoconfig - cp $BASEDIR/tests/autoconfig-$1.php $BASEDIR/config/autoconfig.php + cp "$BASEDIR/tests/autoconfig-$1.php" "$BASEDIR/config/autoconfig.php" # trigger installation echo "INDEX" @@ -204,15 +204,15 @@ EOF #test execution echo "Testing with $1 ..." cd tests - rm -rf coverage-html-$1 - mkdir coverage-html-$1 + rm -rf "coverage-html-$1" + mkdir "coverage-html-$1" php -f enable_all.php | grep -i -C9999 error && echo "Error during setup" && exit 101 if [ -z "$NOCOVERAGE" ]; then - $PHPUNIT --configuration phpunit-autotest.xml --log-junit autotest-results-$1.xml --coverage-clover autotest-clover-$1.xml --coverage-html coverage-html-$1 $2 $3 + "$PHPUNIT" --configuration phpunit-autotest.xml --log-junit "autotest-results-$1.xml" --coverage-clover "autotest-clover-$1.xml" --coverage-html "coverage-html-$1" "$2" "$3" RESULT=$? else echo "No coverage" - $PHPUNIT --configuration phpunit-autotest.xml --log-junit autotest-results-$1.xml $2 $3 + "$PHPUNIT" --configuration phpunit-autotest.xml --log-junit "autotest-results-$1.xml" "$2" "$3" RESULT=$? fi } @@ -227,10 +227,10 @@ if [ -z "$1" ] execute_tests $DBCONFIG done else - execute_tests $1 $2 $3 + execute_tests "$1" "$2" "$3" fi -cd $BASEDIR +cd "$BASEDIR" restore_config # diff --git a/config/config.sample.php b/config/config.sample.php index 879ba9e9d01..8d9bb975662 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -282,7 +282,30 @@ $CONFIG = array( /* custom path for libreoffice / openoffice binary */ 'preview_libreoffice_path' => '/usr/bin/libreoffice', /* cl parameters for libreoffice / openoffice */ -'preview_office_cl_parameters' => '', +'preview_office_cl_parameters' => ' --headless --nologo --nofirststartwizard --invisible --norestore -convert-to pdf -outdir ', + +/** + * Only register providers that have been explicitly enabled + * + * The following providers are enabled by default: + * - OC\Preview\Image + * - OC\Preview\MP3 + * - OC\Preview\TXT + * - OC\Preview\MarkDown + * + * The following providers are disabled by default due to performance or privacy concerns: + * - OC\Preview\Office + * - OC\Preview\SVG + * - OC\Preview\Movies + * - OC\Preview\PDF + * - OC\Preview\Tiff + */ +'enabledPreviewProviders' => array( + 'OC\Preview\Image', + 'OC\Preview\MP3', + 'OC\Preview\TXT', + 'OC\Preview\MarkDown' +), /* whether avatars should be enabled */ 'enable_avatars' => true, diff --git a/core/l10n/en_GB.php b/core/l10n/en_GB.php index b4aa17e2f3f..03b48abe943 100644 --- a/core/l10n/en_GB.php +++ b/core/l10n/en_GB.php @@ -140,6 +140,9 @@ $TRANSLATIONS = array( "Error favoriting" => "Error favouriting", "Error unfavoriting" => "Error unfavouriting", "Access forbidden" => "Access denied", +"File not found" => "File not found", +"The specified document has not been found on the server." => "The specified document has not been found on the server.", +"You can click here to return to %s." => "You can click here to return to %s.", "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" => "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n", "The share will expire on %s." => "The share will expire on %s.", "Cheers!" => "Cheers!", @@ -185,6 +188,8 @@ $TRANSLATIONS = array( "The theme %s has been disabled." => "The theme %s has been disabled.", "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." => "Please make sure that the database, the config folder and the data folder have been backed up before proceeding.", "Start update" => "Start update", -"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" => "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" +"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" => "To avoid timeouts with larger installations, you can instead run the following command from your installation directory:", +"This %s instance is currently being updated, which may take a while." => "This %s instance is currently being updated, which may take a while.", +"This page will refresh itself when the %s instance is available again." => "This page will refresh itself when the %s instance is available again." ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/l10n/fr.php b/core/l10n/fr.php index 5460ab79f0d..493f26f2d47 100644 --- a/core/l10n/fr.php +++ b/core/l10n/fr.php @@ -5,6 +5,8 @@ $TRANSLATIONS = array( "Turned off maintenance mode" => "Basculé en mode production (non maintenance)", "Updated database" => "Base de données mise à jour", "Checked database schema update" => "Mise à jour du schéma de la base de données vérifiée", +"Checked database schema update for apps" => "La mise à jour du schéma de la base de données pour les applications a été vérifiée", +"Updated \"%s\" to %s" => "Mise à jour de \"%s\" à %s", "Disabled incompatible apps: %s" => "Applications incompatibles désactivées: %s", "No image or file provided" => "Aucune image ou fichier fourni", "Unknown filetype" => "Type de fichier inconnu", @@ -138,6 +140,9 @@ $TRANSLATIONS = array( "Error favoriting" => "Erreur lors de la mise en favori", "Error unfavoriting" => "Erreur lors de la suppression des favoris", "Access forbidden" => "Accès interdit", +"File not found" => "Fichier non trouvé", +"The specified document has not been found on the server." => "Le document spécifié n'a pu être trouvé sur le serveur.", +"You can click here to return to %s." => "Vous pouvez cliquer ici pour retourner à %s.", "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" => "Bonjour,\n\nNous vous informons que %s a partagé %s avec vous.\nConsultez-le : %s\n", "The share will expire on %s." => "Le partage expirera le %s.", "Cheers!" => "À bientôt !", diff --git a/core/l10n/pt_PT.php b/core/l10n/pt_PT.php index 3033d62a30a..568499ab2f4 100644 --- a/core/l10n/pt_PT.php +++ b/core/l10n/pt_PT.php @@ -140,6 +140,9 @@ $TRANSLATIONS = array( "Error favoriting" => "Erro a definir como favorito", "Error unfavoriting" => "Erro a remover como favorito", "Access forbidden" => "Acesso interdito", +"File not found" => "Ficheiro não encontrado", +"The specified document has not been found on the server." => "O documento especificado não foi encontrado no servidor.", +"You can click here to return to %s." => "Pode clicar aqui para retornar para %s.", "Hey there,\n\njust letting you know that %s shared %s with you.\nView it: %s\n\n" => "Olá,\n\napenas para informar que %s partilhou »%s« consigo.\nConsulte aqui: %s\n", "The share will expire on %s." => "Esta partilha vai expirar em %s.", "Cheers!" => "Parabéns!", @@ -185,6 +188,8 @@ $TRANSLATIONS = array( "The theme %s has been disabled." => "O tema %s foi desativado.", "Please make sure that the database, the config folder and the data folder have been backed up before proceeding." => "Por favor garanta a cópia de segurança da base de dados e das pastas 'config' e 'data' antes de prosseguir.", "Start update" => "Iniciar atualização", -"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" => "Para evitar tempos de espera com instalações maiores, você pode em vez disso, executar o seguinte comando a partir do diretório de instalação:" +"To avoid timeouts with larger installations, you can instead run the following command from your installation directory:" => "Para evitar tempos de espera com instalações maiores, você pode em vez disso, executar o seguinte comando a partir do diretório de instalação:", +"This %s instance is currently being updated, which may take a while." => "Esta instância %s está actualmente a ser actualizada, poderá demorar algum tempo.", +"This page will refresh itself when the %s instance is available again." => "Esta página irá ser recarregada novamente quando a instância %s ficar novamente disponível." ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/core/routes.php b/core/routes.php index fac67f23175..a9d5387bc14 100644 --- a/core/routes.php +++ b/core/routes.php @@ -20,9 +20,6 @@ $application->registerRoutes($this, array('routes' => array( // Post installation check /** @var $this OCP\Route\IRouter */ -$this->create('post_setup_check', '/post-setup-check') - ->action('OC_Setup', 'postSetupCheck'); - // Core ajax actions // Search $this->create('search_ajax_search', '/search/ajax/search.php') diff --git a/core/setup/controller.php b/core/setup/controller.php index 5da94e83ccc..02226ad9e42 100644 --- a/core/setup/controller.php +++ b/core/setup/controller.php @@ -22,12 +22,10 @@ class Controller { if(count($e) > 0) { $options = array_merge($opts, $post, $errors); $this->display($options); - } - else { + } else { $this->finishSetup(); } - } - else { + } else { $options = array_merge($opts, $post); $this->display($options); } @@ -53,8 +51,7 @@ class Controller { } public function finishSetup() { - header( 'Location: '.\OC_Helper::linkToRoute( 'post_setup_check' )); - exit(); + \OC_Util::redirectToDefaultPage(); } public function loadAutoConfig($post) { diff --git a/l10n/templates/core.pot b/l10n/templates/core.pot index d751cec8db4..e6ad633a86b 100644 --- a/l10n/templates/core.pot +++ b/l10n/templates/core.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/files.pot b/l10n/templates/files.pot index 2cdf2d4e7e1..4932617dc86 100644 --- a/l10n/templates/files.pot +++ b/l10n/templates/files.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/files_encryption.pot b/l10n/templates/files_encryption.pot index 45ee9751c03..3a02d45e59c 100644 --- a/l10n/templates/files_encryption.pot +++ b/l10n/templates/files_encryption.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/files_external.pot b/l10n/templates/files_external.pot index c4ee5c65556..ec0a6052e4b 100644 --- a/l10n/templates/files_external.pot +++ b/l10n/templates/files_external.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/files_sharing.pot b/l10n/templates/files_sharing.pot index 2ab7cf95612..503dae723f6 100644 --- a/l10n/templates/files_sharing.pot +++ b/l10n/templates/files_sharing.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/files_trashbin.pot b/l10n/templates/files_trashbin.pot index 40b12a7b9b6..641aecc7e2d 100644 --- a/l10n/templates/files_trashbin.pot +++ b/l10n/templates/files_trashbin.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -39,7 +39,7 @@ msgstr "" msgid "Error" msgstr "" -#: lib/trashbin.php:940 lib/trashbin.php:942 +#: lib/trashbin.php:966 lib/trashbin.php:968 msgid "restored" msgstr "" diff --git a/l10n/templates/files_versions.pot b/l10n/templates/files_versions.pot index cd62beb6507..c841a4b6452 100644 --- a/l10n/templates/files_versions.pot +++ b/l10n/templates/files_versions.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/lib.pot b/l10n/templates/lib.pot index bf8a965cf5a..e37cdebb4c9 100644 --- a/l10n/templates/lib.pot +++ b/l10n/templates/lib.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:04-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/private.pot b/l10n/templates/private.pot index fb8ed2a6268..234e1494fca 100644 --- a/l10n/templates/private.pot +++ b/l10n/templates/private.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:04-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/settings.pot b/l10n/templates/settings.pot index a82506faea8..2d1bcd0918b 100644 --- a/l10n/templates/settings.pot +++ b/l10n/templates/settings.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:04-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/user_ldap.pot b/l10n/templates/user_ldap.pot index 1223abc4ea5..a4e9433c881 100644 --- a/l10n/templates/user_ldap.pot +++ b/l10n/templates/user_ldap.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/l10n/templates/user_webdavauth.pot b/l10n/templates/user_webdavauth.pot index af4478c7432..4f37d64b64d 100644 --- a/l10n/templates/user_webdavauth.pot +++ b/l10n/templates/user_webdavauth.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud Core 6.0.0\n" "Report-Msgid-Bugs-To: translations@owncloud.org\n" -"POT-Creation-Date: 2014-09-22 01:54-0400\n" +"POT-Creation-Date: 2014-09-23 02:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/lib/l10n/bn_BD.php b/lib/l10n/bn_BD.php index 2440616b88d..89149cf96c5 100644 --- a/lib/l10n/bn_BD.php +++ b/lib/l10n/bn_BD.php @@ -17,6 +17,7 @@ $TRANSLATIONS = array( "App directory already exists" => "এই অ্যাপ ডিরেক্টরিটি পূর্ব থেকেই বিদ্যমান", "Can't create app folder. Please fix permissions. %s" => "অ্যাপ ফোল্ডার বানানো হেলনা। অনুমতি নির্ধারণ করুন। %s", "No source specified when installing app" => "অ্যাপ ইনস্টল করতে যেয়ে কোন উৎস নির্দিষ্ট করা হয়নি", +"Failed to open archive when installing app" => "অ্যাপ ইনস্টল করতে যেয়ে আর্কাইভ উম্মুক্তকরণ ব্যার্থ হলো", "App does not provide an info.xml file" => "অ্যাপের সঙ্গে একটি info.xml ফাইল নেই", "App can't be installed because of not allowed code in the App" => "অ্যাপের সাথে অননুমোদিত কোড থাকায় অ্যাপটি ইনস্টল করা যাবেনা", "App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "অ্যাপ ইনস্টল করা যাবেনা কারণ এতে ননশিপড অ্যাপ এর জন্য অননুমোদিত <shipped>true</shipped> ট্যাগ বিদ্যমান ", diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php index 3f1fe6a9925..0c85c7cfe3d 100644 --- a/lib/l10n/fr.php +++ b/lib/l10n/fr.php @@ -4,6 +4,8 @@ $TRANSLATIONS = array( "This can usually be fixed by giving the webserver write access to the config directory" => "Ce problème est généralement résolu en donnant au serveur web un accès en écriture à ce répertoire", "See %s" => "Voir %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." => "Ce problème est généralement résolu %sen donnant au serveur web un accès en écriture au répertoire de configuration%s.", +"Sample configuration detected" => "Configuration d'example détectée", +"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" => "Il a été détecté que le configuration donnée à titre d'exemple a été copiée. Cela peut rendre votre installation inopérante et n'est pas supporté. Veuillez lire la documentation avant d'effectuer des modifications dans config.php", "Help" => "Aide", "Personal" => "Personnel", "Settings" => "Paramètres", diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 9cd7c553f0b..597fbdae0cc 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -192,7 +192,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node throw new \Sabre\DAV\Exception\Forbidden(); } - $this->fileView->rmdir($this->path); + if (!$this->fileView->rmdir($this->path)) { + // assume it wasn't possible to remove due to permission issue + throw new \Sabre\DAV\Exception\Forbidden(); + } } diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 246749903b3..903c3447b56 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -167,7 +167,11 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\ if (!$this->info->isDeletable()) { throw new \Sabre\DAV\Exception\Forbidden(); } - $this->fileView->unlink($this->path); + + if (!$this->fileView->unlink($this->path)) { + // assume it wasn't possible to delete due to permissions + throw new \Sabre\DAV\Exception\Forbidden(); + } // remove properties $this->removeProperties(); diff --git a/lib/private/files/storage/dav.php b/lib/private/files/storage/dav.php index bd7166c9823..a0ef79a7b32 100644 --- a/lib/private/files/storage/dav.php +++ b/lib/private/files/storage/dav.php @@ -177,6 +177,8 @@ class DAV extends \OC\Files\Storage\Common { curl_setopt($curl, CURLOPT_URL, $this->createBaseUri() . $this->encodePath($path)); curl_setopt($curl, CURLOPT_FILE, $fp); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); if ($this->secure === true) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); @@ -282,6 +284,8 @@ class DAV extends \OC\Files\Storage\Common { curl_setopt($curl, CURLOPT_INFILESIZE, filesize($path)); curl_setopt($curl, CURLOPT_PUT, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); if ($this->secure === true) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); diff --git a/lib/private/helper.php b/lib/private/helper.php index f696b5a8900..1297d356d09 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -630,10 +630,10 @@ class OC_Helper { * temporary files are automatically cleaned up after the script is finished */ public static function tmpFolder() { - $path = get_temp_dir() . '/' . md5(time() . rand()); + $path = get_temp_dir() . DIRECTORY_SEPARATOR . md5(time() . rand()); mkdir($path); self::$tmpFiles[] = $path; - return $path . '/'; + return $path . DIRECTORY_SEPARATOR; } /** diff --git a/lib/private/httphelper.php b/lib/private/httphelper.php new file mode 100644 index 00000000000..8b7aebb3d4d --- /dev/null +++ b/lib/private/httphelper.php @@ -0,0 +1,177 @@ +<?php +/** + * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC; + +class HTTPHelper { + const USER_AGENT = 'ownCloud Server Crawler'; + + /** @var \OC\AllConfig */ + private $config; + + /** + * @param \OC\AllConfig $config + */ + public function __construct(AllConfig $config) { + $this->config = $config; + } + + /** + * Returns the default context array + * @return array + */ + public function getDefaultContextArray() { + return array( + 'http' => array( + 'header' => 'User-Agent: ' . self::USER_AGENT . "\r\n", + 'timeout' => 10, + 'follow_location' => false, // Do not follow the location since we can't limit the protocol + ), + 'ssl' => array( + 'disable_compression' => true + ) + ); + } + + /** + * Get URL content + * @param string $url Url to get content + * @throws \Exception If the URL does not start with http:// or https:// + * @return string of the response or false on error + * This function get the content of a page via curl, if curl is enabled. + * If not, file_get_contents is used. + */ + public function getUrlContent($url) { + if (!$this->isHTTPURL($url)) { + throw new \Exception('$url must start with https:// or http://', 1); + } + + $proxy = $this->config->getSystemValue('proxy', null); + $proxyUserPwd = $this->config->getSystemValue('proxyuserpwd', null); + if (function_exists('curl_init')) { + $curl = curl_init(); + $max_redirects = 10; + + curl_setopt($curl, CURLOPT_HEADER, 0); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + + curl_setopt($curl, CURLOPT_USERAGENT, self::USER_AGENT); + if ($proxy !== null) { + curl_setopt($curl, CURLOPT_PROXY, $proxy); + } + if ($proxyUserPwd !== null) { + curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyUserPwd); + } + + if (ini_get('open_basedir') === '' && (ini_get('safe_mode') === false) || strtolower(ini_get('safe_mode')) === 'off') { + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_MAXREDIRS, $max_redirects); + $data = curl_exec($curl); + } else { + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); + $mr = $max_redirects; + if ($mr > 0) { + $newURL = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); + $rcurl = curl_copy_handle($curl); + curl_setopt($rcurl, CURLOPT_HEADER, true); + curl_setopt($rcurl, CURLOPT_NOBODY, true); + curl_setopt($rcurl, CURLOPT_FORBID_REUSE, false); + curl_setopt($rcurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($rcurl, CURLOPT_USERAGENT, self::USER_AGENT); + do { + curl_setopt($rcurl, CURLOPT_URL, $newURL); + $header = curl_exec($rcurl); + if (curl_errno($rcurl)) { + $code = 0; + } else { + $code = curl_getinfo($rcurl, CURLINFO_HTTP_CODE); + if ($code == 301 || $code == 302) { + preg_match('/Location:(.*?)\n/', $header, $matches); + $newURL = trim(array_pop($matches)); + } else { + $code = 0; + } + } + } while ($code && --$mr); + curl_close($rcurl); + if ($mr > 0) { + curl_setopt($curl, CURLOPT_URL, $newURL); + } + } + + if ($mr == 0 && $max_redirects > 0) { + $data = false; + } else { + $data = curl_exec($curl); + } + } + curl_close($curl); + } else { + $url = $this->getFinalLocationOfURL($url); + $contextArray = $this->getDefaultContextArray(); + + if ($proxy !== null) { + $contextArray['http']['proxy'] = $proxy; + } + + $ctx = stream_context_create( + $contextArray + ); + $data = @file_get_contents($url, 0, $ctx); + + } + return $data; + } + + /** + * Returns the response headers of a HTTP URL without following redirects + * @param string $location Needs to be a HTTPS or HTTP URL + * @return array + */ + public function getHeaders($location) { + stream_context_set_default($this->getDefaultContextArray()); + return get_headers($location, 1); + } + + /** + * Checks whether the supplied URL begins with HTTPS:// or HTTP:// (case insensitive) + * @param string $url + * @return bool + */ + public function isHTTPURL($url) { + return stripos($url, 'https://') === 0 || stripos($url, 'http://') === 0; + } + + /** + * Returns the last HTTP or HTTPS site the request has been redirected too using the Location HTTP header + * This is a very ugly workaround about the missing functionality to restrict fopen() to protocols + * @param string $location Needs to be a HTTPS or HTTP URL + * @throws \Exception In case the initial URL is not a HTTP or HTTPS one + * @return string + */ + public function getFinalLocationOfURL($location) { + if(!$this->isHTTPURL($location)) { + throw new \Exception('URL must begin with HTTPS or HTTP.'); + } + $headerArray = $this->getHeaders($location, 1); + + if($headerArray !== false && isset($headerArray['Location'])) { + while($this->isHTTPURL($headerArray['Location'])) { + $location = $headerArray['Location']; + $headerArray = $this->getHeaders($location); + } + } + + return $location; + } + +} diff --git a/lib/private/preview.php b/lib/private/preview.php index b04cc2b8564..9d44d00e686 100755 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -13,7 +13,6 @@ */ namespace OC; -use OC\Files\Filesystem; use OC\Preview\Provider; use OCP\Files\NotFoundException; @@ -23,7 +22,6 @@ require_once 'preview/mp3.php'; require_once 'preview/pdf.php'; require_once 'preview/svg.php'; require_once 'preview/txt.php'; -require_once 'preview/unknown.php'; require_once 'preview/office.php'; require_once 'preview/tiff.php'; @@ -62,6 +60,7 @@ class Preview { //preview providers static private $providers = array(); static private $registeredProviders = array(); + static private $enabledProviders = array(); /** * @var \OCP\Files\FileInfo @@ -669,12 +668,39 @@ class Preview { } /** - * register a new preview provider to be used + * Register a new preview provider to be used + * @param $class * @param array $options - * @return void */ public static function registerProvider($class, $options = array()) { - self::$registeredProviders[] = array('class' => $class, 'options' => $options); + /** + * Only register providers that have been explicitly enabled + * + * The following providers are enabled by default: + * - OC\Preview\Image + * - OC\Preview\MP3 + * - OC\Preview\TXT + * - OC\Preview\MarkDown + * + * The following providers are disabled by default due to performance or privacy concerns: + * - OC\Preview\Office + * - OC\Preview\SVG + * - OC\Preview\Movies + * - OC\Preview\PDF + * - OC\Preview\Tiff + */ + if(empty(self::$enabledProviders)) { + self::$enabledProviders = \OC::$server->getConfig()->getSystemValue('enabledPreviewProviders', array( + 'OC\Preview\Image', + 'OC\Preview\MP3', + 'OC\Preview\TXT', + 'OC\Preview\MarkDown', + )); + } + + if(in_array($class, self::$enabledProviders)) { + self::$registeredProviders[] = array('class' => $class, 'options' => $options); + } } /** @@ -682,9 +708,8 @@ class Preview { * @return void */ private static function initProviders() { - if (!\OC_Config::getValue('enable_previews', true)) { - $provider = new Preview\Unknown(array()); - self::$providers = array($provider->getMimeType() => $provider); + if (!\OC::$server->getConfig()->getSystemValue('enable_previews', true)) { + self::$providers = array(); return; } @@ -698,12 +723,12 @@ class Preview { /** @var $object Provider */ $object = new $class($options); - self::$providers[$object->getMimeType()] = $object; } $keys = array_map('strlen', array_keys(self::$providers)); array_multisort($keys, SORT_DESC, self::$providers); + } public static function post_write($args) { @@ -758,9 +783,7 @@ class Preview { self::initProviders(); } - //remove last element because it has the mimetype * - $providers = array_slice(self::$providers, 0, -1); - foreach ($providers as $supportedMimeType => $provider) { + foreach (self::$providers as $supportedMimeType => $provider) { /** * @var \OC\Preview\Provider $provider */ diff --git a/lib/private/preview/svg.php b/lib/private/preview/svg.php index 82ef3cdebf6..0b5dbc9716f 100644 --- a/lib/private/preview/svg.php +++ b/lib/private/preview/svg.php @@ -31,6 +31,11 @@ if (extension_loaded('imagick')) { $content = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . $content; } + // Do not parse SVG files with references + if(stripos($content, 'xlink:href') !== false) { + return false; + } + $svg->readImageBlob($content); $svg->setImageFormat('png32'); } catch (\Exception $e) { diff --git a/lib/private/preview/unknown.php b/lib/private/preview/unknown.php deleted file mode 100644 index 2d3b5c5655e..00000000000 --- a/lib/private/preview/unknown.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org - * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -namespace OC\Preview; - -class Unknown extends Provider { - - public function getMimeType() { - return '/.*/'; - } - - public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { - $mimetype = $fileview->getMimeType($path); - - $path = \OC_Helper::mimetypeIcon($mimetype); - $path = \OC::$SERVERROOT . substr($path, strlen(\OC::$WEBROOT)); - - $svgPath = substr_replace($path, 'svg', -3); - - if (extension_loaded('imagick') && file_exists($svgPath) && count(@\Imagick::queryFormats("SVG")) === 1) { - - // http://www.php.net/manual/de/imagick.setresolution.php#85284 - $svg = new \Imagick(); - $svg->readImage($svgPath); - $res = $svg->getImageResolution(); - $x_ratio = $res['x'] / $svg->getImageWidth(); - $y_ratio = $res['y'] / $svg->getImageHeight(); - $svg->removeImage(); - $svg->setResolution($maxX * $x_ratio, $maxY * $y_ratio); - $svg->setBackgroundColor(new \ImagickPixel('transparent')); - $svg->readImage($svgPath); - $svg->setImageFormat('png32'); - - $image = new \OC_Image(); - $image->loadFromData($svg); - } else { - $image = new \OC_Image($path); - } - - return $image; - } -} - -\OC\Preview::registerProvider('OC\Preview\Unknown'); diff --git a/lib/private/server.php b/lib/private/server.php index 912d5c4f635..7fa06298b29 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -212,6 +212,10 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('Db', function ($c) { return new Db(); }); + $this->registerService('HTTPHelper', function (SimpleContainer $c) { + $config = $c->query('AllConfig'); + return new HTTPHelper($config); + }); } /** @@ -503,6 +507,14 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Returns an instance of the HTTP helper class + * @return \OC\HTTPHelper + */ + function getHTTPHelper() { + return $this->query('HTTPHelper'); + } + + /** * Get the certificate manager for the user * * @param \OCP\IUser $user (optional) if not specified the current loggedin user is used diff --git a/lib/private/setup.php b/lib/private/setup.php index 95e908d10ec..ccf996460d0 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -1,7 +1,6 @@ <?php -class DatabaseSetupException extends \OC\HintException -{ +class DatabaseSetupException extends \OC\HintException { } class OC_Setup { @@ -162,23 +161,4 @@ class OC_Setup { file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content); file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/index.html', ''); } - - /** - * Post installation checks - */ - public static function postSetupCheck($params) { - // setup was successful -> webdav testing now - $l = self::getTrans(); - if (OC_Util::isWebDAVWorking()) { - header("Location: ".OC::$WEBROOT.'/'); - } else { - - $error = $l->t('Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken.'); - $hint = $l->t('Please double check the <a href=\'%s\'>installation guides</a>.', - \OC_Helper::linkToDocs('admin-install')); - - OC_Template::printErrorPage($error, $hint); - exit(); - } - } } diff --git a/lib/private/user/http.php b/lib/private/user/http.php index 2bb8b4c864a..617e8adb3f2 100644 --- a/lib/private/user/http.php +++ b/lib/private/user/http.php @@ -72,6 +72,8 @@ class OC_User_HTTP extends OC_User_Backend { curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); curl_exec($ch); diff --git a/lib/private/util.php b/lib/private/util.php index c5483c1654b..18857139791 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -5,8 +5,6 @@ * */ class OC_Util { - const USER_AGENT = 'ownCloud Server Crawler'; - public static $scripts = array(); public static $styles = array(); public static $headers = array(); @@ -879,7 +877,7 @@ class OC_Util { $id = OC_Config::getValue('instanceid', null); if (is_null($id)) { // We need to guarantee at least one letter in instanceid so it can be used as the session_name - $id = 'oc' . \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(10); + $id = 'oc' . \OC::$server->getSecureRandom()->getLowStrengthGenerator()->generate(10, \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_DIGITS); OC_Config::$object->setValue('instanceid', $id); } return $id; @@ -1199,106 +1197,20 @@ class OC_Util { } /** - * @Brief Get file content via curl. + * Get URL content * @param string $url Url to get content + * @deprecated Use \OC::$server->getHTTPHelper()->getUrlContent($url); * @throws Exception If the URL does not start with http:// or https:// * @return string of the response or false on error * This function get the content of a page via curl, if curl is enabled. * If not, file_get_contents is used. */ public static function getUrlContent($url) { - if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) { - throw new Exception('$url must start with https:// or http://', 1); - } - - if (function_exists('curl_init')) { - $curl = curl_init(); - $max_redirects = 10; - - curl_setopt($curl, CURLOPT_HEADER, 0); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); - curl_setopt($curl, CURLOPT_URL, $url); - - - curl_setopt($curl, CURLOPT_USERAGENT, self::USER_AGENT); - if (OC_Config::getValue('proxy', '') != '') { - curl_setopt($curl, CURLOPT_PROXY, OC_Config::getValue('proxy')); - } - if (OC_Config::getValue('proxyuserpwd', '') != '') { - curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd')); - } - - if (ini_get('open_basedir') === '' && ini_get('safe_mode') === 'Off') { - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl, CURLOPT_MAXREDIRS, $max_redirects); - $data = curl_exec($curl); - } else { - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false); - $mr = $max_redirects; - if ($mr > 0) { - $newURL = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); - $rcurl = curl_copy_handle($curl); - curl_setopt($rcurl, CURLOPT_HEADER, true); - curl_setopt($rcurl, CURLOPT_NOBODY, true); - curl_setopt($rcurl, CURLOPT_FORBID_REUSE, false); - curl_setopt($rcurl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($rcurl, CURLOPT_USERAGENT, self::USER_AGENT); - do { - curl_setopt($rcurl, CURLOPT_URL, $newURL); - $header = curl_exec($rcurl); - if (curl_errno($rcurl)) { - $code = 0; - } else { - $code = curl_getinfo($rcurl, CURLINFO_HTTP_CODE); - if ($code == 301 || $code == 302) { - preg_match('/Location:(.*?)\n/', $header, $matches); - $newURL = trim(array_pop($matches)); - } else { - $code = 0; - } - } - } while ($code && --$mr); - curl_close($rcurl); - if ($mr > 0) { - curl_setopt($curl, CURLOPT_URL, $newURL); - } - } - - if ($mr == 0 && $max_redirects > 0) { - $data = false; - } else { - $data = curl_exec($curl); - } - } - curl_close($curl); - } else { - $contextArray = null; - - if (OC_Config::getValue('proxy', '') != '') { - $contextArray = array( - 'http' => array( - 'header' => 'User-Agent: ' . self::USER_AGENT . "\r\n", - 'timeout' => 10, - 'proxy' => OC_Config::getValue('proxy') - ) - ); - } else { - $contextArray = array( - 'http' => array( - 'header' => 'User-Agent: ' . self::USER_AGENT . "\r\n", - 'timeout' => 10 - ) - ); - } - - $ctx = stream_context_create( - $contextArray - ); - $data = @file_get_contents($url, 0, $ctx); - + try { + return \OC::$server->getHTTPHelper()->getUrlContent($url); + } catch (\Exception $e) { + throw $e; } - return $data; } /** diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 1abf0d9938d..a093ff3a640 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -242,4 +242,10 @@ interface IServerContainer { * @return \OCP\IEventSource */ function createEventSource(); + + /** + * Returns an instance of the HTTP helper class + * @return \OC\HTTPHelper + */ + function getHTTPHelper(); } diff --git a/settings/l10n/fr.php b/settings/l10n/fr.php index 42cd848597f..9ce50d51d32 100644 --- a/settings/l10n/fr.php +++ b/settings/l10n/fr.php @@ -43,6 +43,7 @@ $TRANSLATIONS = array( "Are you really sure you want add \"{domain}\" as trusted domain?" => "Êtes-vous vraiment sûr de vouloir ajouter \"{domain}\" comme domaine de confiance ?", "Add trusted domain" => "Ajouter un domaine de confiance", "Sending..." => "Envoi en cours...", +"All" => "Tous", "User Documentation" => "Documentation utilisateur", "Admin Documentation" => "Documentation administrateur", "Update to {appversion}" => "Mettre à jour vers {appversion}", @@ -71,12 +72,12 @@ $TRANSLATIONS = array( "Decrypting files... Please wait, this can take some time." => "Déchiffrement en cours... Cela peut prendre un certain temps.", "Delete encryption keys permanently." => "Supprimer définitivement les clés de chiffrement", "Restore encryption keys." => "Restaurer les clés de chiffrement", +"Groups" => "Groupes", "Unable to delete {objName}" => "Impossible de supprimer {objName}", "Error creating group" => "Erreur lors de la création du groupe", "A valid group name must be provided" => "Vous devez spécifier un nom de groupe valide", "deleted {groupName}" => "{groupName} supprimé", "undo" => "annuler", -"Groups" => "Groupes", "Group Admin" => "Admin Groupe", "never" => "jamais", "deleted {userName}" => "{userName} supprimé", @@ -119,6 +120,8 @@ $TRANSLATIONS = array( "We strongly suggest to install the required packages on your system to support one of the following locales: %s." => "Nous conseillons vivement d'installer les paquets requis sur votre système pour supporter l'un des paramètres régionaux suivants : %s.", "Internet connection not working" => "La connexion internet ne fonctionne pas", "This server has no working internet connection. This means that some of the features like mounting of external storage, notifications about updates or installation of 3rd party apps don´t work. Accessing files from remote and sending of notification emails might also not work. We suggest to enable internet connection for this server if you want to have all features." => "Ce serveur ne peut se connecter à internet. Cela signifie que certaines fonctionnalités, telles que le montage de supports de stockage distants, les notifications de mises à jour ou l'installation d'applications tierces ne fonctionneront pas. L'accès aux fichiers à distance, ainsi que les notifications par mails ne seront pas fonctionnels également. Il est recommandé d'activer la connexion internet pour ce serveur si vous souhaitez disposer de l'ensemble des fonctionnalités offertes.", +"URL generation in notification emails" => "Génération d'URL dans les mails de notification", +"If your installation is not installed in the root of the domain and uses system cron, there can be issues with the URL generation. To avoid these problems, please set the \"overwritewebroot\" option in your config.php file to the webroot path of your installation (Suggested: \"%s\")" => "Si votre installation n'a pas été effectuée à la racine du domaine et qu'elle utilise le cron du système, il peut y avoir des problèmes avec la génération d'URL. Pour les éviter, veuillez configurer l'option \"overwritewebroot\" de votre fichier config.php avec le chemin de la racine de votre installation (suggéré : \"%s\")", "Cron" => "Cron", "Last cron was executed at %s." => "Le dernier cron s'est exécuté à %s.", "Last cron was executed at %s. This is more than an hour ago, something seems wrong." => "Le dernier cron s'est exécuté à %s. Cela fait plus d'une heure, quelque chose a du mal se passer.", @@ -170,7 +173,6 @@ $TRANSLATIONS = array( "See application website" => "Voir le site web de l'application", "<span class=\"licence\"></span>-licensed by <span class=\"author\"></span>" => "Distribué sous licence <span class=\"licence\"></span>, par <span class=\"author\"></span>", "Enable only for specific groups" => "Activer uniquement pour certains groupes", -"All" => "Tous", "Administrator Documentation" => "Documentation administrateur", "Online Documentation" => "Documentation en ligne", "Forum" => "Forum", @@ -201,6 +203,10 @@ $TRANSLATIONS = array( "Language" => "Langue", "Help translate" => "Aidez à traduire", "SSL root certificates" => "Certificats racine SSL", +"Common Name" => "Nom d'usage", +"Valid until" => "Valide jusqu'à", +"Issued By" => "Délivré par", +"Valid until %s" => "Valide jusqu'à %s", "Import Root Certificate" => "Importer un certificat racine", "The encryption app is no longer enabled, please decrypt all your files" => "L'app de chiffrement n’est plus activée, veuillez déchiffrer tous vos fichiers", "Log-in password" => "Mot de passe de connexion", @@ -208,6 +214,7 @@ $TRANSLATIONS = array( "Your encryption keys are moved to a backup location. If something went wrong you can restore the keys. Only delete them permanently if you are sure that all files are decrypted correctly." => "Vos clés de chiffrement ont été déplacées dans l'emplacement de backup. Si quelque chose devait mal se passer, vous pouvez restaurer les clés. Choisissez la suppression permanente seulement si vous êtes sûr que tous les fichiers ont été déchiffrés correctement.", "Restore Encryption Keys" => "Restaurer les clés de chiffrement", "Delete Encryption Keys" => "Supprimer les clés de chiffrement", +"Show storage location" => "Afficher l'emplacement du stockage", "Show last log in" => "Montrer la dernière identification", "Login Name" => "Nom d'utilisateur", "Create" => "Créer", diff --git a/tests/data/testcal.ics b/tests/data/testcal.ics deleted file mode 100644 index e05f01ba1c2..00000000000 --- a/tests/data/testcal.ics +++ /dev/null @@ -1,13 +0,0 @@ -BEGIN:VCALENDAR -PRODID:-//some random cal software//EN -VERSION:2.0 -BEGIN:VEVENT -CREATED:20130102T120000Z -LAST-MODIFIED:20130102T120000Z -DTSTAMP:20130102T120000Z -UID:f106ecdf-c716-43ef-9d94-4e6f19f2fcfb -SUMMARY:a test cal file -DTSTART;VALUE=DATE:20130101 -DTEND;VALUE=DATE:20130102 -END:VEVENT -END:VCALENDAR
\ No newline at end of file diff --git a/tests/data/testcontact.vcf b/tests/data/testcontact.vcf deleted file mode 100644 index 2af963d6916..00000000000 --- a/tests/data/testcontact.vcf +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN:VCARD -VERSION:3.0 -PRODID:-//some random contact software//EN -N:def;abc;;; -FN:abc def -END:VCARD
\ No newline at end of file diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 3767c83fcb1..0e19c105cd1 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -46,8 +46,8 @@ class FileCache extends \Test_Cache { $storage = new \OC\Files\Storage\Temporary(array()); \OC\Files\Filesystem::mount($storage,array(),'/'); $datadir = str_replace('local::', '', $storage->getId()); - $this->datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT.'/data'); - \OC_Config::setValue('datadirectory', $datadir); + $this->datadir = \OC_Config::getValue('cachedirectory', \OC::$SERVERROOT.'/data/cache'); + \OC_Config::setValue('cachedirectory', $datadir); \OC_User::clearBackends(); \OC_User::useBackend(new \OC_User_Dummy()); @@ -67,6 +67,6 @@ class FileCache extends \Test_Cache { public function tearDown() { \OC_User::setUserId($this->user); - \OC_Config::setValue('datadirectory', $this->datadir); + \OC_Config::setValue('cachedirectory', $this->datadir); } } diff --git a/tests/lib/cache/usercache.php b/tests/lib/cache/usercache.php index 21b7f848ab6..a1b6af1c55d 100644 --- a/tests/lib/cache/usercache.php +++ b/tests/lib/cache/usercache.php @@ -42,8 +42,8 @@ class UserCache extends \Test_Cache { $storage = new \OC\Files\Storage\Temporary(array()); \OC\Files\Filesystem::mount($storage,array(),'/'); $datadir = str_replace('local::', '', $storage->getId()); - $this->datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT.'/data'); - \OC_Config::setValue('datadirectory', $datadir); + $this->datadir = \OC_Config::getValue('cachedirectory', \OC::$SERVERROOT.'/data/cache'); + \OC_Config::setValue('cachedirectory', $datadir); \OC_User::clearBackends(); \OC_User::useBackend(new \OC_User_Dummy()); @@ -63,6 +63,5 @@ class UserCache extends \Test_Cache { public function tearDown() { \OC_User::setUserId($this->user); - \OC_Config::setValue('datadirectory', $this->datadir); } } diff --git a/tests/lib/config.php b/tests/lib/config.php index c67a66c832e..f739df3ce97 100644 --- a/tests/lib/config.php +++ b/tests/lib/config.php @@ -79,6 +79,9 @@ class Test_Config extends PHPUnit_Framework_TestCase { * @expectedException \OC\HintException */ public function testWriteData() { + if (\OC_Util::runningOnWindows()) { + throw new \OC\HintException('this is ireelevent for windows'); + } $config = new OC\Config('/non-writable'); $config->setValue('foo', 'bar'); } diff --git a/tests/lib/connector/sabre/directory.php b/tests/lib/connector/sabre/directory.php index 8a1550ffa95..453d8e8d42a 100644 --- a/tests/lib/connector/sabre/directory.php +++ b/tests/lib/connector/sabre/directory.php @@ -8,18 +8,24 @@ */ class Test_OC_Connector_Sabre_Directory extends PHPUnit_Framework_TestCase { + private $view; + private $info; + + public function setUp() { + $this->view = $this->getMock('OC\Files\View', array(), array(), '', false); + $this->info = $this->getMock('OC\Files\FileInfo', array(), array(), '', false); + } + private function getRootDir() { - $view = $this->getMock('OC\Files\View', array(), array(), '', false); - $view->expects($this->once()) + $this->view->expects($this->once()) ->method('getRelativePath') ->will($this->returnValue('')); - $info = $this->getMock('OC\Files\FileInfo', array(), array(), '', false); - $info->expects($this->once()) + $this->info->expects($this->once()) ->method('getPath') ->will($this->returnValue('')); - return new OC_Connector_Sabre_Directory($view, $info); + return new OC_Connector_Sabre_Directory($this->view, $this->info); } /** @@ -45,4 +51,52 @@ class Test_OC_Connector_Sabre_Directory extends PHPUnit_Framework_TestCase { $dir = $this->getRootDir(); $dir->delete(); } + + /** + * + */ + public function testDeleteFolderWhenAllowed() { + // deletion allowed + $this->info->expects($this->once()) + ->method('isDeletable') + ->will($this->returnValue(true)); + + // but fails + $this->view->expects($this->once()) + ->method('rmdir') + ->will($this->returnValue(true)); + + $dir = $this->getRootDir(); + $dir->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testDeleteFolderFailsWhenNotAllowed() { + $this->info->expects($this->once()) + ->method('isDeletable') + ->will($this->returnValue(false)); + + $dir = $this->getRootDir(); + $dir->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testDeleteFolderThrowsWhenDeletionFailed() { + // deletion allowed + $this->info->expects($this->once()) + ->method('isDeletable') + ->will($this->returnValue(true)); + + // but fails + $this->view->expects($this->once()) + ->method('rmdir') + ->will($this->returnValue(false)); + + $dir = $this->getRootDir(); + $dir->delete(); + } } diff --git a/tests/lib/connector/sabre/file.php b/tests/lib/connector/sabre/file.php index 1602c5181fe..0993a27f372 100644 --- a/tests/lib/connector/sabre/file.php +++ b/tests/lib/connector/sabre/file.php @@ -143,4 +143,67 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase { // action $file->put('test data'); } + + /** + * + */ + public function testDeleteWhenAllowed() { + // setup + $view = $this->getMock('\OC\Files\View', + array()); + + $view->expects($this->once()) + ->method('unlink') + ->will($this->returnValue(true)); + + $info = new \OC\Files\FileInfo('/test.txt', null, null, array( + 'permissions' => \OCP\PERMISSION_ALL + )); + + $file = new OC_Connector_Sabre_File($view, $info); + + // action + $file->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testDeleteThrowsWhenDeletionNotAllowed() { + // setup + $view = $this->getMock('\OC\Files\View', + array()); + + $info = new \OC\Files\FileInfo('/test.txt', null, null, array( + 'permissions' => 0 + )); + + $file = new OC_Connector_Sabre_File($view, $info); + + // action + $file->delete(); + } + + /** + * @expectedException \Sabre\DAV\Exception\Forbidden + */ + public function testDeleteThrowsWhenDeletionFailed() { + // setup + $view = $this->getMock('\OC\Files\View', + array()); + + // but fails + $view->expects($this->once()) + ->method('unlink') + ->will($this->returnValue(false)); + + $info = new \OC\Files\FileInfo('/test.txt', null, null, array( + 'permissions' => \OCP\PERMISSION_ALL + )); + + $file = new OC_Connector_Sabre_File($view, $info); + + // action + $file->delete(); + } } diff --git a/tests/lib/httphelper.php b/tests/lib/httphelper.php new file mode 100644 index 00000000000..191200aee3d --- /dev/null +++ b/tests/lib/httphelper.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright (c) 2014 Lukas Reschke <lukas@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class TestHTTPHelper extends \PHPUnit_Framework_TestCase { + + /** @var \OC\AllConfig*/ + private $config; + /** @var \OC\HTTPHelper */ + private $httpHelperMock; + + function setUp() { + $this->config = $this->getMockBuilder('\OC\AllConfig') + ->disableOriginalConstructor()->getMock(); + $this->httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper') + ->setConstructorArgs(array($this->config)) + ->setMethods(array('getHeaders')) + ->getMock(); + } + + public function testIsHTTPProvider() { + return array( + array('http://wwww.owncloud.org/enterprise/', true), + array('https://wwww.owncloud.org/enterprise/', true), + array('HTTPS://WWW.OWNCLOUD.ORG', true), + array('HTTP://WWW.OWNCLOUD.ORG', true), + array('FILE://WWW.OWNCLOUD.ORG', false), + array('file://www.owncloud.org', false), + array('FTP://WWW.OWNCLOUD.ORG', false), + array('ftp://www.owncloud.org', false), + ); + } + + /** + * Note: Not using a dataprovider because onConsecutiveCalls expects not + * an array but the function arguments directly + */ + public function testGetFinalLocationOfURLValid() { + $url = 'https://www.owncloud.org/enterprise/'; + $expected = 'https://www.owncloud.com/enterprise/'; + $this->httpHelperMock->expects($this->any()) + ->method('getHeaders') + ->will($this->onConsecutiveCalls( + array('Location' => 'http://www.owncloud.com/enterprise/'), + array('Location' => 'https://www.owncloud.com/enterprise/') + )); + $result = $this->httpHelperMock->getFinalLocationOfURL($url); + $this->assertSame($expected, $result); + } + + /** + * Note: Not using a dataprovider because onConsecutiveCalls expects not + * an array but the function arguments directly + */ + public function testGetFinalLocationOfURLInvalid() { + $url = 'https://www.owncloud.org/enterprise/'; + $expected = 'http://www.owncloud.com/enterprise/'; + $this->httpHelperMock->expects($this->any()) + ->method('getHeaders') + ->will($this->onConsecutiveCalls( + array('Location' => 'http://www.owncloud.com/enterprise/'), + array('Location' => 'file://etc/passwd'), + array('Location' => 'http://www.example.com/') + )); + $result = $this->httpHelperMock->getFinalLocationOfURL($url); + $this->assertSame($expected, $result); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage URL must begin with HTTPS or HTTP. + */ + public function testGetFinalLocationOfURLException() { + $this->httpHelperMock->getFinalLocationOfURL('file://etc/passwd'); + } + + /** + * @dataProvider testIsHTTPProvider + */ + public function testIsHTTP($url, $expected) { + $this->assertSame($expected, $this->httpHelperMock->isHTTPURL($url)); + } + +} diff --git a/tests/lib/largefilehelpergetfilesize.php b/tests/lib/largefilehelpergetfilesize.php index 86ce6d295cf..21a0aa9a233 100644 --- a/tests/lib/largefilehelpergetfilesize.php +++ b/tests/lib/largefilehelpergetfilesize.php @@ -19,7 +19,8 @@ class LargeFileHelperGetFileSize extends \PHPUnit_Framework_TestCase { public function setUp() { parent::setUp(); - $this->filename = __DIR__ . '/../data/data.tar.gz'; + $ds = DIRECTORY_SEPARATOR; + $this->filename = dirname(__DIR__) . "{$ds}data{$ds}data.tar.gz"; $this->fileSize = 4195; $this->helper = new \OC\LargeFileHelper; } diff --git a/tests/lib/preview.php b/tests/lib/preview.php index 4ef61fb8257..2febe524cba 100644 --- a/tests/lib/preview.php +++ b/tests/lib/preview.php @@ -97,13 +97,9 @@ class Preview extends \PHPUnit_Framework_TestCase { public function txtBlacklist() { $txt = 'random text file'; - $ics = file_get_contents(__DIR__ . '/../data/testcal.ics'); - $vcf = file_get_contents(__DIR__ . '/../data/testcontact.vcf'); return array( array('txt', $txt, false), - array('ics', $ics, true), - array('vcf', $vcf, true), ); } diff --git a/tests/lib/util.php b/tests/lib/util.php index 8964f9f2666..999c62486a7 100644 --- a/tests/lib/util.php +++ b/tests/lib/util.php @@ -116,7 +116,10 @@ class Test_Util extends PHPUnit_Framework_TestCase { function testGetInstanceIdGeneratesValidId() { OC_Config::deleteKey('instanceid'); - $this->assertStringStartsWith('oc', OC_Util::getInstanceId()); + $instanceId = OC_Util::getInstanceId(); + $this->assertStringStartsWith('oc', $instanceId); + $matchesRegex = preg_match('/^[a-z0-9]+$/', $instanceId); + $this->assertSame(1, $matchesRegex); } /** |