summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rw-r--r--README.md2
-rw-r--r--apps/encryption/appinfo/application.php1
-rw-r--r--apps/encryption/hooks/userhooks.php10
-rw-r--r--apps/encryption/l10n/fr.js4
-rw-r--r--apps/encryption/l10n/fr.json4
-rw-r--r--apps/encryption/tests/hooks/UserHooksTest.php65
-rw-r--r--apps/files/appinfo/remote.php3
-rw-r--r--apps/files/css/files.css2
-rw-r--r--apps/files_external/js/settings.js7
-rw-r--r--apps/files_external/l10n/da.js1
-rw-r--r--apps/files_external/l10n/da.json1
-rw-r--r--apps/files_external/l10n/fi_FI.js2
-rw-r--r--apps/files_external/l10n/fi_FI.json2
-rw-r--r--apps/files_external/l10n/it.js2
-rw-r--r--apps/files_external/l10n/it.json2
-rw-r--r--apps/files_external/l10n/nb_NO.js1
-rw-r--r--apps/files_external/l10n/nb_NO.json1
-rw-r--r--apps/files_external/l10n/nl.js1
-rw-r--r--apps/files_external/l10n/nl.json1
-rw-r--r--apps/files_external/l10n/pt_BR.js1
-rw-r--r--apps/files_external/l10n/pt_BR.json1
-rw-r--r--apps/files_external/l10n/th_TH.js1
-rw-r--r--apps/files_external/l10n/th_TH.json1
-rw-r--r--apps/files_external/lib/amazons3.php5
-rw-r--r--apps/files_external/lib/config/configadapter.php2
-rw-r--r--apps/files_external/service/userglobalstoragesservice.php57
-rw-r--r--apps/files_external/templates/settings.php16
-rw-r--r--apps/files_external/tests/backends/amazons3.php6
-rwxr-xr-xapps/files_external/tests/env/start-amazons3-ceph.sh81
-rwxr-xr-xapps/files_external/tests/env/stop-amazons3-ceph.sh36
-rw-r--r--apps/files_external/tests/service/userglobalstoragesservicetest.php80
-rw-r--r--apps/files_sharing/api/server2server.php13
-rw-r--r--apps/files_sharing/api/sharees.php14
-rw-r--r--apps/files_sharing/appinfo/app.php3
-rw-r--r--apps/files_sharing/css/sharetabview.css24
-rw-r--r--apps/files_sharing/l10n/da.js3
-rw-r--r--apps/files_sharing/l10n/da.json3
-rw-r--r--apps/files_sharing/l10n/fi_FI.js3
-rw-r--r--apps/files_sharing/l10n/fi_FI.json3
-rw-r--r--apps/files_sharing/l10n/it.js5
-rw-r--r--apps/files_sharing/l10n/it.json5
-rw-r--r--apps/files_sharing/l10n/nb_NO.js4
-rw-r--r--apps/files_sharing/l10n/nb_NO.json4
-rw-r--r--apps/files_sharing/l10n/nl.js3
-rw-r--r--apps/files_sharing/l10n/nl.json3
-rw-r--r--apps/files_sharing/l10n/pt_BR.js3
-rw-r--r--apps/files_sharing/l10n/pt_BR.json3
-rw-r--r--apps/files_sharing/lib/activity.php42
-rw-r--r--apps/files_sharing/lib/capabilities.php7
-rw-r--r--apps/files_sharing/lib/external/manager.php4
-rw-r--r--apps/files_sharing/publicwebdav.php3
-rw-r--r--apps/files_sharing/tests/api/shareestest.php112
-rw-r--r--apps/files_sharing/tests/capabilities.php35
-rw-r--r--apps/files_trashbin/appinfo/app.php1
-rw-r--r--apps/files_trashbin/appinfo/install.php23
-rw-r--r--apps/files_trashbin/appinfo/update.php3
-rw-r--r--apps/files_trashbin/lib/backgroundjob/expiretrash.php127
-rw-r--r--apps/files_trashbin/lib/expiration.php12
-rw-r--r--apps/files_trashbin/lib/trashbin.php6
-rw-r--r--apps/files_trashbin/tests/backgroundjob/expiretrash.php40
-rw-r--r--apps/files_trashbin/tests/expiration.php34
-rw-r--r--apps/files_versions/appinfo/app.php3
-rw-r--r--apps/files_versions/appinfo/install.php23
-rw-r--r--apps/files_versions/appinfo/update.php3
-rw-r--r--apps/files_versions/css/versions.css15
-rw-r--r--apps/files_versions/js/versionstabview.js3
-rw-r--r--apps/files_versions/lib/backgroundjob/expireversions.php98
-rw-r--r--apps/files_versions/lib/expiration.php13
-rw-r--r--apps/files_versions/lib/storage.php32
-rw-r--r--core/command/encryption/decryptall.php18
-rw-r--r--core/command/encryption/encryptall.php24
-rw-r--r--core/css/share.css16
-rw-r--r--core/js/jquery.avatar.js2
-rw-r--r--core/js/share.js2
-rw-r--r--core/js/sharedialogshareelistview.js18
-rw-r--r--core/js/tests/specs/jquery.avatarSpec.js240
-rw-r--r--core/l10n/da.js2
-rw-r--r--core/l10n/da.json2
-rw-r--r--core/l10n/fi_FI.js2
-rw-r--r--core/l10n/fi_FI.json2
-rw-r--r--core/l10n/it.js2
-rw-r--r--core/l10n/it.json2
-rw-r--r--core/l10n/nb_NO.js2
-rw-r--r--core/l10n/nb_NO.json2
-rw-r--r--core/l10n/nl.js2
-rw-r--r--core/l10n/nl.json2
-rw-r--r--core/l10n/pt_BR.js2
-rw-r--r--core/l10n/pt_BR.json2
-rw-r--r--core/l10n/th_TH.js2
-rw-r--r--core/l10n/th_TH.json2
-rw-r--r--lib/private/app.php29
-rw-r--r--lib/private/connector/sabre/listenerplugin.php58
-rw-r--r--lib/private/connector/sabre/maintenanceplugin.php2
-rw-r--r--lib/private/connector/sabre/serverfactory.php6
-rw-r--r--lib/private/files.php5
-rw-r--r--lib/private/files/cache/storage.php2
-rw-r--r--lib/private/lock/dblockingprovider.php49
-rw-r--r--lib/private/notification/imanager.php6
-rw-r--r--lib/private/notification/manager.php8
-rw-r--r--lib/private/preview.php6
-rw-r--r--lib/private/repair.php6
-rw-r--r--lib/private/server.php2
-rw-r--r--lib/repair/updateoutdatedocsids.php108
-rw-r--r--settings/ajax/navigationdetect.php12
-rw-r--r--settings/js/apps.js31
-rw-r--r--settings/l10n/da.js20
-rw-r--r--settings/l10n/da.json20
-rw-r--r--settings/l10n/it.js2
-rw-r--r--settings/l10n/it.json2
-rw-r--r--tests/core/command/encryption/decryptalltest.php7
-rw-r--r--tests/core/command/encryption/encryptalltest.php4
-rw-r--r--tests/lib/connector/sabre/requesttest/downloadtest.php52
-rw-r--r--tests/lib/connector/sabre/requesttest/encryptionuploadtest.php25
-rw-r--r--tests/lib/connector/sabre/requesttest/requesttest.php6
-rw-r--r--tests/lib/connector/sabre/requesttest/sapi.php10
-rw-r--r--tests/lib/connector/sabre/requesttest/uploadtest.php14
-rw-r--r--tests/lib/lock/dblockingprovider.php56
-rw-r--r--tests/lib/repair/updateoutdatedocsids.php80
-rw-r--r--tests/lib/traits/encryptiontrait.php104
-rw-r--r--tests/lib/traits/mountprovidertrait.php6
-rw-r--r--version.php6
122 files changed, 1984 insertions, 242 deletions
diff --git a/3rdparty b/3rdparty
-Subproject b94f7d38f6e13825fd34c7113827d3c369a689a
+Subproject 6b6575b04c01e30e5f38dbb373fd5166cce0ef5
diff --git a/README.md b/README.md
index a705074d6be..1085d516263 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Quality:
- Scrutinizer: [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/owncloud/core/badges/quality-score.png?s=ce2f5ded03d4ac628e9ee5c767243fa7412e644f)](https://scrutinizer-ci.com/g/owncloud/core/)
- CodeClimate: [![Code Climate](https://codeclimate.com/github/owncloud/core/badges/gpa.svg)](https://codeclimate.com/github/owncloud/core)
-Depencencies:
+Dependencies:
[![Dependency Status](https://www.versioneye.com/user/projects/54f4a2384f3108959a000a16/badge.svg?style=flat)](https://www.versioneye.com/user/projects/54f4a2384f3108959a000a16)
diff --git a/apps/encryption/appinfo/application.php b/apps/encryption/appinfo/application.php
index 515a408fa2c..d89833a5ab2 100644
--- a/apps/encryption/appinfo/application.php
+++ b/apps/encryption/appinfo/application.php
@@ -84,6 +84,7 @@ class Application extends \OCP\AppFramework\App {
$hookManager->registerHook([
new UserHooks($container->query('KeyManager'),
+ $server->getUserManager(),
$server->getLogger(),
$container->query('UserSetup'),
$server->getUserSession(),
diff --git a/apps/encryption/hooks/userhooks.php b/apps/encryption/hooks/userhooks.php
index 8b6f17bec6d..5bd5e39f3c5 100644
--- a/apps/encryption/hooks/userhooks.php
+++ b/apps/encryption/hooks/userhooks.php
@@ -24,6 +24,7 @@
namespace OCA\Encryption\Hooks;
+use OCP\IUserManager;
use OCP\Util as OCUtil;
use OCA\Encryption\Hooks\Contracts\IHook;
use OCA\Encryption\KeyManager;
@@ -42,6 +43,10 @@ class UserHooks implements IHook {
*/
private $keyManager;
/**
+ * @var IUserManager
+ */
+ private $userManager;
+ /**
* @var ILogger
*/
private $logger;
@@ -74,6 +79,7 @@ class UserHooks implements IHook {
* UserHooks constructor.
*
* @param KeyManager $keyManager
+ * @param IUserManager $userManager
* @param ILogger $logger
* @param Setup $userSetup
* @param IUserSession $user
@@ -83,6 +89,7 @@ class UserHooks implements IHook {
* @param Recovery $recovery
*/
public function __construct(KeyManager $keyManager,
+ IUserManager $userManager,
ILogger $logger,
Setup $userSetup,
IUserSession $user,
@@ -92,6 +99,7 @@ class UserHooks implements IHook {
Recovery $recovery) {
$this->keyManager = $keyManager;
+ $this->userManager = $userManager;
$this->logger = $logger;
$this->userSetup = $userSetup;
$this->user = $user;
@@ -196,7 +204,7 @@ class UserHooks implements IHook {
public function preSetPassphrase($params) {
if (App::isEnabled('encryption')) {
- $user = $this->user->getUser();
+ $user = $this->userManager->get($params['uid']);
if ($user && !$user->canChangePassword()) {
$this->setPassphrase($params);
diff --git a/apps/encryption/l10n/fr.js b/apps/encryption/l10n/fr.js
index 0de35f8ec1c..3ee1c05ffa7 100644
--- a/apps/encryption/l10n/fr.js
+++ b/apps/encryption/l10n/fr.js
@@ -28,10 +28,10 @@ OC.L10N.register(
"one-time password for server-side-encryption" : "Mot de passe à usage unique pour le chiffrement côté serveur",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de déchiffrer ce fichier : il s'agit probablement d'un fichier partagé. Veuillez demander au propriétaire du fichier de le partager à nouveau avec vous.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de lire ce fichier, il s'agit probablement d'un fichier partagé. Veuillez demander au propriétaire du fichier de le repartager avec vous. ",
- "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjour,\n\nL'administrateur a activé le chiffrement côté serveur. Vos fichiers ont été chiffrés avec le mot de passe '%s'.\n\nVeuillez vous connecté dans l'interface web, allez dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là mettez à jour votre mot de passe de chiffrement en entrant ce mot de passe dans le champ \"Ancien mot de passe de connexion\" et votre mot de passe de connexion actuel.\n",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjour,\n\nL'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe '%s'.\n\nVeuillez vous connecter dans l'interface web et aller dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là, mettez à jour votre mot de passe de chiffrement en entrant le mot de passe fourni dans ce message dans le champ \"Ancien mot de passe de connexion\", et votre mot de passe de connexion actuel.\n",
"The share will expire on %s." : "Le partage expirera le %s.",
"Cheers!" : "À bientôt !",
- "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,<br><br>L'administrateur a activé le chiffrement côté serveur. Vos fichiers ont été chiffrés avec le mot de passe <strong>%s</strong>. <br><br>Veuillez vous connecté dans l'interface web, allez dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là mettez à jour votre mot de passe de chiffrement en entrant ce mot de passe dans le champ \"Ancien mot de passe de connexion\" et votre mot de passe de connexion actuel. <br><br>",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,<br><br>L'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe <strong>%s</strong>.<br><br>\nVeuillez vous connecter dans l'interface web et aller dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là, mettez à jour votre mot de passe de chiffrement en entrant le mot de passe fourni dans ce message dans le champ \"Ancien mot de passe de connexion\", et votre mot de passe de connexion actuel.<br><br>",
"Enable recovery key" : "Activer la clé de récupération",
"Disable recovery key" : "Désactiver la clé de récupération",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clé de récupération est une clé supplémentaire utilisée pour chiffrer les fichiers. Elle permet de récupérer les fichiers des utilisateurs s'ils oublient leur mot de passe.",
diff --git a/apps/encryption/l10n/fr.json b/apps/encryption/l10n/fr.json
index 3fa598a72ce..3694682d8bc 100644
--- a/apps/encryption/l10n/fr.json
+++ b/apps/encryption/l10n/fr.json
@@ -26,10 +26,10 @@
"one-time password for server-side-encryption" : "Mot de passe à usage unique pour le chiffrement côté serveur",
"Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de déchiffrer ce fichier : il s'agit probablement d'un fichier partagé. Veuillez demander au propriétaire du fichier de le partager à nouveau avec vous.",
"Can not read this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Impossible de lire ce fichier, il s'agit probablement d'un fichier partagé. Veuillez demander au propriétaire du fichier de le repartager avec vous. ",
- "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjour,\n\nL'administrateur a activé le chiffrement côté serveur. Vos fichiers ont été chiffrés avec le mot de passe '%s'.\n\nVeuillez vous connecté dans l'interface web, allez dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là mettez à jour votre mot de passe de chiffrement en entrant ce mot de passe dans le champ \"Ancien mot de passe de connexion\" et votre mot de passe de connexion actuel.\n",
+ "Hey there,\n\nthe admin enabled server-side-encryption. Your files were encrypted using the password '%s'.\n\nPlease login to the web interface, go to the section 'ownCloud basic encryption module' of your personal settings and update your encryption password by entering this password into the 'old log-in password' field and your current login-password.\n\n" : "Bonjour,\n\nL'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe '%s'.\n\nVeuillez vous connecter dans l'interface web et aller dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là, mettez à jour votre mot de passe de chiffrement en entrant le mot de passe fourni dans ce message dans le champ \"Ancien mot de passe de connexion\", et votre mot de passe de connexion actuel.\n",
"The share will expire on %s." : "Le partage expirera le %s.",
"Cheers!" : "À bientôt !",
- "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,<br><br>L'administrateur a activé le chiffrement côté serveur. Vos fichiers ont été chiffrés avec le mot de passe <strong>%s</strong>. <br><br>Veuillez vous connecté dans l'interface web, allez dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là mettez à jour votre mot de passe de chiffrement en entrant ce mot de passe dans le champ \"Ancien mot de passe de connexion\" et votre mot de passe de connexion actuel. <br><br>",
+ "Hey there,<br><br>the admin enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br>Please login to the web interface, go to the section \"ownCloud basic encryption module\" of your personal settings and update your encryption password by entering this password into the \"old log-in password\" field and your current login-password.<br><br>" : "Bonjour,<br><br>L'administrateur a activé le chiffrement sur le serveur. Vos fichiers ont été chiffrés avec le mot de passe <strong>%s</strong>.<br><br>\nVeuillez vous connecter dans l'interface web et aller dans la section \"Module de chiffrement de base d'ownCloud\" de vos paramètres personnels. De là, mettez à jour votre mot de passe de chiffrement en entrant le mot de passe fourni dans ce message dans le champ \"Ancien mot de passe de connexion\", et votre mot de passe de connexion actuel.<br><br>",
"Enable recovery key" : "Activer la clé de récupération",
"Disable recovery key" : "Désactiver la clé de récupération",
"The recovery key is an extra encryption key that is used to encrypt files. It allows recovery of a user's files if the user forgets his or her password." : "La clé de récupération est une clé supplémentaire utilisée pour chiffrer les fichiers. Elle permet de récupérer les fichiers des utilisateurs s'ils oublient leur mot de passe.",
diff --git a/apps/encryption/tests/hooks/UserHooksTest.php b/apps/encryption/tests/hooks/UserHooksTest.php
index aa16a4d8703..0b0222ce861 100644
--- a/apps/encryption/tests/hooks/UserHooksTest.php
+++ b/apps/encryption/tests/hooks/UserHooksTest.php
@@ -50,6 +50,11 @@ class UserHooksTest extends TestCase {
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
+ private $userManagerMock;
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject
+ */
private $userSetupMock;
/**
* @var \PHPUnit_Framework_MockObject_MockObject
@@ -101,11 +106,58 @@ class UserHooksTest extends TestCase {
$this->assertNull($this->instance->postDeleteUser($this->params));
}
- public function testPreSetPassphrase() {
- $this->userSessionMock->expects($this->once())
- ->method('canChangePassword');
+ /**
+ * @dataProvider dataTestPreSetPassphrase
+ */
+ public function testPreSetPassphrase($canChange) {
+
+ /** @var UserHooks | \PHPUnit_Framework_MockObject_MockObject $instance */
+ $instance = $this->getMockBuilder('OCA\Encryption\Hooks\UserHooks')
+ ->setConstructorArgs(
+ [
+ $this->keyManagerMock,
+ $this->userManagerMock,
+ $this->loggerMock,
+ $this->userSetupMock,
+ $this->userSessionMock,
+ $this->utilMock,
+ $this->sessionMock,
+ $this->cryptMock,
+ $this->recoveryMock
+ ]
+ )
+ ->setMethods(['setPassphrase'])
+ ->getMock();
+
+ $userMock = $this->getMock('OCP\IUser');
+
+ $this->userManagerMock->expects($this->once())
+ ->method('get')
+ ->with($this->params['uid'])
+ ->willReturn($userMock);
+ $userMock->expects($this->once())
+ ->method('canChangePassword')
+ ->willReturn($canChange);
+
+ if ($canChange) {
+ // in this case the password will be changed in the post hook
+ $instance->expects($this->never())->method('setPassphrase');
+ } else {
+ // if user can't change the password we update the encryption
+ // key password already in the pre hook
+ $instance->expects($this->once())
+ ->method('setPassphrase')
+ ->with($this->params);
+ }
+
+ $instance->preSetPassphrase($this->params);
+ }
- $this->assertNull($this->instance->preSetPassphrase($this->params));
+ public function dataTestPreSetPassphrase() {
+ return [
+ [true],
+ [false]
+ ];
}
public function testSetPassphrase() {
@@ -186,6 +238,7 @@ class UserHooksTest extends TestCase {
->willReturn(false);
$userHooks = new UserHooks($this->keyManagerMock,
+ $this->userManagerMock,
$this->loggerMock,
$this->userSetupMock,
$userSessionMock,
@@ -216,6 +269,9 @@ class UserHooksTest extends TestCase {
$this->keyManagerMock = $this->getMockBuilder('OCA\Encryption\KeyManager')
->disableOriginalConstructor()
->getMock();
+ $this->userManagerMock = $this->getMockBuilder('OCP\IUserManager')
+ ->disableOriginalConstructor()
+ ->getMock();
$this->userSetupMock = $this->getMockBuilder('OCA\Encryption\Users\Setup')
->disableOriginalConstructor()
->getMock();
@@ -258,6 +314,7 @@ class UserHooksTest extends TestCase {
$this->recoveryMock = $recoveryMock;
$this->utilMock = $utilMock;
$this->instance = new UserHooks($this->keyManagerMock,
+ $this->userManagerMock,
$this->loggerMock,
$this->userSetupMock,
$this->userSessionMock,
diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php
index 36479ae13d0..4d0d8b3e2ec 100644
--- a/apps/files/appinfo/remote.php
+++ b/apps/files/appinfo/remote.php
@@ -39,7 +39,8 @@ $serverFactory = new \OC\Connector\Sabre\ServerFactory(
\OC::$server->getDatabaseConnection(),
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
- \OC::$server->getTagManager()
+ \OC::$server->getTagManager(),
+ \OC::$server->getEventDispatcher()
);
// Backends
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index df23f415129..c0701fb18b8 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -250,7 +250,7 @@ table thead th {
background-color: #fff;
}
table.multiselect thead th {
- background-color: rgba(248,248,248,.8); /* #f8f8f8 like other hover style */
+ background-color: rgba(255, 255, 255, 0.95); /* like controls bar */
color: #000;
font-weight: bold;
border-bottom: 0;
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index bf9981adabf..4319677f4f4 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -15,12 +15,12 @@ var MOUNT_OPTIONS_DROPDOWN_TEMPLATE =
'<div class="drop dropdown mountOptionsDropdown">' +
// FIXME: options are hard-coded for now
' <div class="optionRow">' +
- ' <label for="mountOptionsEncrypt">{{t "files_external" "Enable encryption"}}</label>' +
' <input id="mountOptionsEncrypt" name="encrypt" type="checkbox" value="true" checked="checked"/>' +
+ ' <label for="mountOptionsEncrypt">{{t "files_external" "Enable encryption"}}</label>' +
' </div>' +
' <div class="optionRow">' +
- ' <label for="mountOptionsPreviews">{{t "files_external" "Enable previews"}}</label>' +
' <input id="mountOptionsPreviews" name="previews" type="checkbox" value="true" checked="checked"/>' +
+ ' <label for="mountOptionsPreviews">{{t "files_external" "Enable previews"}}</label>' +
' </div>' +
' <div class="optionRow">' +
' <label for="mountOptionsFilesystemCheck">{{t "files_external" "Check for changes"}}</label>' +
@@ -808,7 +808,8 @@ MountConfigListView.prototype = _.extend({
if (placeholder.indexOf('*') === 0) {
newElement = $('<input type="password" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" placeholder="'+placeholder.substring(1)+'" />');
} else if (placeholder.indexOf('!') === 0) {
- newElement = $('<label><input type="checkbox" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" />'+placeholder.substring(1)+'</label>');
+ var checkboxId = _.uniqueId('checkbox_');
+ newElement = $('<input type="checkbox" id="'+checkboxId+'" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" /><label for="'+checkboxId+'">'+placeholder.substring(1)+'</label>');
} else if (placeholder.indexOf('#') === 0) {
newElement = $('<input type="hidden" class="'+classes.join(' ')+'" data-parameter="'+parameter+'" />');
} else {
diff --git a/apps/files_external/l10n/da.js b/apps/files_external/l10n/da.js
index 98f020785c9..435884aa11d 100644
--- a/apps/files_external/l10n/da.js
+++ b/apps/files_external/l10n/da.js
@@ -78,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP med det hemmelige nøgle login [DEPRECATED]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Del",
+ "Domain" : "Domæne",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS der bruger OC login [DEPRECATED]",
"Username as share" : "Brugernavn som deling",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/da.json b/apps/files_external/l10n/da.json
index 5c7bda17a40..631fb196624 100644
--- a/apps/files_external/l10n/da.json
+++ b/apps/files_external/l10n/da.json
@@ -76,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP med det hemmelige nøgle login [DEPRECATED]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Del",
+ "Domain" : "Domæne",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS der bruger OC login [DEPRECATED]",
"Username as share" : "Brugernavn som deling",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/fi_FI.js b/apps/files_external/l10n/fi_FI.js
index 2243f5f5526..92e93d9ed3a 100644
--- a/apps/files_external/l10n/fi_FI.js
+++ b/apps/files_external/l10n/fi_FI.js
@@ -23,6 +23,7 @@ OC.L10N.register(
"All users. Type to select user or group." : "Kaikki käyttäjät. Kirjoita valitaksesi käyttäjän tai ryhmän.",
"(group)" : "(ryhmä)",
"Saved" : "Tallennettu",
+ "Builtin" : "Sisäänrakennettu",
"None" : "Ei mitään",
"OAuth1" : "OAuth1",
"App key" : "Sovellusavain",
@@ -33,6 +34,7 @@ OC.L10N.register(
"OpenStack" : "OpenStack",
"Username" : "Käyttäjätunnus",
"Password" : "Salasana",
+ "Rackspace" : "Rackspace",
"API key" : "API-avain",
"Username and password" : "Käyttäjätunnus ja salasana",
"RSA public key" : "Julkinen RSA-avain",
diff --git a/apps/files_external/l10n/fi_FI.json b/apps/files_external/l10n/fi_FI.json
index b629fad87c6..6459b33a126 100644
--- a/apps/files_external/l10n/fi_FI.json
+++ b/apps/files_external/l10n/fi_FI.json
@@ -21,6 +21,7 @@
"All users. Type to select user or group." : "Kaikki käyttäjät. Kirjoita valitaksesi käyttäjän tai ryhmän.",
"(group)" : "(ryhmä)",
"Saved" : "Tallennettu",
+ "Builtin" : "Sisäänrakennettu",
"None" : "Ei mitään",
"OAuth1" : "OAuth1",
"App key" : "Sovellusavain",
@@ -31,6 +32,7 @@
"OpenStack" : "OpenStack",
"Username" : "Käyttäjätunnus",
"Password" : "Salasana",
+ "Rackspace" : "Rackspace",
"API key" : "API-avain",
"Username and password" : "Käyttäjätunnus ja salasana",
"RSA public key" : "Julkinen RSA-avain",
diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js
index cae6e428cd8..0844e90b903 100644
--- a/apps/files_external/l10n/it.js
+++ b/apps/files_external/l10n/it.js
@@ -47,6 +47,7 @@ OC.L10N.register(
"Username" : "Nome utente",
"Password" : "Password",
"Tenant name" : "Nome tenant",
+ "Identity endpoint URL" : "URL endpoint delle identità",
"Rackspace" : "Rackspace",
"API key" : "Chiave API",
"Username and password" : "Nome utente e password",
@@ -77,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP con accesso a chiave segreta [DEPRECATO]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Condividi",
+ "Domain" : "Dominio",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS utilizzando le credenziali di OC [DEPRECATO]",
"Username as share" : "Nome utente come condivisione",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json
index 8be3cd2cd97..cfe633bc328 100644
--- a/apps/files_external/l10n/it.json
+++ b/apps/files_external/l10n/it.json
@@ -45,6 +45,7 @@
"Username" : "Nome utente",
"Password" : "Password",
"Tenant name" : "Nome tenant",
+ "Identity endpoint URL" : "URL endpoint delle identità",
"Rackspace" : "Rackspace",
"API key" : "Chiave API",
"Username and password" : "Nome utente e password",
@@ -75,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP con accesso a chiave segreta [DEPRECATO]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Condividi",
+ "Domain" : "Dominio",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS utilizzando le credenziali di OC [DEPRECATO]",
"Username as share" : "Nome utente come condivisione",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/nb_NO.js b/apps/files_external/l10n/nb_NO.js
index 0089d42288d..ea912e4cf7a 100644
--- a/apps/files_external/l10n/nb_NO.js
+++ b/apps/files_external/l10n/nb_NO.js
@@ -78,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP med hemmelig nøkkel for pålogging [FORELDET]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Delt ressurs",
+ "Domain" : "Domene",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS med OC-pålogging [FORELDET]",
"Username as share" : "Brukernavn som share",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/nb_NO.json b/apps/files_external/l10n/nb_NO.json
index 8ee2713f329..800234a931a 100644
--- a/apps/files_external/l10n/nb_NO.json
+++ b/apps/files_external/l10n/nb_NO.json
@@ -76,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP med hemmelig nøkkel for pålogging [FORELDET]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Delt ressurs",
+ "Domain" : "Domene",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS med OC-pålogging [FORELDET]",
"Username as share" : "Brukernavn som share",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js
index 8367c64c394..a40b2afa7e8 100644
--- a/apps/files_external/l10n/nl.js
+++ b/apps/files_external/l10n/nl.js
@@ -78,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP inlog met geheime sleutel [VEROUDERD]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Share",
+ "Domain" : "Domein",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS login met OC [VEROUDERD]",
"Username as share" : "Gebruikersnaam als share",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json
index 0414e7b08c5..52507dc4744 100644
--- a/apps/files_external/l10n/nl.json
+++ b/apps/files_external/l10n/nl.json
@@ -76,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP inlog met geheime sleutel [VEROUDERD]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Share",
+ "Domain" : "Domein",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS login met OC [VEROUDERD]",
"Username as share" : "Gebruikersnaam als share",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/pt_BR.js b/apps/files_external/l10n/pt_BR.js
index 9b9d1c49a49..68b1c671c3c 100644
--- a/apps/files_external/l10n/pt_BR.js
+++ b/apps/files_external/l10n/pt_BR.js
@@ -78,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP com chave secreta de login [DEPRECATED]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Compartilhar",
+ "Domain" : "Domínio",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS usando OC de login [DEPRECATED]",
"Username as share" : "Nome de usuário como compartilhado",
"OpenStack Object Storage" : "Armazenamento de Objetos OpenStack",
diff --git a/apps/files_external/l10n/pt_BR.json b/apps/files_external/l10n/pt_BR.json
index a863e6abffb..bb4c5b88a2d 100644
--- a/apps/files_external/l10n/pt_BR.json
+++ b/apps/files_external/l10n/pt_BR.json
@@ -76,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP com chave secreta de login [DEPRECATED]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "Compartilhar",
+ "Domain" : "Domínio",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS usando OC de login [DEPRECATED]",
"Username as share" : "Nome de usuário como compartilhado",
"OpenStack Object Storage" : "Armazenamento de Objetos OpenStack",
diff --git a/apps/files_external/l10n/th_TH.js b/apps/files_external/l10n/th_TH.js
index 34c1f74ecf8..89308e5889c 100644
--- a/apps/files_external/l10n/th_TH.js
+++ b/apps/files_external/l10n/th_TH.js
@@ -78,6 +78,7 @@ OC.L10N.register(
"SFTP with secret key login [DEPRECATED]" : "SFTP กับรหัสลับเข้าสู่ระบบ [ยกเลิก]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "แชร์",
+ "Domain" : "โดเมน",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS กำลังใช้ OC เข้าสู่ระบบ [ยกเลิก]",
"Username as share" : "ชื่อผู้ใช้ที่แชร์",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/l10n/th_TH.json b/apps/files_external/l10n/th_TH.json
index cb18b221c4a..5b167001e4e 100644
--- a/apps/files_external/l10n/th_TH.json
+++ b/apps/files_external/l10n/th_TH.json
@@ -76,6 +76,7 @@
"SFTP with secret key login [DEPRECATED]" : "SFTP กับรหัสลับเข้าสู่ระบบ [ยกเลิก]",
"SMB / CIFS" : "SMB / CIFS",
"Share" : "แชร์",
+ "Domain" : "โดเมน",
"SMB / CIFS using OC login [DEPRECATED]" : "SMB / CIFS กำลังใช้ OC เข้าสู่ระบบ [ยกเลิก]",
"Username as share" : "ชื่อผู้ใช้ที่แชร์",
"OpenStack Object Storage" : "OpenStack Object Storage",
diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php
index 7c6ac4cbdd5..34e8974a6d5 100644
--- a/apps/files_external/lib/amazons3.php
+++ b/apps/files_external/lib/amazons3.php
@@ -592,7 +592,10 @@ class AmazonS3 extends \OC\Files\Storage\Common {
'key' => $this->params['key'],
'secret' => $this->params['secret'],
'base_url' => $base_url,
- 'region' => $this->params['region']
+ 'region' => $this->params['region'],
+ S3Client::COMMAND_PARAMS => [
+ 'PathStyle' => $this->params['use_path_style'],
+ ],
));
if (!$this->connection->isValidBucketName($this->bucket)) {
diff --git a/apps/files_external/lib/config/configadapter.php b/apps/files_external/lib/config/configadapter.php
index a255a7b3d25..cb8c2f24caa 100644
--- a/apps/files_external/lib/config/configadapter.php
+++ b/apps/files_external/lib/config/configadapter.php
@@ -114,7 +114,7 @@ class ConfigAdapter implements IMountProvider {
$this->userStoragesService->setUser($user);
$this->userGlobalStoragesService->setUser($user);
- foreach ($this->userGlobalStoragesService->getAllStorages() as $storage) {
+ foreach ($this->userGlobalStoragesService->getUniqueStorages() as $storage) {
try {
$this->prepareStorageConfig($storage, $user);
$impl = $this->constructStorage($storage);
diff --git a/apps/files_external/service/userglobalstoragesservice.php b/apps/files_external/service/userglobalstoragesservice.php
index c59652d057f..b60473f131e 100644
--- a/apps/files_external/service/userglobalstoragesservice.php
+++ b/apps/files_external/service/userglobalstoragesservice.php
@@ -26,6 +26,7 @@ use \OCA\Files_External\Service\BackendService;
use \OCP\IUserSession;
use \OCP\IGroupManager;
use \OCA\Files_External\Service\UserTrait;
+use \OCA\Files_External\Lib\StorageConfig;
/**
* Service class to read global storages applicable to the user
@@ -109,4 +110,60 @@ class UserGlobalStoragesService extends GlobalStoragesService {
throw new \DomainException('UserGlobalStoragesService writing disallowed');
}
+ /**
+ * Get unique storages, in case two are defined with the same mountpoint
+ * Higher priority storages take precedence
+ *
+ * @return StorageConfig[]
+ */
+ public function getUniqueStorages() {
+ $storages = $this->getAllStorages();
+
+ $storagesByMountpoint = [];
+ foreach ($storages as $storage) {
+ $storagesByMountpoint[$storage->getMountPoint()][] = $storage;
+ }
+
+ $result = [];
+ foreach ($storagesByMountpoint as $storageList) {
+ $storage = array_reduce($storageList, function($carry, $item) {
+ if (isset($carry)) {
+ $carryPriorityType = $this->getPriorityType($carry);
+ $itemPriorityType = $this->getPriorityType($item);
+ if ($carryPriorityType > $itemPriorityType) {
+ return $carry;
+ } elseif ($carryPriorityType === $itemPriorityType) {
+ if ($carry->getPriority() > $item->getPriority()) {
+ return $carry;
+ }
+ }
+ }
+ return $item;
+ });
+ $result[$storage->getID()] = $storage;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get a priority 'type', where a bigger number means higher priority
+ * user applicable > group applicable > 'all'
+ *
+ * @param StorageConfig $storage
+ * @return int
+ */
+ protected function getPriorityType(StorageConfig $storage) {
+ $applicableUsers = $storage->getApplicableUsers();
+ $applicableGroups = $storage->getApplicableGroups();
+
+ if ($applicableUsers && $applicableUsers[0] !== 'all') {
+ return 2;
+ }
+ if ($applicableGroups) {
+ return 1;
+ }
+ return 0;
+ }
+
}
diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php
index 63a3a19de2f..7762ff60333 100644
--- a/apps/files_external/templates/settings.php
+++ b/apps/files_external/templates/settings.php
@@ -23,14 +23,14 @@
<?php
break;
case DefinitionParameter::VALUE_BOOLEAN: ?>
- <label>
- <input type="checkbox"
- <?php if (!empty($classes)): ?> class="<?php p(implode(' ', $classes)); ?>"<?php endif; ?>
- data-parameter="<?php p($parameter->getName()); ?>"
- <?php if ($value === true): ?> checked="checked"<?php endif; ?>
- />
- <?php p($placeholder); ?>
- </label>
+ <?php $checkboxId = uniqid("checkbox_"); ?>
+ <input type="checkbox"
+ id="<?php p($checkboxId); ?>"
+ <?php if (!empty($classes)): ?> class="<?php p(implode(' ', $classes)); ?>"<?php endif; ?>
+ data-parameter="<?php p($parameter->getName()); ?>"
+ <?php if ($value === true): ?> checked="checked"<?php endif; ?>
+ />
+ <label for="<?php p($checkboxId); ?>"><?php p($placeholder); ?></label>
<?php
break;
case DefinitionParameter::VALUE_HIDDEN: ?>
diff --git a/apps/files_external/tests/backends/amazons3.php b/apps/files_external/tests/backends/amazons3.php
index 1923ddc30b1..7e88f3d0b74 100644
--- a/apps/files_external/tests/backends/amazons3.php
+++ b/apps/files_external/tests/backends/amazons3.php
@@ -32,11 +32,11 @@ class AmazonS3 extends Storage {
protected function setUp() {
parent::setUp();
- $this->config = include('files_external/tests/config.php');
- if ( ! is_array($this->config) or ! isset($this->config['amazons3']) or ! $this->config['amazons3']['run']) {
+ $this->config = include('files_external/tests/config.amazons3.php');
+ if ( ! is_array($this->config) or ! $this->config['run']) {
$this->markTestSkipped('AmazonS3 backend not configured');
}
- $this->instance = new \OC\Files\Storage\AmazonS3($this->config['amazons3']);
+ $this->instance = new \OC\Files\Storage\AmazonS3($this->config);
}
protected function tearDown() {
diff --git a/apps/files_external/tests/env/start-amazons3-ceph.sh b/apps/files_external/tests/env/start-amazons3-ceph.sh
new file mode 100755
index 00000000000..5f274f10ca2
--- /dev/null
+++ b/apps/files_external/tests/env/start-amazons3-ceph.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script start a docker container to test the files_external tests
+# against. It will also change the files_external config to use the docker
+# container as testing environment. This is reverted in the stop step.W
+#
+# Set environment variable DEBUG to print config file
+#
+# @author Morris Jobke
+# @author Robin McCorkell
+# @copyright 2015 ownCloud
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker setup"
+ exit 0;
+fi
+
+echo "Docker executable found - setup docker"
+
+docker_image=xenopathic/ceph-keystone
+
+echo "Fetch recent ${docker_image} docker image"
+docker pull ${docker_image}
+
+# retrieve current folder to place the config in the parent folder
+thisFolder=`echo $0 | replace "env/start-amazons3-ceph.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+user=test
+accesskey=aaabbbccc
+secretkey=cccbbbaaa
+bucket=testbucket
+port=80
+
+container=`docker run -d \
+ -e RGW_CIVETWEB_PORT=$port \
+ ${docker_image}`
+
+host=`docker inspect $container | grep IPAddress | cut -d '"' -f 4`
+
+
+echo "${docker_image} container: $container"
+
+# put container IDs into a file to drop them after the test run (keep in mind that multiple tests run in parallel on the same host)
+echo $container >> $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.amazons3
+
+# TODO find a way to determine the successful initialization inside the docker container
+echo "Waiting 20 seconds for ceph initialization ... "
+sleep 20
+
+echo "Create ceph user"
+docker exec $container radosgw-admin user create \
+ --uid="$user" --display-name="$user" \
+ --access-key="$accesskey" --secret="$secretkey" \
+ >/dev/null
+
+cat > $thisFolder/config.amazons3.php <<DELIM
+<?php
+
+return array(
+ 'run'=>true,
+ 'bucket'=>'$bucket',
+ 'hostname'=>'$host',
+ 'port'=>'$port',
+ 'key'=>'$accesskey',
+ 'secret'=>'$secretkey',
+ 'use_ssl'=>false,
+ 'use_path_style'=>true,
+);
+
+DELIM
+
+if [ -n "$DEBUG" ]; then
+ cat $thisFolder/config.amazons3.php
+ cat $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.amazons3
+fi
diff --git a/apps/files_external/tests/env/stop-amazons3-ceph.sh b/apps/files_external/tests/env/stop-amazons3-ceph.sh
new file mode 100755
index 00000000000..01b39b4c680
--- /dev/null
+++ b/apps/files_external/tests/env/stop-amazons3-ceph.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# ownCloud
+#
+# This script stops the docker container the files_external tests were run
+# against. It will also revert the config changes done in start step.
+#
+# @author Morris Jobke
+# @author Robin McCorkell
+# @copyright 2015 ownCloud
+
+if ! command -v docker >/dev/null 2>&1; then
+ echo "No docker executable found - skipped docker stop"
+ exit 0;
+fi
+
+echo "Docker executable found - stop and remove docker containers"
+
+# retrieve current folder to remove the config from the parent folder
+thisFolder=`echo $0 | replace "env/stop-amazons3-ceph.sh" ""`
+
+if [ -z "$thisFolder" ]; then
+ thisFolder="."
+fi;
+
+# stopping and removing docker containers
+for container in `cat $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.amazons3`; do
+ echo "Stopping and removing docker container $container"
+ # kills running container and removes it
+ docker rm -f $container
+done;
+
+# cleanup
+rm $thisFolder/config.amazons3.php
+rm $thisFolder/dockerContainerCeph.$EXECUTOR_NUMBER.amazons3
+
diff --git a/apps/files_external/tests/service/userglobalstoragesservicetest.php b/apps/files_external/tests/service/userglobalstoragesservicetest.php
index b9e2c08c932..867872f3683 100644
--- a/apps/files_external/tests/service/userglobalstoragesservicetest.php
+++ b/apps/files_external/tests/service/userglobalstoragesservicetest.php
@@ -35,6 +35,7 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
const USER_ID = 'test_user';
const GROUP_ID = 'test_group';
+ const GROUP_ID2 = 'test_group2';
public function setUp() {
parent::setUp();
@@ -51,8 +52,12 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$this->groupManager = $this->getMock('\OCP\IGroupManager');
$this->groupManager->method('isInGroup')
->will($this->returnCallback(function($userId, $groupId) {
- if ($userId === self::USER_ID && $groupId === self::GROUP_ID) {
- return true;
+ if ($userId === self::USER_ID) {
+ switch ($groupId) {
+ case self::GROUP_ID:
+ case self::GROUP_ID2:
+ return true;
+ }
}
return false;
}));
@@ -167,6 +172,77 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
$this->service->removeStorage(1);
}
+ public function getUniqueStoragesProvider() {
+ return [
+ // 'all' vs group
+ [100, [], [], 100, [], [self::GROUP_ID], 2],
+ [100, [], [self::GROUP_ID], 100, [], [], 1],
+
+ // 'all' vs user
+ [100, [], [], 100, [self::USER_ID], [], 2],
+ [100, [self::USER_ID], [], 100, [], [], 1],
+
+ // group vs user
+ [100, [], [self::GROUP_ID], 100, [self::USER_ID], [], 2],
+ [100, [self::USER_ID], [], 100, [], [self::GROUP_ID], 1],
+
+ // group+user vs group
+ [100, [], [self::GROUP_ID2], 100, [self::USER_ID], [self::GROUP_ID], 2],
+ [100, [self::USER_ID], [self::GROUP_ID], 100, [], [self::GROUP_ID2], 1],
+
+ // user vs 'all' (higher priority)
+ [200, [], [], 100, [self::USER_ID], [], 2],
+ [100, [self::USER_ID], [], 200, [], [], 1],
+
+ // group vs group (higher priority)
+ [100, [], [self::GROUP_ID2], 200, [], [self::GROUP_ID], 2],
+ [200, [], [self::GROUP_ID], 100, [], [self::GROUP_ID2], 1],
+ ];
+ }
+
+ /**
+ * @dataProvider getUniqueStoragesProvider
+ */
+ public function testGetUniqueStorages(
+ $priority1, $applicableUsers1, $applicableGroups1,
+ $priority2, $applicableUsers2, $applicableGroups2,
+ $expectedPrecedence
+ ) {
+ $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
+ $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
+
+ $storage1 = new StorageConfig();
+ $storage1->setMountPoint('mountpoint');
+ $storage1->setBackend($backend);
+ $storage1->setAuthMechanism($authMechanism);
+ $storage1->setBackendOptions(['password' => 'testPassword']);
+ $storage1->setPriority($priority1);
+ $storage1->setApplicableUsers($applicableUsers1);
+ $storage1->setApplicableGroups($applicableGroups1);
+
+ $storage1 = $this->globalStoragesService->addStorage($storage1);
+
+ $storage2 = new StorageConfig();
+ $storage2->setMountPoint('mountpoint');
+ $storage2->setBackend($backend);
+ $storage2->setAuthMechanism($authMechanism);
+ $storage2->setBackendOptions(['password' => 'testPassword']);
+ $storage2->setPriority($priority2);
+ $storage2->setApplicableUsers($applicableUsers2);
+ $storage2->setApplicableGroups($applicableGroups2);
+
+ $storage2 = $this->globalStoragesService->addStorage($storage2);
+
+ $storages = $this->service->getUniqueStorages();
+ $this->assertCount(1, $storages);
+
+ if ($expectedPrecedence === 1) {
+ $this->assertArrayHasKey($storage1->getID(), $storages);
+ } elseif ($expectedPrecedence === 2) {
+ $this->assertArrayHasKey($storage2->getID(), $storages);
+ }
+ }
+
public function testHooksAddStorage($a = null, $b = null, $c = null) {
// we don't test this here
$this->assertTrue(true);
diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php
index 6ecaea20535..7d8860ad6ff 100644
--- a/apps/files_sharing/api/server2server.php
+++ b/apps/files_sharing/api/server2server.php
@@ -83,6 +83,8 @@ class Server2Server {
Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_RECEIVED, array($user, trim($name, '/')), '', array(),
'', '', $shareWith, Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_LOW);
+ /**
+ * FIXME
$urlGenerator = \OC::$server->getURLGenerator();
$notificationManager = \OC::$server->getNotificationManager();
@@ -93,17 +95,18 @@ class Server2Server {
->setObject('remote_share', $remoteId)
->setSubject('remote_share', [$user, trim($name, '/')]);
- $acceptAction = $notification->createAction();
- $acceptAction->setLabel('accept')
- ->setLink($urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/remote_shares/' . $remoteId), 'POST');
$declineAction = $notification->createAction();
$declineAction->setLabel('decline')
->setLink($urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/remote_shares/' . $remoteId), 'DELETE');
+ $notification->addAction($declineAction);
- $notification->addAction($acceptAction)
- ->addAction($declineAction);
+ $acceptAction = $notification->createAction();
+ $acceptAction->setLabel('accept')
+ ->setLink($urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/remote_shares/' . $remoteId), 'POST');
+ $notification->addAction($acceptAction);
$notificationManager->notify($notification);
+ */
return new \OC_OCS_Result();
} catch (\Exception $e) {
diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php
index 924a9dd1cd7..9e324078dad 100644
--- a/apps/files_sharing/api/sharees.php
+++ b/apps/files_sharing/api/sharees.php
@@ -20,6 +20,7 @@
*/
namespace OCA\Files_Sharing\API;
+use OCP\AppFramework\Http;
use OCP\Contacts\IManager;
use OCP\IGroup;
use OCP\IGroupManager;
@@ -291,8 +292,15 @@ class Sharees {
public function search() {
$search = isset($_GET['search']) ? (string) $_GET['search'] : '';
$itemType = isset($_GET['itemType']) ? (string) $_GET['itemType'] : null;
- $page = !empty($_GET['page']) ? max(1, (int) $_GET['page']) : 1;
- $perPage = !empty($_GET['perPage']) ? max(1, (int) $_GET['perPage']) : 200;
+ $page = isset($_GET['page']) ? (int) $_GET['page'] : 1;
+ $perPage = isset($_GET['perPage']) ? (int) $_GET['perPage'] : 200;
+
+ if ($perPage <= 0) {
+ return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid perPage argument');
+ }
+ if ($page <= 0) {
+ return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Invalid page');
+ }
$shareTypes = [
Share::SHARE_TYPE_USER,
@@ -348,7 +356,7 @@ class Sharees {
protected function searchSharees($search, $itemType, array $shareTypes, $page, $perPage) {
// Verify arguments
if ($itemType === null) {
- return new \OC_OCS_Result(null, 400, 'missing itemType');
+ return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST, 'Missing itemType');
}
// Get users
diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php
index 8d919d1466f..15c0b864b08 100644
--- a/apps/files_sharing/appinfo/app.php
+++ b/apps/files_sharing/appinfo/app.php
@@ -113,9 +113,12 @@ if ($config->getAppValue('core', 'shareapi_enabled', 'yes') === 'yes') {
}
}
+/**
+ * FIXME
$manager = \OC::$server->getNotificationManager();
$manager->registerNotifier(function() {
return new \OCA\Files_Sharing\Notifier(
\OC::$server->getL10NFactory()
);
});
+ */
diff --git a/apps/files_sharing/css/sharetabview.css b/apps/files_sharing/css/sharetabview.css
index 0cc812e917c..fe7a1947502 100644
--- a/apps/files_sharing/css/sharetabview.css
+++ b/apps/files_sharing/css/sharetabview.css
@@ -12,22 +12,25 @@
}
.shareTabView .shareWithRemoteInfo {
- padding: 11px 0 11px 10px
+ padding: 11px 20px;
}
.shareTabView label {
- font-weight:400;
white-space: nowrap;
}
.shareTabView input[type="checkbox"] {
- margin:0 3px 0 8px;
+ margin: 0 3px 0 8px;
vertical-align: middle;
}
-.shareTabView input[type="text"], .shareTabView input[type="password"] {
- width: 91%;
- margin-left: 7px;
+.shareTabView input[type="text"],
+.shareTabView input[type="password"] {
+ width: 94%;
+ margin-left: 0;
+}
+.shareTabView #shareWith {
+ width: 80%;
}
.shareTabView form {
@@ -37,15 +40,14 @@
}
#shareWithList {
- list-style-type:none;
- padding:8px;
+ list-style-type: none;
+ padding: 0 0 16px;
}
#shareWithList li {
- padding-top: 10px;
- padding-bottom: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
font-weight: bold;
- line-height: 21px;
white-space: normal;
}
diff --git a/apps/files_sharing/l10n/da.js b/apps/files_sharing/l10n/da.js
index 7b54b361d8d..d31acc37760 100644
--- a/apps/files_sharing/l10n/da.js
+++ b/apps/files_sharing/l10n/da.js
@@ -38,6 +38,9 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "Den offentligt delte fil %1$s blev downloadet",
"You shared %1$s with %2$s" : "Du delte %1$s med %2$s",
"You shared %1$s with group %2$s" : "Du delte %1$s med gruppen %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s delt %1$s med %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s delt %1$s med gruppen %3$s",
+ "%2$s shared %1$s via link" : "%2$s delt %1$s via link",
"%2$s shared %1$s with you" : "%2$s delt %1$s med dig",
"You shared %1$s via link" : "Du delte %1$s via link",
"Shares" : "Delt",
diff --git a/apps/files_sharing/l10n/da.json b/apps/files_sharing/l10n/da.json
index f430935e8bc..fe702de52e8 100644
--- a/apps/files_sharing/l10n/da.json
+++ b/apps/files_sharing/l10n/da.json
@@ -36,6 +36,9 @@
"Public shared file %1$s was downloaded" : "Den offentligt delte fil %1$s blev downloadet",
"You shared %1$s with %2$s" : "Du delte %1$s med %2$s",
"You shared %1$s with group %2$s" : "Du delte %1$s med gruppen %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s delt %1$s med %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s delt %1$s med gruppen %3$s",
+ "%2$s shared %1$s via link" : "%2$s delt %1$s via link",
"%2$s shared %1$s with you" : "%2$s delt %1$s med dig",
"You shared %1$s via link" : "Du delte %1$s via link",
"Shares" : "Delt",
diff --git a/apps/files_sharing/l10n/fi_FI.js b/apps/files_sharing/l10n/fi_FI.js
index 060efce51dd..2e4a32480b1 100644
--- a/apps/files_sharing/l10n/fi_FI.js
+++ b/apps/files_sharing/l10n/fi_FI.js
@@ -38,6 +38,9 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "Julkisesti jaettu tiedosto %1$s ladattiin",
"You shared %1$s with %2$s" : "Jaoit kohteen %1$s käyttäjän %2$s kanssa",
"You shared %1$s with group %2$s" : "Jaoit kohteen %1$s ryhmän %2$s kanssa",
+ "%2$s shared %1$s with %3$s" : "%2$s jakoi kohteen %1$s käyttäjän %3$s kanssa",
+ "%2$s shared %1$s with group %3$s" : "%2$s jakoi kohteen %1$s ryhmän %3$s kanssa",
+ "%2$s shared %1$s via link" : "%2$s jakoi kohteen %1$s linkin kautta",
"%2$s shared %1$s with you" : "%2$s jakoi kohteen %1$s kanssasi",
"You shared %1$s via link" : "Jaoit kohteen %1$s linkin kautta",
"Shares" : "Jaot",
diff --git a/apps/files_sharing/l10n/fi_FI.json b/apps/files_sharing/l10n/fi_FI.json
index 091f7aec81f..2b938d95c0e 100644
--- a/apps/files_sharing/l10n/fi_FI.json
+++ b/apps/files_sharing/l10n/fi_FI.json
@@ -36,6 +36,9 @@
"Public shared file %1$s was downloaded" : "Julkisesti jaettu tiedosto %1$s ladattiin",
"You shared %1$s with %2$s" : "Jaoit kohteen %1$s käyttäjän %2$s kanssa",
"You shared %1$s with group %2$s" : "Jaoit kohteen %1$s ryhmän %2$s kanssa",
+ "%2$s shared %1$s with %3$s" : "%2$s jakoi kohteen %1$s käyttäjän %3$s kanssa",
+ "%2$s shared %1$s with group %3$s" : "%2$s jakoi kohteen %1$s ryhmän %3$s kanssa",
+ "%2$s shared %1$s via link" : "%2$s jakoi kohteen %1$s linkin kautta",
"%2$s shared %1$s with you" : "%2$s jakoi kohteen %1$s kanssasi",
"You shared %1$s via link" : "Jaoit kohteen %1$s linkin kautta",
"Shares" : "Jaot",
diff --git a/apps/files_sharing/l10n/it.js b/apps/files_sharing/l10n/it.js
index 0167ef4625d..d6fcab9c788 100644
--- a/apps/files_sharing/l10n/it.js
+++ b/apps/files_sharing/l10n/it.js
@@ -38,6 +38,9 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "Il file condiviso pubblicamente %1$s è stato scaricato",
"You shared %1$s with %2$s" : "Hai condiviso %1$s con %2$s",
"You shared %1$s with group %2$s" : "Hai condiviso %1$s con il gruppo %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s ha condiviso %1$s con %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s ha condiviso %1$s con il gruppo %3$s",
+ "%2$s shared %1$s via link" : "%2$s ha condiviso %1$s tramite collegamento",
"%2$s shared %1$s with you" : "%2$s ha condiviso %1$s con te",
"You shared %1$s via link" : "Hai condiviso %1$s tramite collegamento",
"Shares" : "Condivisioni",
@@ -46,7 +49,7 @@ OC.L10N.register(
"Decline" : "Rifiuta",
"Share with me through my #ownCloud Federated Cloud ID, see %s" : "Condividi con me attraverso il mio ID di cloud federata #ownCloud, vedi %s",
"Share with me through my #ownCloud Federated Cloud ID" : "Condividi con me attraverso il mio ID di cloud federata #ownCloud",
- "This share is password-protected" : "Questa condivione è protetta da password",
+ "This share is password-protected" : "Questa condivisione è protetta da password",
"The password is wrong. Try again." : "La password è errata. Prova ancora.",
"Password" : "Password",
"No entries found in this folder" : "Nessuna voce trovata in questa cartella",
diff --git a/apps/files_sharing/l10n/it.json b/apps/files_sharing/l10n/it.json
index ae26579572a..1ae87296032 100644
--- a/apps/files_sharing/l10n/it.json
+++ b/apps/files_sharing/l10n/it.json
@@ -36,6 +36,9 @@
"Public shared file %1$s was downloaded" : "Il file condiviso pubblicamente %1$s è stato scaricato",
"You shared %1$s with %2$s" : "Hai condiviso %1$s con %2$s",
"You shared %1$s with group %2$s" : "Hai condiviso %1$s con il gruppo %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s ha condiviso %1$s con %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s ha condiviso %1$s con il gruppo %3$s",
+ "%2$s shared %1$s via link" : "%2$s ha condiviso %1$s tramite collegamento",
"%2$s shared %1$s with you" : "%2$s ha condiviso %1$s con te",
"You shared %1$s via link" : "Hai condiviso %1$s tramite collegamento",
"Shares" : "Condivisioni",
@@ -44,7 +47,7 @@
"Decline" : "Rifiuta",
"Share with me through my #ownCloud Federated Cloud ID, see %s" : "Condividi con me attraverso il mio ID di cloud federata #ownCloud, vedi %s",
"Share with me through my #ownCloud Federated Cloud ID" : "Condividi con me attraverso il mio ID di cloud federata #ownCloud",
- "This share is password-protected" : "Questa condivione è protetta da password",
+ "This share is password-protected" : "Questa condivisione è protetta da password",
"The password is wrong. Try again." : "La password è errata. Prova ancora.",
"Password" : "Password",
"No entries found in this folder" : "Nessuna voce trovata in questa cartella",
diff --git a/apps/files_sharing/l10n/nb_NO.js b/apps/files_sharing/l10n/nb_NO.js
index b8b6c634959..a8f7fbdbc9b 100644
--- a/apps/files_sharing/l10n/nb_NO.js
+++ b/apps/files_sharing/l10n/nb_NO.js
@@ -38,9 +38,13 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "Offentlig delt fil %1$s ble lastet ned",
"You shared %1$s with %2$s" : "Du delte %1$s med %2$s",
"You shared %1$s with group %2$s" : "Du delte %1$s med gruppe %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s delte %1$s med %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s delte %1$s med gruppe %3$s",
+ "%2$s shared %1$s via link" : "%2$s delte %1$s via lenke",
"%2$s shared %1$s with you" : "%2$s delte %1$s med deg",
"You shared %1$s via link" : "Du delte %1$s via lenke",
"Shares" : "Delinger",
+ "You received %2$s as a remote share from %1$s" : "Du mottok %2$s som en ekstern deling fra %1$s",
"Accept" : "Aksepter",
"Decline" : "Avslå",
"Share with me through my #ownCloud Federated Cloud ID, see %s" : "Del med meg gjennom min #ownCloud ID for sammenknyttet sky, se %s",
diff --git a/apps/files_sharing/l10n/nb_NO.json b/apps/files_sharing/l10n/nb_NO.json
index 9382119e5c4..e9c67955708 100644
--- a/apps/files_sharing/l10n/nb_NO.json
+++ b/apps/files_sharing/l10n/nb_NO.json
@@ -36,9 +36,13 @@
"Public shared file %1$s was downloaded" : "Offentlig delt fil %1$s ble lastet ned",
"You shared %1$s with %2$s" : "Du delte %1$s med %2$s",
"You shared %1$s with group %2$s" : "Du delte %1$s med gruppe %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s delte %1$s med %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s delte %1$s med gruppe %3$s",
+ "%2$s shared %1$s via link" : "%2$s delte %1$s via lenke",
"%2$s shared %1$s with you" : "%2$s delte %1$s med deg",
"You shared %1$s via link" : "Du delte %1$s via lenke",
"Shares" : "Delinger",
+ "You received %2$s as a remote share from %1$s" : "Du mottok %2$s som en ekstern deling fra %1$s",
"Accept" : "Aksepter",
"Decline" : "Avslå",
"Share with me through my #ownCloud Federated Cloud ID, see %s" : "Del med meg gjennom min #ownCloud ID for sammenknyttet sky, se %s",
diff --git a/apps/files_sharing/l10n/nl.js b/apps/files_sharing/l10n/nl.js
index 2ccddb5d9a7..f1edae5f8eb 100644
--- a/apps/files_sharing/l10n/nl.js
+++ b/apps/files_sharing/l10n/nl.js
@@ -38,6 +38,9 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "Openbaar gedeeld bestand %1$s werd gedownloaded",
"You shared %1$s with %2$s" : "U deelde %1$s met %2$s",
"You shared %1$s with group %2$s" : "U deelde %1$s met groep %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s deelde %1$s met %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s deelde %1$s met groep %3$s",
+ "%2$s shared %1$s via link" : "%2$s deelde %1$s via link",
"%2$s shared %1$s with you" : "%2$s deelde %1$s met u",
"You shared %1$s via link" : "U deelde %1$s via link",
"Shares" : "Gedeeld",
diff --git a/apps/files_sharing/l10n/nl.json b/apps/files_sharing/l10n/nl.json
index 53cd8954898..a285071ca30 100644
--- a/apps/files_sharing/l10n/nl.json
+++ b/apps/files_sharing/l10n/nl.json
@@ -36,6 +36,9 @@
"Public shared file %1$s was downloaded" : "Openbaar gedeeld bestand %1$s werd gedownloaded",
"You shared %1$s with %2$s" : "U deelde %1$s met %2$s",
"You shared %1$s with group %2$s" : "U deelde %1$s met groep %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s deelde %1$s met %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s deelde %1$s met groep %3$s",
+ "%2$s shared %1$s via link" : "%2$s deelde %1$s via link",
"%2$s shared %1$s with you" : "%2$s deelde %1$s met u",
"You shared %1$s via link" : "U deelde %1$s via link",
"Shares" : "Gedeeld",
diff --git a/apps/files_sharing/l10n/pt_BR.js b/apps/files_sharing/l10n/pt_BR.js
index bb455487186..cb167dfb5a4 100644
--- a/apps/files_sharing/l10n/pt_BR.js
+++ b/apps/files_sharing/l10n/pt_BR.js
@@ -38,6 +38,9 @@ OC.L10N.register(
"Public shared file %1$s was downloaded" : "O arquivo %1$s compartilhado publicamente foi baixado",
"You shared %1$s with %2$s" : "Você compartilhou %1$s com %2$s",
"You shared %1$s with group %2$s" : "Você compartilhou %1$s com o grupo %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s compartilhado %1$s com %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s compartilhado %1$s com o grupo %3$s",
+ "%2$s shared %1$s via link" : "%2$s compartilhado via link %1$s",
"%2$s shared %1$s with you" : "%2$s compartilhou %1$s com você",
"You shared %1$s via link" : "Você compartilhou %1$s via link",
"Shares" : "Compartilhamentos",
diff --git a/apps/files_sharing/l10n/pt_BR.json b/apps/files_sharing/l10n/pt_BR.json
index 7db2b1f0494..b42a56f03ce 100644
--- a/apps/files_sharing/l10n/pt_BR.json
+++ b/apps/files_sharing/l10n/pt_BR.json
@@ -36,6 +36,9 @@
"Public shared file %1$s was downloaded" : "O arquivo %1$s compartilhado publicamente foi baixado",
"You shared %1$s with %2$s" : "Você compartilhou %1$s com %2$s",
"You shared %1$s with group %2$s" : "Você compartilhou %1$s com o grupo %2$s",
+ "%2$s shared %1$s with %3$s" : "%2$s compartilhado %1$s com %3$s",
+ "%2$s shared %1$s with group %3$s" : "%2$s compartilhado %1$s com o grupo %3$s",
+ "%2$s shared %1$s via link" : "%2$s compartilhado via link %1$s",
"%2$s shared %1$s with you" : "%2$s compartilhou %1$s com você",
"You shared %1$s via link" : "Você compartilhou %1$s via link",
"Shares" : "Compartilhamentos",
diff --git a/apps/files_sharing/lib/activity.php b/apps/files_sharing/lib/activity.php
index 204c0a037b9..1257e7a445c 100644
--- a/apps/files_sharing/lib/activity.php
+++ b/apps/files_sharing/lib/activity.php
@@ -23,9 +23,9 @@
namespace OCA\Files_Sharing;
-use OC\L10N\Factory;
use OCP\Activity\IExtension;
use OCP\IURLGenerator;
+use OCP\L10N\IFactory;
class Activity implements IExtension {
const FILES_SHARING_APP = 'files_sharing';
@@ -55,19 +55,22 @@ class Activity implements IExtension {
const SUBJECT_SHARED_GROUP_SELF = 'shared_group_self';
const SUBJECT_SHARED_LINK_SELF = 'shared_link_self';
const SUBJECT_SHARED_USER_SELF = 'shared_user_self';
+ const SUBJECT_RESHARED_GROUP_BY = 'reshared_group_by';
+ const SUBJECT_RESHARED_LINK_BY = 'reshared_link_by';
+ const SUBJECT_RESHARED_USER_BY = 'reshared_user_by';
const SUBJECT_SHARED_WITH_BY = 'shared_with_by';
- /** @var Factory */
+ /** @var IFactory */
protected $languageFactory;
/** @var IURLGenerator */
protected $URLGenerator;
/**
- * @param Factory $languageFactory
+ * @param IFactory $languageFactory
* @param IURLGenerator $URLGenerator
*/
- public function __construct(Factory $languageFactory, IURLGenerator $URLGenerator) {
+ public function __construct(IFactory $languageFactory, IURLGenerator $URLGenerator) {
$this->languageFactory = $languageFactory;
$this->URLGenerator = $URLGenerator;
}
@@ -169,6 +172,12 @@ class Activity implements IExtension {
return (string) $l->t('You shared %1$s with %2$s', $params);
case self::SUBJECT_SHARED_GROUP_SELF:
return (string) $l->t('You shared %1$s with group %2$s', $params);
+ case self::SUBJECT_RESHARED_USER_BY:
+ return (string) $l->t('%2$s shared %1$s with %3$s', $params);
+ case self::SUBJECT_RESHARED_GROUP_BY:
+ return (string) $l->t('%2$s shared %1$s with group %3$s', $params);
+ case self::SUBJECT_RESHARED_LINK_BY:
+ return (string) $l->t('%2$s shared %1$s via link', $params);
case self::SUBJECT_SHARED_WITH_BY:
return (string) $l->t('%2$s shared %1$s with you', $params);
case self::SUBJECT_SHARED_LINK_SELF:
@@ -212,15 +221,35 @@ class Activity implements IExtension {
);
case self::SUBJECT_SHARED_LINK_SELF:
return [0 => 'file'];
+ case self::SUBJECT_RESHARED_LINK_BY:
+ return [
+ 0 => 'file',
+ 1 => 'username',
+ 2 => '',
+ ];
+
case self::SUBJECT_SHARED_USER_SELF:
case self::SUBJECT_SHARED_WITH_BY:
return [0 => 'file', 1 => 'username'];
+ case self::SUBJECT_RESHARED_USER_BY:
+ return [
+ 0 => 'file',
+ 1 => 'username',
+ 2 => 'username',
+ ];
case self::SUBJECT_SHARED_GROUP_SELF:
return [
0 => 'file',
1 => 'group',
];
+
+ case self::SUBJECT_RESHARED_GROUP_BY:
+ return [
+ 0 => 'file',
+ 1 => 'username',
+ 2 => 'group',
+ ];
}
}
@@ -245,6 +274,11 @@ class Activity implements IExtension {
case self::SUBJECT_SHARED_GROUP_SELF:
// Group by user/group
return 1;
+ case self::SUBJECT_RESHARED_USER_BY:
+ case self::SUBJECT_RESHARED_GROUP_BY:
+ // Group by user/group
+ // FIXME: Grouping does currently not work with more then 2 parameters
+ // return 2;
}
}
diff --git a/apps/files_sharing/lib/capabilities.php b/apps/files_sharing/lib/capabilities.php
index ea71c47a05c..b24eb8d61f0 100644
--- a/apps/files_sharing/lib/capabilities.php
+++ b/apps/files_sharing/lib/capabilities.php
@@ -67,6 +67,13 @@ class Capabilities implements ICapability {
$res['resharing'] = $this->config->getAppValue('core', 'shareapi_allow_resharing', 'yes') === 'yes';
+
+ //Federated sharing
+ $res['federation'] = [
+ 'outgoing' => $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes',
+ 'incoming' => $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes') === 'yes'
+ ];
+
return [
'files_sharing' => $res,
];
diff --git a/apps/files_sharing/lib/external/manager.php b/apps/files_sharing/lib/external/manager.php
index 17142e95099..8552b2fbd34 100644
--- a/apps/files_sharing/lib/external/manager.php
+++ b/apps/files_sharing/lib/external/manager.php
@@ -214,7 +214,7 @@ class Manager {
$acceptShare->execute(array(1, $mountPoint, $hash, $id, $this->uid));
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'accept');
- $this->scrapNotification($share['remote_id']);
+ //FIXME $this->scrapNotification($share['remote_id']);
return true;
}
@@ -237,7 +237,7 @@ class Manager {
$removeShare->execute(array($id, $this->uid));
$this->sendFeedbackToRemote($share['remote'], $share['share_token'], $share['remote_id'], 'decline');
- $this->scrapNotification($share['remote_id']);
+ //FIXME $this->scrapNotification($share['remote_id']);
return true;
}
diff --git a/apps/files_sharing/publicwebdav.php b/apps/files_sharing/publicwebdav.php
index eec158dd4b6..773a15c888e 100644
--- a/apps/files_sharing/publicwebdav.php
+++ b/apps/files_sharing/publicwebdav.php
@@ -39,7 +39,8 @@ $serverFactory = new \OC\Connector\Sabre\ServerFactory(
\OC::$server->getDatabaseConnection(),
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
- \OC::$server->getTagManager()
+ \OC::$server->getTagManager(),
+ \OC::$server->getEventDispatcher()
);
$requestUri = \OC::$server->getRequest()->getRequestUri();
diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php
index 1e28cb8ed5a..5c5d5b0d309 100644
--- a/apps/files_sharing/tests/api/shareestest.php
+++ b/apps/files_sharing/tests/api/shareestest.php
@@ -21,10 +21,9 @@
namespace OCA\Files_Sharing\Tests\API;
-use Doctrine\DBAL\Connection;
-use OC\Share\Constants;
use OCA\Files_Sharing\API\Sharees;
use OCA\Files_sharing\Tests\TestCase;
+use OCP\AppFramework\Http;
use OCP\Share;
class ShareesTest extends TestCase {
@@ -653,15 +652,6 @@ class ShareesTest extends TestCase {
// Test pagination
[[
- 'page' => 0,
- ], '', true, '', null, $allTypes, 1, 200, false],
- [[
- 'page' => '0',
- ], '', true, '', null, $allTypes, 1, 200, false],
- [[
- 'page' => -1,
- ], '', true, '', null, $allTypes, 1, 200, false],
- [[
'page' => 1,
], '', true, '', null, $allTypes, 1, 200, false],
[[
@@ -670,15 +660,6 @@ class ShareesTest extends TestCase {
// Test perPage
[[
- 'perPage' => 0,
- ], '', true, '', null, $allTypes, 1, 200, false],
- [[
- 'perPage' => '0',
- ], '', true, '', null, $allTypes, 1, 200, false],
- [[
- 'perPage' => -1,
- ], '', true, '', null, $allTypes, 1, 1, false],
- [[
'perPage' => 1,
], '', true, '', null, $allTypes, 1, 1, false],
[[
@@ -758,6 +739,75 @@ class ShareesTest extends TestCase {
$_GET = $oldGet;
}
+ public function dataSearchInvalid() {
+ return [
+ // Test invalid pagination
+ [[
+ 'page' => 0,
+ ], 'Invalid page'],
+ [[
+ 'page' => '0',
+ ], 'Invalid page'],
+ [[
+ 'page' => -1,
+ ], 'Invalid page'],
+
+ // Test invalid perPage
+ [[
+ 'perPage' => 0,
+ ], 'Invalid perPage argument'],
+ [[
+ 'perPage' => '0',
+ ], 'Invalid perPage argument'],
+ [[
+ 'perPage' => -1,
+ ], 'Invalid perPage argument'],
+ ];
+ }
+
+ /**
+ * @dataProvider dataSearchInvalid
+ *
+ * @param array $getData
+ * @param string $message
+ */
+ public function testSearchInvalid($getData, $message) {
+ $oldGet = $_GET;
+ $_GET = $getData;
+
+ $config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $config->expects($this->never())
+ ->method('getAppValue');
+
+ $sharees = $this->getMockBuilder('\OCA\Files_Sharing\API\Sharees')
+ ->setConstructorArgs([
+ $this->groupManager,
+ $this->userManager,
+ $this->contactsManager,
+ $config,
+ $this->session,
+ $this->getMockBuilder('OCP\IURLGenerator')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\IRequest')->disableOriginalConstructor()->getMock(),
+ $this->getMockBuilder('OCP\ILogger')->disableOriginalConstructor()->getMock()
+ ])
+ ->setMethods(array('searchSharees', 'isRemoteSharingAllowed'))
+ ->getMock();
+ $sharees->expects($this->never())
+ ->method('searchSharees');
+ $sharees->expects($this->never())
+ ->method('isRemoteSharingAllowed');
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCA\Files_Sharing\API\Sharees $sharees */
+ $ocs = $sharees->search();
+ $this->assertInstanceOf('\OC_OCS_Result', $ocs);
+
+ $this->assertOCSError($ocs, $message);
+
+ $_GET = $oldGet;
+ }
+
public function dataIsRemoteSharingAllowed() {
return [
['file', true],
@@ -940,13 +990,7 @@ class ShareesTest extends TestCase {
$ocs = $this->invokePrivate($this->sharees, 'searchSharees', ['', null, [], [], 0, 0, false]);
$this->assertInstanceOf('\OC_OCS_Result', $ocs);
- $this->assertSame(400, $ocs->getStatusCode(), 'Expected status code 400');
- $this->assertSame([], $ocs->getData(), 'Expected that no data is send');
-
- $meta = $ocs->getMeta();
- $this->assertNotEmpty($meta);
- $this->assertArrayHasKey('message', $meta);
- $this->assertSame('missing itemType', $meta['message']);
+ $this->assertOCSError($ocs, 'Missing itemType');
}
public function dataGetPaginationLink() {
@@ -992,4 +1036,18 @@ class ShareesTest extends TestCase {
$this->assertEquals($expected, $this->invokePrivate($this->sharees, 'isV2'));
}
+
+ /**
+ * @param \OC_OCS_Result $ocs
+ * @param string $message
+ */
+ protected function assertOCSError(\OC_OCS_Result $ocs, $message) {
+ $this->assertSame(Http::STATUS_BAD_REQUEST, $ocs->getStatusCode(), 'Expected status code 400');
+ $this->assertSame([], $ocs->getData(), 'Expected that no data is send');
+
+ $meta = $ocs->getMeta();
+ $this->assertNotEmpty($meta);
+ $this->assertArrayHasKey('message', $meta);
+ $this->assertSame($message, $meta['message']);
+ }
}
diff --git a/apps/files_sharing/tests/capabilities.php b/apps/files_sharing/tests/capabilities.php
index 5b9789ce324..f1a9626db9b 100644
--- a/apps/files_sharing/tests/capabilities.php
+++ b/apps/files_sharing/tests/capabilities.php
@@ -202,5 +202,40 @@ class FilesSharingCapabilitiesTest extends \Test\TestCase {
$this->assertFalse($result['public']['upload']);
}
+ public function testFederatedSharingIncomming() {
+ $map = [
+ ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'yes'],
+ ];
+ $result = $this->getResults($map);
+ $this->assertArrayHasKey('federation', $result);
+ $this->assertTrue($result['federation']['incoming']);
+ }
+
+ public function testFederatedSharingNoIncomming() {
+ $map = [
+ ['files_sharing', 'incoming_server2server_share_enabled', 'yes', 'no'],
+ ];
+ $result = $this->getResults($map);
+ $this->assertArrayHasKey('federation', $result);
+ $this->assertFalse($result['federation']['incoming']);
+ }
+
+ public function testFederatedSharingOutgoing() {
+ $map = [
+ ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'yes'],
+ ];
+ $result = $this->getResults($map);
+ $this->assertArrayHasKey('federation', $result);
+ $this->assertTrue($result['federation']['outgoing']);
+ }
+
+ public function testFederatedSharingNoOutgoing() {
+ $map = [
+ ['files_sharing', 'outgoing_server2server_share_enabled', 'yes', 'no'],
+ ];
+ $result = $this->getResults($map);
+ $this->assertArrayHasKey('federation', $result);
+ $this->assertFalse($result['federation']['outgoing']);
+ }
}
diff --git a/apps/files_trashbin/appinfo/app.php b/apps/files_trashbin/appinfo/app.php
index 8f079fe6120..4805f9eeafd 100644
--- a/apps/files_trashbin/appinfo/app.php
+++ b/apps/files_trashbin/appinfo/app.php
@@ -23,6 +23,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
$l = \OC::$server->getL10N('files_trashbin');
// register hooks
diff --git a/apps/files_trashbin/appinfo/install.php b/apps/files_trashbin/appinfo/install.php
new file mode 100644
index 00000000000..dc4c2847c22
--- /dev/null
+++ b/apps/files_trashbin/appinfo/install.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+ // Cron job for deleting expired trash items
+\OC::$server->getJobList()->add('OCA\Files_Trashbin\BackgroundJob\ExpireTrash');
diff --git a/apps/files_trashbin/appinfo/update.php b/apps/files_trashbin/appinfo/update.php
index b77210ae4c0..ae018a9da5d 100644
--- a/apps/files_trashbin/appinfo/update.php
+++ b/apps/files_trashbin/appinfo/update.php
@@ -46,3 +46,6 @@ if (version_compare($installedVersion, '0.6.4', '<')) {
$config->setSystemValue('trashbin_retention_obligation', $newObligation);
$config->deleteSystemValue('trashbin_auto_expire');
}
+
+// Cron job for deleting expired trash items
+\OC::$server->getJobList()->add('OCA\Files_Trashbin\BackgroundJob\ExpireTrash');
diff --git a/apps/files_trashbin/lib/backgroundjob/expiretrash.php b/apps/files_trashbin/lib/backgroundjob/expiretrash.php
new file mode 100644
index 00000000000..a222767669a
--- /dev/null
+++ b/apps/files_trashbin/lib/backgroundjob/expiretrash.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Files_Trashbin\BackgroundJob;
+
+use OCP\IConfig;
+use OCP\IUserManager;
+use OCA\Files_Trashbin\AppInfo\Application;
+use OCA\Files_Trashbin\Expiration;
+use OCA\Files_Trashbin\Helper;
+use OCA\Files_Trashbin\Trashbin;
+
+class ExpireTrash extends \OC\BackgroundJob\TimedJob {
+
+ const ITEMS_PER_SESSION = 1000;
+
+ /**
+ * @var Expiration
+ */
+ private $expiration;
+
+ /**
+ * @var IConfig
+ */
+ private $config;
+
+ /**
+ * @var IUserManager
+ */
+ private $userManager;
+
+ const USERS_PER_SESSION = 1000;
+
+ /**
+ * @param IConfig|null $config
+ * @param IUserManager|null $userManager
+ * @param Expiration|null $expiration
+ */
+ public function __construct(IConfig $config = null,
+ IUserManager $userManager = null,
+ Expiration $expiration = null) {
+ // Run once per 30 minutes
+ $this->setInterval(60 * 30);
+
+ if (is_null($expiration) || is_null($userManager) || is_null($config)) {
+ $this->fixDIForJobs();
+ } else {
+ $this->config = $config;
+ $this->userManager = $userManager;
+ $this->expiration = $expiration;
+ }
+ }
+
+ protected function fixDIForJobs() {
+ $application = new Application();
+ $this->config = \OC::$server->getConfig();
+ $this->userManager = \OC::$server->getUserManager();
+ $this->expiration = $application->getContainer()->query('Expiration');
+ }
+
+ /**
+ * @param $argument
+ * @throws \Exception
+ */
+ protected function run($argument) {
+ $maxAge = $this->expiration->getMaxAgeAsTimestamp();
+ if (!$maxAge) {
+ return;
+ }
+
+ $offset = $this->config->getAppValue('files_trashbin', 'cronjob_user_offset', 0);
+ $users = $this->userManager->search('', self::USERS_PER_SESSION, $offset);
+ if (!count($users)) {
+ // No users found, reset offset and retry
+ $offset = 0;
+ $users = $this->userManager->search('', self::USERS_PER_SESSION);
+ }
+
+ $offset += self::USERS_PER_SESSION;
+ $this->config->setAppValue('files_trashbin', 'cronjob_user_offset', $offset);
+
+ foreach ($users as $user) {
+ $uid = $user->getUID();
+ if (!$this->setupFS($uid)) {
+ continue;
+ }
+ $dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
+ Trashbin::deleteExpiredFiles($dirContent, $uid);
+ }
+
+ \OC_Util::tearDownFS();
+ }
+
+ /**
+ * Act on behalf on trash item owner
+ * @param string $user
+ * @return boolean
+ */
+ private function setupFS($user){
+ if (!$this->userManager->userExists($user)) {
+ return false;
+ }
+
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($user);
+
+ return true;
+ }
+}
diff --git a/apps/files_trashbin/lib/expiration.php b/apps/files_trashbin/lib/expiration.php
index 138540febf8..5069521aab3 100644
--- a/apps/files_trashbin/lib/expiration.php
+++ b/apps/files_trashbin/lib/expiration.php
@@ -105,6 +105,18 @@ class Expiration {
return $isOlderThanMax || $isMinReached;
}
+ /**
+ * @return bool|int
+ */
+ public function getMaxAgeAsTimestamp() {
+ $maxAge = false;
+ if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
+ $time = $this->timeFactory->getTime();
+ $maxAge = $time - ($this->maxAge * 86400);
+ }
+ return $maxAge;
+ }
+
private function parseRetentionObligation(){
$splitValues = explode(',', $this->retentionObligation);
if (!isset($splitValues[0])) {
diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php
index 2719eece2a8..3b2d4cf5929 100644
--- a/apps/files_trashbin/lib/trashbin.php
+++ b/apps/files_trashbin/lib/trashbin.php
@@ -689,7 +689,7 @@ class Trashbin {
* @param string $user
* @return array size of deleted files and number of deleted files
*/
- protected static function deleteExpiredFiles($files, $user) {
+ public static function deleteExpiredFiles($files, $user) {
$application = new Application();
$expiration = $application->getContainer()->query('Expiration');
$size = 0;
@@ -700,6 +700,10 @@ class Trashbin {
if ($expiration->isExpired($timestamp)) {
$count++;
$size += self::delete($filename, $user, $timestamp);
+ \OC::$server->getLogger()->info(
+ 'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.',
+ ['app' => 'files_trashbin']
+ );
} else {
break;
}
diff --git a/apps/files_trashbin/tests/backgroundjob/expiretrash.php b/apps/files_trashbin/tests/backgroundjob/expiretrash.php
new file mode 100644
index 00000000000..ad7b0fbca28
--- /dev/null
+++ b/apps/files_trashbin/tests/backgroundjob/expiretrash.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Files_Trashbin\Tests\BackgroundJob\ExpireTrash;
+
+use \OCA\Files_Trashbin\BackgroundJob\ExpireTrash;
+
+class ExpireTrash_Test extends \Test\TestCase {
+ public function testConstructAndRun() {
+ $backgroundJob = new ExpireTrash(
+ $this->getMock('OCP\IConfig'),
+ $this->getMock('OCP\IUserManager'),
+ $this->getMockBuilder('OCA\Files_Trashbin\Expiration')->disableOriginalConstructor()->getMock()
+ );
+
+ $jobList = $this->getMock('\OCP\BackgroundJob\IJobList');
+
+ /** @var \OC\BackgroundJob\JobList $jobList */
+ $backgroundJob->execute($jobList);
+ $this->assertTrue(true);
+ }
+}
diff --git a/apps/files_trashbin/tests/expiration.php b/apps/files_trashbin/tests/expiration.php
index 7bd51dccddd..b3c6fcd95af 100644
--- a/apps/files_trashbin/tests/expiration.php
+++ b/apps/files_trashbin/tests/expiration.php
@@ -24,6 +24,8 @@ use \OCA\Files_Trashbin\Expiration;
class Expiration_Test extends \PHPUnit_Framework_TestCase {
const SECONDS_PER_DAY = 86400; //60*60*24
+ const FAKE_TIME_NOW = 1000000;
+
public function expirationData(){
$today = 100*self::SECONDS_PER_DAY;
$back10Days = (100-10)*self::SECONDS_PER_DAY;
@@ -142,6 +144,38 @@ class Expiration_Test extends \PHPUnit_Framework_TestCase {
$this->assertAttributeEquals($expectedCanPurgeToSaveSpace, 'canPurgeToSaveSpace', $expiration);
}
+
+ public function timestampTestData(){
+ return [
+ [ 'disabled', false],
+ [ 'auto', false ],
+ [ 'auto,auto', false ],
+ [ 'auto, auto', false ],
+ [ 'auto, 3', self::FAKE_TIME_NOW - (3*self::SECONDS_PER_DAY) ],
+ [ '5, auto', false ],
+ [ '3, 5', self::FAKE_TIME_NOW - (5*self::SECONDS_PER_DAY) ],
+ [ '10, 3', self::FAKE_TIME_NOW - (10*self::SECONDS_PER_DAY) ],
+ ];
+ }
+
+
+ /**
+ * @dataProvider timestampTestData
+ *
+ * @param string $configValue
+ * @param int $expectedMaxAgeTimestamp
+ */
+ public function testGetMaxAgeAsTimestamp($configValue, $expectedMaxAgeTimestamp){
+ $mockedConfig = $this->getMockedConfig($configValue);
+ $mockedTimeFactory = $this->getMockedTimeFactory(
+ self::FAKE_TIME_NOW
+ );
+
+ $expiration = new Expiration($mockedConfig, $mockedTimeFactory);
+ $actualTimestamp = $expiration->getMaxAgeAsTimestamp();
+ $this->assertEquals($expectedMaxAgeTimestamp, $actualTimestamp);
+ }
+
/**
*
* @param int $time
diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php
index 967f2e73a34..eadc7c69a23 100644
--- a/apps/files_versions/appinfo/app.php
+++ b/apps/files_versions/appinfo/app.php
@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
-OCP\Util::addStyle('files_versions', 'versions');
+
+\OCP\Util::addStyle('files_versions', 'versions');
\OCA\Files_Versions\Hooks::connectHooks();
diff --git a/apps/files_versions/appinfo/install.php b/apps/files_versions/appinfo/install.php
new file mode 100644
index 00000000000..d72ba2f56e5
--- /dev/null
+++ b/apps/files_versions/appinfo/install.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+// Cron job for deleting expired trash items
+\OC::$server->getJobList()->add('OCA\Files_Versions\BackgroundJob\ExpireVersions');
diff --git a/apps/files_versions/appinfo/update.php b/apps/files_versions/appinfo/update.php
index 524f9bd153f..687e5d3b5d4 100644
--- a/apps/files_versions/appinfo/update.php
+++ b/apps/files_versions/appinfo/update.php
@@ -24,3 +24,6 @@ $installedVersion=OCP\Config::getAppValue('files_versions', 'installed_version')
if (version_compare($installedVersion, '1.0.4', '<')) {
\OC_DB::dropTable("files_versions");
}
+
+// Cron job for deleting expired trash items
+\OC::$server->getJobList()->add('OCA\Files_Versions\BackgroundJob\ExpireVersions');
diff --git a/apps/files_versions/css/versions.css b/apps/files_versions/css/versions.css
index ec0f0cc9896..b159de82ea3 100644
--- a/apps/files_versions/css/versions.css
+++ b/apps/files_versions/css/versions.css
@@ -13,9 +13,7 @@
}
.versionsTabView li > * {
- padding: 7px;
- float: left;
- vertical-align: top;
+ vertical-align: middle;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
filter: alpha(opacity=50);
opacity: .5;
@@ -23,7 +21,7 @@
.versionsTabView li > a,
.versionsTabView li > span {
- padding: 17px 7px;
+ padding: 15px 10px 11px;
}
.versionsTabView li > *:hover,
@@ -43,16 +41,13 @@
opacity: 1;
}
-.versionsTabView .versionDate {
+.versionsTabView .versiondate {
min-width: 100px;
- vertical-align: text-bottom;
+ vertical-align: super;
}
.versionsTabView .revertVersion {
cursor: pointer;
float: right;
- max-width: 130px;
- text-overflow: ellipsis;
- overflow: hidden;
+ margin-right: -10px;
}
-
diff --git a/apps/files_versions/js/versionstabview.js b/apps/files_versions/js/versionstabview.js
index 1f84428e616..f6a6f037988 100644
--- a/apps/files_versions/js/versionstabview.js
+++ b/apps/files_versions/js/versionstabview.js
@@ -15,7 +15,7 @@
'<a href="{{downloadUrl}}" class="downloadVersion"><img src="{{downloadIconUrl}}" />' +
'<span class="versiondate has-tooltip" title="{{formattedTimestamp}}">{{relativeTimestamp}}</span>' +
'</a>' +
- '<a href="#" class="revertVersion"><img src="{{revertIconUrl}}" />{{revertLabel}}</a>' +
+ '<a href="#" class="revertVersion" title="{{revertLabel}}"><img src="{{revertIconUrl}}" /></a>' +
'</li>';
var TEMPLATE =
@@ -195,4 +195,3 @@
OCA.Versions.VersionsTabView = VersionsTabView;
})();
-
diff --git a/apps/files_versions/lib/backgroundjob/expireversions.php b/apps/files_versions/lib/backgroundjob/expireversions.php
new file mode 100644
index 00000000000..afdd5eed57a
--- /dev/null
+++ b/apps/files_versions/lib/backgroundjob/expireversions.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @author Victor Dubiniuk <dubiniuk@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Files_Versions\BackgroundJob;
+
+use OCP\IUserManager;
+use OCA\Files_Versions\AppInfo\Application;
+use OCA\Files_Versions\Storage;
+use OCA\Files_Versions\Expiration;
+
+class ExpireVersions extends \OC\BackgroundJob\TimedJob {
+
+ const ITEMS_PER_SESSION = 1000;
+
+ /**
+ * @var Expiration
+ */
+ private $expiration;
+
+ /**
+ * @var IUserManager
+ */
+ private $userManager;
+
+ public function __construct(IUserManager $userManager = null, Expiration $expiration = null) {
+ // Run once per 30 minutes
+ $this->setInterval(60 * 30);
+
+ if (is_null($expiration) || is_null($userManager)) {
+ $this->fixDIForJobs();
+ } else {
+ $this->expiration = $expiration;
+ $this->userManager = $userManager;
+ }
+ }
+
+ protected function fixDIForJobs() {
+ $application = new Application();
+ $this->expiration = $application->getContainer()->query('Expiration');
+ $this->userManager = \OC::$server->getUserManager();
+ }
+
+ protected function run($argument) {
+ $maxAge = $this->expiration->getMaxAgeAsTimestamp();
+ if (!$maxAge) {
+ return;
+ }
+
+ $users = $this->userManager->search('');
+ $isFSready = false;
+ foreach ($users as $user) {
+ $uid = $user->getUID();
+ if (!$isFSready) {
+ if (!$this->setupFS($uid)) {
+ continue;
+ }
+ $isFSready = true;
+ }
+ Storage::expireOlderThanMaxForUser($uid);
+ }
+
+ \OC_Util::tearDownFS();
+ }
+
+ /**
+ * Act on behalf on trash item owner
+ * @param string $user
+ * @return boolean
+ */
+ private function setupFS($user){
+ if (!$this->userManager->userExists($user)) {
+ return false;
+ }
+
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($user);
+
+ return true;
+ }
+}
diff --git a/apps/files_versions/lib/expiration.php b/apps/files_versions/lib/expiration.php
index d42c62f0ee3..fba705251e9 100644
--- a/apps/files_versions/lib/expiration.php
+++ b/apps/files_versions/lib/expiration.php
@@ -113,6 +113,19 @@ class Expiration {
}
/**
+ * Get maximal retention obligation as a timestamp
+ * @return int
+ */
+ public function getMaxAgeAsTimestamp(){
+ $maxAge = false;
+ if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
+ $time = $this->timeFactory->getTime();
+ $maxAge = $time - ($this->maxAge * 86400);
+ }
+ return $maxAge;
+ }
+
+ /**
* Read versions_retention_obligation, validate it
* and set private members accordingly
*/
diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php
index ba2b78ff4d2..6aa58c55e9b 100644
--- a/apps/files_versions/lib/storage.php
+++ b/apps/files_versions/lib/storage.php
@@ -404,6 +404,38 @@ class Storage {
}
/**
+ * Expire versions that older than max version retention time
+ * @param string $uid
+ */
+ public static function expireOlderThanMaxForUser($uid){
+ $expiration = self::getExpiration();
+ $threshold = $expiration->getMaxAgeAsTimestamp();
+ $versions = self::getAllVersions($uid);
+ if (!$threshold || !array_key_exists('all', $versions)) {
+ return;
+ }
+
+ $toDelete = [];
+ foreach (array_reverse($versions['all']) as $key => $version) {
+ if (intval($version['version'])<$threshold) {
+ $toDelete[$key] = $version;
+ } else {
+ //Versions are sorted by time - nothing mo to iterate.
+ break;
+ }
+ }
+
+ $view = new \OC\Files\View('/' . $uid . '/files_versions');
+ if (!empty($toDelete)) {
+ foreach ($toDelete as $version) {
+ \OC_Hook::emit('\OCP\Versions', 'preDelete', array('path' => $version['path'].'.v'.$version['version']));
+ self::deleteVersion($view, $version['path'] . '.v' . $version['version']);
+ \OC_Hook::emit('\OCP\Versions', 'delete', array('path' => $version['path'].'.v'.$version['version']));
+ }
+ }
+ }
+
+ /**
* translate a timestamp into a string like "5 days ago"
* @param int $timestamp
* @return string for example "5 days ago"
diff --git a/core/command/encryption/decryptall.php b/core/command/encryption/decryptall.php
index 696570b7ae6..c71ba5f04c7 100644
--- a/core/command/encryption/decryptall.php
+++ b/core/command/encryption/decryptall.php
@@ -75,14 +75,22 @@ class DecryptAll extends Command {
$this->config = $config;
$this->decryptAll = $decryptAll;
$this->questionHelper = $questionHelper;
+ }
+ /**
+ * Set single user mode and disable the trashbin app
+ */
+ protected function forceSingleUserAndTrashbin() {
$this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin');
$this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false);
$this->config->setSystemValue('singleuser', true);
$this->appManager->disableApp('files_trashbin');
}
- public function __destruct() {
+ /**
+ * Reset the single user mode and re-enable the trashbin app
+ */
+ protected function resetSingleUserAndTrashbin() {
$this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled);
if ($this->wasTrashbinEnabled) {
$this->appManager->enableApp('files_trashbin');
@@ -115,7 +123,6 @@ class DecryptAll extends Command {
} else {
$output->writeln('Server side encryption not enabled. Nothing to do.');
return;
-
}
$output->writeln("\n");
@@ -126,12 +133,14 @@ class DecryptAll extends Command {
$output->writeln('');
$question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false);
if ($this->questionHelper->ask($input, $output, $question)) {
+ $this->forceSingleUserAndTrashbin();
$user = $input->getArgument('user');
$result = $this->decryptAll->decryptAll($input, $output, $user);
if ($result === false) {
- $this->output->writeln(' aborted.');
+ $output->writeln(' aborted.');
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
}
+ $this->resetSingleUserAndTrashbin();
} else {
$output->write('Enable server side encryption... ');
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
@@ -141,8 +150,9 @@ class DecryptAll extends Command {
} catch (\Exception $e) {
// enable server side encryption again if something went wrong
$this->config->setAppValue('core', 'encryption_enabled', 'yes');
+ $this->resetSingleUserAndTrashbin();
throw $e;
}
- }
+ }
}
diff --git a/core/command/encryption/encryptall.php b/core/command/encryption/encryptall.php
index 950ce5166d8..4ae6ae47836 100644
--- a/core/command/encryption/encryptall.php
+++ b/core/command/encryption/encryptall.php
@@ -67,13 +67,22 @@ class EncryptAll extends Command {
$this->encryptionManager = $encryptionManager;
$this->config = $config;
$this->questionHelper = $questionHelper;
+ }
+
+ /**
+ * Set single user mode and disable the trashbin app
+ */
+ protected function forceSingleUserAndTrashbin() {
$this->wasTrashbinEnabled = $this->appManager->isEnabledForUser('files_trashbin');
$this->wasSingleUserModeEnabled = $this->config->getSystemValue('singleuser', false);
$this->config->setSystemValue('singleuser', true);
$this->appManager->disableApp('files_trashbin');
}
- public function __destruct() {
+ /**
+ * Reset the single user mode and re-enable the trashbin app
+ */
+ protected function resetSingleUserAndTrashbin() {
$this->config->setSystemValue('singleuser', $this->wasSingleUserModeEnabled);
if ($this->wasTrashbinEnabled) {
$this->appManager->enableApp('files_trashbin');
@@ -104,8 +113,17 @@ class EncryptAll extends Command {
$output->writeln('');
$question = new ConfirmationQuestion('Do you really want to continue? (y/n) ', false);
if ($this->questionHelper->ask($input, $output, $question)) {
- $defaultModule = $this->encryptionManager->getEncryptionModule();
- $defaultModule->encryptAll($input, $output);
+ $this->forceSingleUserAndTrashbin();
+
+ try {
+ $defaultModule = $this->encryptionManager->getEncryptionModule();
+ $defaultModule->encryptAll($input, $output);
+ } catch (\Exception $ex) {
+ $this->resetSingleUserAndTrashbin();
+ throw $ex;
+ }
+
+ $this->resetSingleUserAndTrashbin();
} else {
$output->writeln('aborted');
}
diff --git a/core/css/share.css b/core/css/share.css
index 6467cc0239c..15f8061b068 100644
--- a/core/css/share.css
+++ b/core/css/share.css
@@ -41,10 +41,6 @@
display: none !important;
}
-.shareTabView .shareWithRemoteInfo {
- padding: 11px 20px;
-}
-
.shareTabView .avatar {
margin-right: 8px;
display: inline-block;
@@ -106,8 +102,9 @@ a.unshare {
display:inline;
float:right;
opacity:.5;
- padding:5px 0 0 5px !important;
- margin-top:-5px;
+ padding: 10px;
+ margin-top: -5px;
+ margin-right: -10px;
}
#link {
@@ -115,17 +112,10 @@ a.unshare {
padding-top:8px;
}
-.shareTabView input[type="text"],
-.shareTabView input[type="password"],
.shareTabView input[type="submit"] {
margin-left: 7px;
}
-.shareTabView input[type="text"],
-.shareTabView input[type="password"] {
- width: 86%;
-}
-
.shareTabView form {
font-size: 100%;
margin-left: 0;
diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js
index b0d1ca7d88f..552657877e7 100644
--- a/core/js/jquery.avatar.js
+++ b/core/js/jquery.avatar.js
@@ -77,7 +77,7 @@
var url = OC.generateUrl(
'/avatar/{user}/{size}',
- {user: user, size: size * window.devicePixelRatio});
+ {user: user, size: Math.ceil(size * window.devicePixelRatio)});
$.get(url, function(result) {
if (typeof(result) === 'object') {
diff --git a/core/js/share.js b/core/js/share.js
index a2e6e6af0fc..1131ae8f112 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -395,7 +395,7 @@ OC.Share = _.extend(OC.Share || {}, {
attributes: {
'data-item-source-name': filename,
'data-item-type': itemType,
- 'data-item-soruce': itemSource
+ 'data-item-source': itemSource
}
});
dialogView.setShowLink(link);
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index 41be49dc241..d2c45bb08b1 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -27,25 +27,31 @@
' {{/if}}' +
' <span class="username">{{shareWithDisplayName}}</span>' +
' {{#if mailPublicNotificationEnabled}} {{#unless isRemoteShare}}' +
- ' <label><input type="checkbox" name="mailNotification" class="mailNotification" {{#if wasMailSent}}checked="checked"{{/if}} />{{notifyByMailLabel}}</label>' +
+ ' <input id="mail-{{shareWith}}" type="checkbox" name="mailNotification" class="mailNotification" {{#if wasMailSent}}checked="checked"{{/if}} />' +
+ ' <label for="mail-{{shareWith}}">{{notifyByMailLabel}}</label>' +
' {{/unless}} {{/if}}' +
' {{#if isResharingAllowed}} {{#if sharePermissionPossible}} {{#unless isRemoteShare}}' +
- ' <label><input id="canShare-{{shareWith}}" type="checkbox" name="share" class="permissions" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />{{canShareLabel}}</label>' +
+ ' <input id="canShare-{{shareWith}}" type="checkbox" name="share" class="permissions" {{#if hasSharePermission}}checked="checked"{{/if}} data-permissions="{{sharePermission}}" />' +
+ ' <label for="canShare-{{shareWith}}">{{canShareLabel}}</label>' +
' {{/unless}} {{/if}} {{/if}}' +
' {{#if editPermissionPossible}}' +
- ' <label><input id="canEdit-{{shareWith}}" type="checkbox" name="edit" class="permissions" {{#if hasEditPermission}}checked="checked"{{/if}} />{{canEditLabel}}</label>' +
+ ' <input id="canEdit-{{shareWith}}" type="checkbox" name="edit" class="permissions" {{#if hasEditPermission}}checked="checked"{{/if}} />' +
+ ' <label for="canEdit-{{shareWith}}">{{canEditLabel}}</label>' +
' {{/if}}' +
' {{#unless isRemoteShare}}' +
' <a href="#" class="showCruds"><img class="svg" alt="{{crudsLabel}}" src="{{triangleSImage}}"/></a>' +
' <div class="cruds hidden">' +
' {{#if createPermissionPossible}}' +
- ' <label><input id="canCreate-{{shareWith}}" type="checkbox" name="create" class="permissions" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/>{{createPermissionLabel}}</label>' +
+ ' <input id="canCreate-{{shareWith}}" type="checkbox" name="create" class="permissions" {{#if hasCreatePermission}}checked="checked"{{/if}} data-permissions="{{createPermission}}"/>' +
+ ' <label for="canCreate-{{shareWith}}">{{createPermissionLabel}}</label>' +
' {{/if}}' +
' {{#if updatePermissionPossible}}' +
- ' <label><input id="canUpdate-{{shareWith}}" type="checkbox" name="update" class="permissions" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/>{{updatePermissionLabel}}</label>' +
+ ' <input id="canUpdate-{{shareWith}}" type="checkbox" name="update" class="permissions" {{#if hasUpdatePermission}}checked="checked"{{/if}} data-permissions="{{updatePermission}}"/>' +
+ ' <label for="canUpdate-{{shareWith}}">{{updatePermissionLabel}}</label>' +
' {{/if}}' +
' {{#if deletePermissionPossible}} {{#unless isRemoteShare}}' +
- ' <label><input id="canDelete-{{shareWith}}" type="checkbox" name="delete" class="permissions" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/>{{deletePermissionLabel}}</label>' +
+ ' <input id="canDelete-{{shareWith}}" type="checkbox" name="delete" class="permissions" {{#if hasDeletePermission}}checked="checked"{{/if}} data-permissions="{{deletePermission}}"/>' +
+ ' <label for="canDelete-{{shareWith}}">{{deletePermissionLabel}}</label>' +
' {{/unless}} {{/if}}' +
' </div>' +
' {{/unless}}' +
diff --git a/core/js/tests/specs/jquery.avatarSpec.js b/core/js/tests/specs/jquery.avatarSpec.js
new file mode 100644
index 00000000000..f5caae10020
--- /dev/null
+++ b/core/js/tests/specs/jquery.avatarSpec.js
@@ -0,0 +1,240 @@
+/**
+ * Copyright (c) 2015 Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+describe('jquery.avatar tests', function() {
+
+ var $div;
+ var devicePixelRatio
+
+ beforeEach(function() {
+ $('#testArea').append($('<div id="avatardiv">'));
+ $div = $('#avatardiv');
+
+ devicePixelRatio = window.devicePixelRatio;
+ window.devicePixelRatio = 1;
+ });
+
+ afterEach(function() {
+ $div.remove();
+
+ window.devicePixelRatio = devicePixelRatio
+ });
+
+ describe('size', function() {
+ it('undefined', function() {
+ $div.avatar('foo');
+
+ expect($div.height()).toEqual(64);
+ expect($div.width()).toEqual(64);
+ });
+
+ it('undefined but div has height', function() {
+ $div.height(9);
+ $div.avatar('foo');
+
+ expect($div.height()).toEqual(9);
+ expect($div.width()).toEqual(9);
+ });
+
+ it('undefined but data size is set', function() {
+ $div.data('size', 10);
+ $div.avatar('foo');
+
+ expect($div.height()).toEqual(10);
+ expect($div.width()).toEqual(10);
+ });
+
+
+ it('defined', function() {
+ $div.avatar('foo', 8);
+
+ expect($div.height()).toEqual(8);
+ expect($div.width()).toEqual(8);
+ });
+ });
+
+ it('undefined user', function() {
+ spyOn($div, 'imageplaceholder');
+
+ $div.avatar();
+
+ expect($div.imageplaceholder).toHaveBeenCalledWith('x');
+ });
+
+ describe('no avatar', function() {
+ it('show placeholder for existing user', function() {
+ spyOn($div, 'imageplaceholder');
+ $div.avatar('foo');
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({
+ data: {displayname: 'bar'}
+ })
+ );
+
+ expect($div.imageplaceholder).toHaveBeenCalledWith('foo', 'bar');
+ });
+
+ it('show placeholder for non existing user', function() {
+ spyOn($div, 'imageplaceholder');
+ $div.avatar('foo');
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({
+ data: {}
+ })
+ );
+
+ expect($div.imageplaceholder).toHaveBeenCalledWith('foo', 'X');
+ });
+
+ it('show no placeholder', function() {
+ spyOn($div, 'imageplaceholder');
+ $div.avatar('foo', undefined, undefined, true);
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'application/json' },
+ JSON.stringify({
+ data: {}
+ })
+ );
+
+ expect($div.imageplaceholder.calls.any()).toEqual(false);
+ expect($div.css('display')).toEqual('none');
+ });
+ });
+
+ describe('url generation', function() {
+ beforeEach(function() {
+ window.devicePixelRatio = 1;
+ });
+
+ it('default', function() {
+ window.devicePixelRatio = 1;
+ $div.avatar('foo', 32);
+
+ expect(fakeServer.requests[0].method).toEqual('GET');
+ expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/32');
+ });
+
+ it('high DPI icon', function() {
+ window.devicePixelRatio = 4;
+ $div.avatar('foo', 32);
+
+ expect(fakeServer.requests[0].method).toEqual('GET');
+ expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/128');
+ });
+
+ it('high DPI icon round up size', function() {
+ window.devicePixelRatio = 1.9;
+ $div.avatar('foo', 32);
+
+ expect(fakeServer.requests[0].method).toEqual('GET');
+ expect(fakeServer.requests[0].url).toEqual('http://localhost/index.php/avatar/foo/61');
+ });
+ });
+
+ describe('valid avatar', function() {
+ beforeEach(function() {
+ window.devicePixelRatio = 1;
+ });
+
+ it('default (no ie8 fix)', function() {
+ $div.avatar('foo', 32);
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'image/jpeg' },
+ ''
+ );
+
+ var img = $div.children('img')[0];
+
+ expect(img.height).toEqual(32);
+ expect(img.width).toEqual(32);
+ expect(img.src).toEqual('http://localhost/index.php/avatar/foo/32');
+ });
+
+ it('default high DPI icon', function() {
+ window.devicePixelRatio = 1.9;
+
+ $div.avatar('foo', 32);
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'image/jpeg' },
+ ''
+ );
+
+ var img = $div.children('img')[0];
+
+ expect(img.height).toEqual(32);
+ expect(img.width).toEqual(32);
+ expect(img.src).toEqual('http://localhost/index.php/avatar/foo/61');
+ });
+
+ it('with ie8 fix', function() {
+ sinon.stub(Math, 'random', function() {
+ return 0.5;
+ });
+
+ $div.avatar('foo', 32, true);
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'image/jpeg' },
+ ''
+ );
+
+ var img = $div.children('img')[0];
+
+ expect(img.height).toEqual(32);
+ expect(img.width).toEqual(32);
+ expect(img.src).toEqual('http://localhost/index.php/avatar/foo/32#500');
+ });
+
+ it('unhide div', function() {
+ $div.hide();
+
+ $div.avatar('foo', 32);
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'image/jpeg' },
+ ''
+ );
+
+ expect($div.css('display')).toEqual('block');
+ });
+
+ it('callback called', function() {
+ var observer = {callback: function() { dump("FOO"); }};
+
+ spyOn(observer, 'callback');
+
+ $div.avatar('foo', 32, undefined, undefined, function() {
+ observer.callback();
+ });
+
+ fakeServer.requests[0].respond(
+ 200,
+ { 'Content-Type': 'image/jpeg' },
+ ''
+ );
+
+ expect(observer.callback).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/core/l10n/da.js b/core/l10n/da.js
index 40407d2980d..5461275fb8e 100644
--- a/core/l10n/da.js
+++ b/core/l10n/da.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "tilpas",
"delete" : "slet",
"access control" : "Adgangskontrol",
+ "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.",
"An error occured. Please try again" : "Der skete en fejl. Prøv venligst igen",
"Share" : "Del",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med andre på ownCloud ved hjælp af syntaxen username@example.com/owncloud",
"Share with users or groups …" : "Del med brugere eller grupper",
"Share with users, groups or remote users …" : "Del med brugere, grupper eller eksterne brugere...",
"Warning" : "Advarsel",
+ "Error while sending notification" : "Fejl ved afsendelse af notifikation",
"The object type is not specified." : "Objekttypen er ikke angivet.",
"Enter new" : "Indtast nyt",
"Delete" : "Slet",
diff --git a/core/l10n/da.json b/core/l10n/da.json
index b8714521bbe..adf9fb314d5 100644
--- a/core/l10n/da.json
+++ b/core/l10n/da.json
@@ -143,12 +143,14 @@
"change" : "tilpas",
"delete" : "slet",
"access control" : "Adgangskontrol",
+ "Share details could not be loaded for this item." : "Detaljer for deling kunne ikke indlæses for dette element.",
"An error occured. Please try again" : "Der skete en fejl. Prøv venligst igen",
"Share" : "Del",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med andre på ownCloud ved hjælp af syntaxen username@example.com/owncloud",
"Share with users or groups …" : "Del med brugere eller grupper",
"Share with users, groups or remote users …" : "Del med brugere, grupper eller eksterne brugere...",
"Warning" : "Advarsel",
+ "Error while sending notification" : "Fejl ved afsendelse af notifikation",
"The object type is not specified." : "Objekttypen er ikke angivet.",
"Enter new" : "Indtast nyt",
"Delete" : "Slet",
diff --git a/core/l10n/fi_FI.js b/core/l10n/fi_FI.js
index 15c63679f21..826305c9b5a 100644
--- a/core/l10n/fi_FI.js
+++ b/core/l10n/fi_FI.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "muuta",
"delete" : "poista",
"access control" : "Pääsyn hallinta",
+ "Share details could not be loaded for this item." : "Tämän kohteen jakamistietoja ei voitu ladata.",
"An error occured. Please try again" : "Tapahtui virhe. Yritä myöhemmin uudestaan",
"Share" : "Jaa",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Jaa toisia ownCloud-järjestelmiä käyttävien kesken käyttäen syntaksia käyttäjätunnus@esimerkki.fi/owncloud",
"Share with users or groups …" : "Jaa käyttäjien tai ryhmien kanssa…",
"Share with users, groups or remote users …" : "Jaa käyttäjien, ryhmien tai etäkäyttäjien kanssa…",
"Warning" : "Varoitus",
+ "Error while sending notification" : "Virhe ilmoitusta lähettäessä",
"The object type is not specified." : "The object type is not specified.",
"Enter new" : "Kirjoita uusi",
"Delete" : "Poista",
diff --git a/core/l10n/fi_FI.json b/core/l10n/fi_FI.json
index 69045e7783f..c8a37ae2ef1 100644
--- a/core/l10n/fi_FI.json
+++ b/core/l10n/fi_FI.json
@@ -143,12 +143,14 @@
"change" : "muuta",
"delete" : "poista",
"access control" : "Pääsyn hallinta",
+ "Share details could not be loaded for this item." : "Tämän kohteen jakamistietoja ei voitu ladata.",
"An error occured. Please try again" : "Tapahtui virhe. Yritä myöhemmin uudestaan",
"Share" : "Jaa",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Jaa toisia ownCloud-järjestelmiä käyttävien kesken käyttäen syntaksia käyttäjätunnus@esimerkki.fi/owncloud",
"Share with users or groups …" : "Jaa käyttäjien tai ryhmien kanssa…",
"Share with users, groups or remote users …" : "Jaa käyttäjien, ryhmien tai etäkäyttäjien kanssa…",
"Warning" : "Varoitus",
+ "Error while sending notification" : "Virhe ilmoitusta lähettäessä",
"The object type is not specified." : "The object type is not specified.",
"Enter new" : "Kirjoita uusi",
"Delete" : "Poista",
diff --git a/core/l10n/it.js b/core/l10n/it.js
index cd3fc097c64..48fdf0e9b0c 100644
--- a/core/l10n/it.js
+++ b/core/l10n/it.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "cambia",
"delete" : "elimina",
"access control" : "controllo d'accesso",
+ "Share details could not be loaded for this item." : "I dettagli della condivisione non possono essere caricati per questo elemento.",
"An error occured. Please try again" : "Si è verificato un errore. Prova ancora",
"Share" : "Condividi",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Condividi con persone su altri ownCloud utilizzando la sintassi nomeutente@esempio.com/owncloud",
"Share with users or groups …" : "Condividi con utenti o gruppi...",
"Share with users, groups or remote users …" : "Condividi con utenti, gruppi o utenti remoti...",
"Warning" : "Avviso",
+ "Error while sending notification" : "Errore durante l'invio della notifica",
"The object type is not specified." : "Il tipo di oggetto non è specificato.",
"Enter new" : "Inserisci nuovo",
"Delete" : "Elimina",
diff --git a/core/l10n/it.json b/core/l10n/it.json
index 10049baf3ca..bedb6b8aa66 100644
--- a/core/l10n/it.json
+++ b/core/l10n/it.json
@@ -143,12 +143,14 @@
"change" : "cambia",
"delete" : "elimina",
"access control" : "controllo d'accesso",
+ "Share details could not be loaded for this item." : "I dettagli della condivisione non possono essere caricati per questo elemento.",
"An error occured. Please try again" : "Si è verificato un errore. Prova ancora",
"Share" : "Condividi",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Condividi con persone su altri ownCloud utilizzando la sintassi nomeutente@esempio.com/owncloud",
"Share with users or groups …" : "Condividi con utenti o gruppi...",
"Share with users, groups or remote users …" : "Condividi con utenti, gruppi o utenti remoti...",
"Warning" : "Avviso",
+ "Error while sending notification" : "Errore durante l'invio della notifica",
"The object type is not specified." : "Il tipo di oggetto non è specificato.",
"Enter new" : "Inserisci nuovo",
"Delete" : "Elimina",
diff --git a/core/l10n/nb_NO.js b/core/l10n/nb_NO.js
index d95186a94db..13f133dbaf4 100644
--- a/core/l10n/nb_NO.js
+++ b/core/l10n/nb_NO.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "endre",
"delete" : "slette",
"access control" : "tilgangskontroll",
+ "Share details could not be loaded for this item." : "Klarte ikke å laste inn detaljer om deling for dette elementet.",
"An error occured. Please try again" : "Det oppstod en feil. Prøv igjen",
"Share" : "Del",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med personer på andre ownCloud-installasjoner med syntaksen brukernavn@example.com/owncloud",
"Share with users or groups …" : "Del med brukere eller grupper ...",
"Share with users, groups or remote users …" : "Del med brukere, grupper eller eksterne brukere ...",
"Warning" : "Advarsel",
+ "Error while sending notification" : "Feil ved sending av varsling",
"The object type is not specified." : "Objekttypen er ikke spesifisert.",
"Enter new" : "Oppgi ny",
"Delete" : "Slett",
diff --git a/core/l10n/nb_NO.json b/core/l10n/nb_NO.json
index 0bde814c095..beb7a53e57b 100644
--- a/core/l10n/nb_NO.json
+++ b/core/l10n/nb_NO.json
@@ -143,12 +143,14 @@
"change" : "endre",
"delete" : "slette",
"access control" : "tilgangskontroll",
+ "Share details could not be loaded for this item." : "Klarte ikke å laste inn detaljer om deling for dette elementet.",
"An error occured. Please try again" : "Det oppstod en feil. Prøv igjen",
"Share" : "Del",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Del med personer på andre ownCloud-installasjoner med syntaksen brukernavn@example.com/owncloud",
"Share with users or groups …" : "Del med brukere eller grupper ...",
"Share with users, groups or remote users …" : "Del med brukere, grupper eller eksterne brukere ...",
"Warning" : "Advarsel",
+ "Error while sending notification" : "Feil ved sending av varsling",
"The object type is not specified." : "Objekttypen er ikke spesifisert.",
"Enter new" : "Oppgi ny",
"Delete" : "Slett",
diff --git a/core/l10n/nl.js b/core/l10n/nl.js
index 3734c3e0c40..0b12185cae4 100644
--- a/core/l10n/nl.js
+++ b/core/l10n/nl.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "wijzig",
"delete" : "verwijderen",
"access control" : "toegangscontrole",
+ "Share details could not be loaded for this item." : "Details van shares voor dit object konden niet worden geladen.",
"An error occured. Please try again" : "Er trad een fout op. Probeer het opnieuw",
"Share" : "Delen",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Delen met mensen op andere ownClouds via de syntax gebruikersnaam@voorbeeld.org/owncloud",
"Share with users or groups …" : "Delen met gebruikers of groepen ...",
"Share with users, groups or remote users …" : "Delen met gebruikers, groepen of externe gebruikers ...",
"Warning" : "Waarschuwing",
+ "Error while sending notification" : "Fout bij versturen melding",
"The object type is not specified." : "Het object type is niet gespecificeerd.",
"Enter new" : "Opgeven nieuw",
"Delete" : "Verwijder",
diff --git a/core/l10n/nl.json b/core/l10n/nl.json
index 1495ccfd5ac..7a9765d8c3a 100644
--- a/core/l10n/nl.json
+++ b/core/l10n/nl.json
@@ -143,12 +143,14 @@
"change" : "wijzig",
"delete" : "verwijderen",
"access control" : "toegangscontrole",
+ "Share details could not be loaded for this item." : "Details van shares voor dit object konden niet worden geladen.",
"An error occured. Please try again" : "Er trad een fout op. Probeer het opnieuw",
"Share" : "Delen",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Delen met mensen op andere ownClouds via de syntax gebruikersnaam@voorbeeld.org/owncloud",
"Share with users or groups …" : "Delen met gebruikers of groepen ...",
"Share with users, groups or remote users …" : "Delen met gebruikers, groepen of externe gebruikers ...",
"Warning" : "Waarschuwing",
+ "Error while sending notification" : "Fout bij versturen melding",
"The object type is not specified." : "Het object type is niet gespecificeerd.",
"Enter new" : "Opgeven nieuw",
"Delete" : "Verwijder",
diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js
index 2cf6224b9a9..ca6b56ae0a1 100644
--- a/core/l10n/pt_BR.js
+++ b/core/l10n/pt_BR.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "mudança",
"delete" : "remover",
"access control" : "controle de acesso",
+ "Share details could not be loaded for this item." : "Detalhes de compartilhamento não puderam ser carregados para este item.",
"An error occured. Please try again" : "Ocorreu um erro. Por favor tente novamente",
"Share" : "Compartilhar",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Compartilhar com usuários em outros ownClouds usando a sintaxe username@example.com/owncloud",
"Share with users or groups …" : "Compartilhar com usuários ou grupos ...",
"Share with users, groups or remote users …" : "Compartilhar com usuários, grupos ou usuários remoto ...",
"Warning" : "Aviso",
+ "Error while sending notification" : "Erro ao enviar notificação",
"The object type is not specified." : "O tipo de objeto não foi especificado.",
"Enter new" : "Entrar uma nova",
"Delete" : "Eliminar",
diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json
index 5e3b723c3c4..7441ad571eb 100644
--- a/core/l10n/pt_BR.json
+++ b/core/l10n/pt_BR.json
@@ -143,12 +143,14 @@
"change" : "mudança",
"delete" : "remover",
"access control" : "controle de acesso",
+ "Share details could not be loaded for this item." : "Detalhes de compartilhamento não puderam ser carregados para este item.",
"An error occured. Please try again" : "Ocorreu um erro. Por favor tente novamente",
"Share" : "Compartilhar",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "Compartilhar com usuários em outros ownClouds usando a sintaxe username@example.com/owncloud",
"Share with users or groups …" : "Compartilhar com usuários ou grupos ...",
"Share with users, groups or remote users …" : "Compartilhar com usuários, grupos ou usuários remoto ...",
"Warning" : "Aviso",
+ "Error while sending notification" : "Erro ao enviar notificação",
"The object type is not specified." : "O tipo de objeto não foi especificado.",
"Enter new" : "Entrar uma nova",
"Delete" : "Eliminar",
diff --git a/core/l10n/th_TH.js b/core/l10n/th_TH.js
index a183ccae7f7..3ed34bc336d 100644
--- a/core/l10n/th_TH.js
+++ b/core/l10n/th_TH.js
@@ -145,12 +145,14 @@ OC.L10N.register(
"change" : "เปลี่ยนแปลง",
"delete" : "ลบ",
"access control" : "ควบคุมการเข้าถึง",
+ "Share details could not be loaded for this item." : "รายละเอียดการแชร์ไม่สามารถโหลดสำหรับรายการนี้",
"An error occured. Please try again" : "เกิดข้อผิดพลาด กรุณาลองอีกครั้ง",
"Share" : "แชร์",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "แชร์กับคนใน ownClouds อื่นๆ ที่ใช้ไวยากรณ์ username@example.com/owncloud ",
"Share with users or groups …" : "แชร์กับผู้ใช้หรือกลุ่ม ...",
"Share with users, groups or remote users …" : "แชร์กับผู้ใช้กลุ่มหรือผู้ใช้ระยะไกล ...",
"Warning" : "คำเตือน",
+ "Error while sending notification" : "เกิดข้อผิดพลาดขณะกำลังส่งการแจ้งเตือน",
"The object type is not specified." : "ชนิดของวัตถุยังไม่ได้รับการระบุ",
"Enter new" : "ใส่ข้อมูลใหม่",
"Delete" : "ลบ",
diff --git a/core/l10n/th_TH.json b/core/l10n/th_TH.json
index ccdfd94c649..ecf02c36b4b 100644
--- a/core/l10n/th_TH.json
+++ b/core/l10n/th_TH.json
@@ -143,12 +143,14 @@
"change" : "เปลี่ยนแปลง",
"delete" : "ลบ",
"access control" : "ควบคุมการเข้าถึง",
+ "Share details could not be loaded for this item." : "รายละเอียดการแชร์ไม่สามารถโหลดสำหรับรายการนี้",
"An error occured. Please try again" : "เกิดข้อผิดพลาด กรุณาลองอีกครั้ง",
"Share" : "แชร์",
"Share with people on other ownClouds using the syntax username@example.com/owncloud" : "แชร์กับคนใน ownClouds อื่นๆ ที่ใช้ไวยากรณ์ username@example.com/owncloud ",
"Share with users or groups …" : "แชร์กับผู้ใช้หรือกลุ่ม ...",
"Share with users, groups or remote users …" : "แชร์กับผู้ใช้กลุ่มหรือผู้ใช้ระยะไกล ...",
"Warning" : "คำเตือน",
+ "Error while sending notification" : "เกิดข้อผิดพลาดขณะกำลังส่งการแจ้งเตือน",
"The object type is not specified." : "ชนิดของวัตถุยังไม่ได้รับการระบุ",
"Enter new" : "ใส่ข้อมูลใหม่",
"Delete" : "ลบ",
diff --git a/lib/private/app.php b/lib/private/app.php
index 368b3220b49..6c9f7615228 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -395,29 +395,6 @@ class OC_App {
}
/**
- * Get the navigation entries for the $app
- *
- * @param string $app app
- * @return array an array of the $data added with addNavigationEntry
- *
- * Warning: destroys the existing entries
- */
- public static function getAppNavigationEntries($app) {
- if (is_file(self::getAppPath($app) . '/appinfo/app.php')) {
- OC::$server->getNavigationManager()->clear();
- try {
- require $app . '/appinfo/app.php';
- } catch (\OC\Encryption\Exceptions\ModuleAlreadyExistsException $e) {
- // FIXME we should avoid getting this exception in first place,
- // For now we just catch it, since we don't care about encryption modules
- // when trying to find out, whether the app has a navigation entry.
- }
- return OC::$server->getNavigationManager()->getAll();
- }
- return array();
- }
-
- /**
* gets the active Menu entry
*
* @return string id or empty string
@@ -679,6 +656,12 @@ class OC_App {
if (is_array($data)) {
$data = OC_App::parseAppInfo($data);
}
+ if(isset($data['ocsid'])) {
+ $storedId = \OC::$server->getConfig()->getAppValue($appId, 'ocsid');
+ if($storedId !== '' && $storedId !== $data['ocsid']) {
+ $data['ocsid'] = $storedId;
+ }
+ }
self::$appInfo[$appId] = $data;
diff --git a/lib/private/connector/sabre/listenerplugin.php b/lib/private/connector/sabre/listenerplugin.php
new file mode 100644
index 00000000000..d0d40f4dc86
--- /dev/null
+++ b/lib/private/connector/sabre/listenerplugin.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Connector\Sabre;
+
+use Sabre\DAV\ServerPlugin;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+class ListenerPlugin extends ServerPlugin {
+ /** @var EventDispatcherInterface */
+ protected $dispatcher;
+
+ /**
+ * @param EventDispatcherInterface $dispatcher
+ */
+ public function __construct(EventDispatcherInterface $dispatcher) {
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * This initialize the plugin
+ *
+ * @param \Sabre\DAV\Server $server
+ */
+ public function initialize(\Sabre\DAV\Server $server) {
+ $server->on('beforeMethod', array($this, 'emitListener'), 15);
+ }
+
+ /**
+ * This method is called before any HTTP method and returns http status code 503
+ * in case the system is in maintenance mode.
+ *
+ * @return bool
+ */
+ public function emitListener() {
+ $this->dispatcher->dispatch('OC\Connector\Sabre::beforeMethod');
+
+ return true;
+ }
+}
diff --git a/lib/private/connector/sabre/maintenanceplugin.php b/lib/private/connector/sabre/maintenanceplugin.php
index 5b48abbc517..f886332418a 100644
--- a/lib/private/connector/sabre/maintenanceplugin.php
+++ b/lib/private/connector/sabre/maintenanceplugin.php
@@ -65,7 +65,7 @@ class MaintenancePlugin extends ServerPlugin {
*/
public function initialize(\Sabre\DAV\Server $server) {
$this->server = $server;
- $this->server->on('beforeMethod', array($this, 'checkMaintenanceMode'), 10);
+ $this->server->on('beforeMethod', array($this, 'checkMaintenanceMode'), 1);
}
/**
diff --git a/lib/private/connector/sabre/serverfactory.php b/lib/private/connector/sabre/serverfactory.php
index 042cc051d35..54470b0b8aa 100644
--- a/lib/private/connector/sabre/serverfactory.php
+++ b/lib/private/connector/sabre/serverfactory.php
@@ -28,6 +28,7 @@ use OCP\ILogger;
use OCP\ITagManager;
use OCP\IUserSession;
use Sabre\DAV\Auth\Backend\BackendInterface;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ServerFactory {
public function __construct(
@@ -36,7 +37,8 @@ class ServerFactory {
IDBConnection $databaseConnection,
IUserSession $userSession,
IMountManager $mountManager,
- ITagManager $tagManager
+ ITagManager $tagManager,
+ EventDispatcherInterface $dispatcher
) {
$this->config = $config;
$this->logger = $logger;
@@ -44,6 +46,7 @@ class ServerFactory {
$this->userSession = $userSession;
$this->mountManager = $mountManager;
$this->tagManager = $tagManager;
+ $this->dispatcher = $dispatcher;
}
/**
@@ -71,6 +74,7 @@ class ServerFactory {
$server->addPlugin(new \OC\Connector\Sabre\FilesPlugin($objectTree));
$server->addPlugin(new \OC\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger));
$server->addPlugin(new \OC\Connector\Sabre\LockPlugin($objectTree));
+ $server->addPlugin(new \OC\Connector\Sabre\ListenerPlugin($this->dispatcher));
// wait with registering these until auth is handled and the filesystem is setup
$server->on('beforeMethod', function () use ($server, $objectTree, $viewCallBack) {
diff --git a/lib/private/files.php b/lib/private/files.php
index 0172f1ca6af..658e708e5de 100644
--- a/lib/private/files.php
+++ b/lib/private/files.php
@@ -40,9 +40,6 @@
*
*/
-// TODO: get rid of this using proper composer packages
-require_once 'mcnetic/phpzipstreamer/ZipStreamer.php';
-
use OC\Lock\NoopLockingProvider;
use OCP\Lock\ILockingProvider;
@@ -121,7 +118,7 @@ class OC_Files {
if ($get_type === self::FILE) {
$zip = false;
} else {
- $zip = new ZipStreamer(false);
+ $zip = new ZipStreamer\ZipStreamer();
}
OC_Util::obEnd();
diff --git a/lib/private/files/cache/storage.php b/lib/private/files/cache/storage.php
index a116e84b3f2..88ceb287fb9 100644
--- a/lib/private/files/cache/storage.php
+++ b/lib/private/files/cache/storage.php
@@ -142,7 +142,7 @@ class Storage {
public function getAvailability() {
if ($row = self::getStorageById($this->storageId)) {
return [
- 'available' => ($row['available'] === 1),
+ 'available' => ((int)$row['available'] === 1),
'last_checked' => $row['last_checked']
];
} else {
diff --git a/lib/private/lock/dblockingprovider.php b/lib/private/lock/dblockingprovider.php
index f3e684d0b4d..bfa86a6920e 100644
--- a/lib/private/lock/dblockingprovider.php
+++ b/lib/private/lock/dblockingprovider.php
@@ -21,6 +21,7 @@
namespace OC\Lock;
+use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IDBConnection;
use OCP\ILogger;
use OCP\Lock\LockedException;
@@ -40,16 +41,33 @@ class DBLockingProvider extends AbstractLockingProvider {
private $logger;
/**
+ * @var \OCP\AppFramework\Utility\ITimeFactory
+ */
+ private $timeFactory;
+
+ const TTL = 3600; // how long until we clear stray locks in seconds
+
+ /**
* @param \OCP\IDBConnection $connection
* @param \OCP\ILogger $logger
+ * @param \OCP\AppFramework\Utility\ITimeFactory $timeFactory
*/
- public function __construct(IDBConnection $connection, ILogger $logger) {
+ public function __construct(IDBConnection $connection, ILogger $logger, ITimeFactory $timeFactory) {
$this->connection = $connection;
$this->logger = $logger;
+ $this->timeFactory = $timeFactory;
}
protected function initLockField($path) {
- $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => 0, 'ttl' => 0], ['key']);
+ $expire = $this->getExpireTime();
+ $this->connection->insertIfNotExist('*PREFIX*file_locks', ['key' => $path, 'lock' => 0, 'ttl' => $expire], ['key']);
+ }
+
+ /**
+ * @return int
+ */
+ protected function getExpireTime() {
+ return $this->timeFactory->getTime() + self::TTL;
}
/**
@@ -76,24 +94,23 @@ class DBLockingProvider extends AbstractLockingProvider {
* @throws \OCP\Lock\LockedException
*/
public function acquireLock($path, $type) {
- if ($this->connection->inTransaction()){
+ if ($this->connection->inTransaction()) {
$this->logger->warning("Trying to acquire a lock for '$path' while inside a transition");
}
- $this->connection->beginTransaction();
$this->initLockField($path);
+ $expire = $this->getExpireTime();
if ($type === self::LOCK_SHARED) {
$result = $this->connection->executeUpdate(
- 'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1 WHERE `key` = ? AND `lock` >= 0',
- [$path]
+ 'UPDATE `*PREFIX*file_locks` SET `lock` = `lock` + 1, `ttl` = ? WHERE `key` = ? AND `lock` >= 0',
+ [$expire, $path]
);
} else {
$result = $this->connection->executeUpdate(
- 'UPDATE `*PREFIX*file_locks` SET `lock` = -1 WHERE `key` = ? AND `lock` = 0',
- [$path]
+ 'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 0',
+ [$expire, $path]
);
}
- $this->connection->commit();
if ($result !== 1) {
throw new LockedException($path);
}
@@ -129,16 +146,16 @@ class DBLockingProvider extends AbstractLockingProvider {
* @throws \OCP\Lock\LockedException
*/
public function changeLock($path, $targetType) {
- $this->initLockField($path);
+ $expire = $this->getExpireTime();
if ($targetType === self::LOCK_SHARED) {
$result = $this->connection->executeUpdate(
- 'UPDATE `*PREFIX*file_locks` SET `lock` = 1 WHERE `key` = ? AND `lock` = -1',
- [$path]
+ 'UPDATE `*PREFIX*file_locks` SET `lock` = 1, `ttl` = ? WHERE `key` = ? AND `lock` = -1',
+ [$expire, $path]
);
} else {
$result = $this->connection->executeUpdate(
- 'UPDATE `*PREFIX*file_locks` SET `lock` = -1 WHERE `key` = ? AND `lock` = 1',
- [$path]
+ 'UPDATE `*PREFIX*file_locks` SET `lock` = -1, `ttl` = ? WHERE `key` = ? AND `lock` = 1',
+ [$expire, $path]
);
}
if ($result !== 1) {
@@ -151,8 +168,10 @@ class DBLockingProvider extends AbstractLockingProvider {
* cleanup empty locks
*/
public function cleanEmptyLocks() {
+ $expire = $this->timeFactory->getTime();
$this->connection->executeUpdate(
- 'DELETE FROM `*PREFIX*file_locks` WHERE `lock` = 0'
+ 'DELETE FROM `*PREFIX*file_locks` WHERE `lock` = 0 AND `ttl` < ?',
+ [$expire]
);
}
diff --git a/lib/private/notification/imanager.php b/lib/private/notification/imanager.php
index 0cd92b33251..f4a5fb14e31 100644
--- a/lib/private/notification/imanager.php
+++ b/lib/private/notification/imanager.php
@@ -53,4 +53,10 @@ interface IManager extends IApp, INotifier {
* @since 8.2.0
*/
public function createNotification();
+
+ /**
+ * @return bool
+ * @since 8.2.0
+ */
+ public function hasNotifiers();
}
diff --git a/lib/private/notification/manager.php b/lib/private/notification/manager.php
index 9635925e38e..0d5bb9be514 100644
--- a/lib/private/notification/manager.php
+++ b/lib/private/notification/manager.php
@@ -113,6 +113,14 @@ class Manager implements IManager {
}
/**
+ * @return bool
+ * @since 8.2.0
+ */
+ public function hasNotifiers() {
+ return !empty($this->notifiersClosures);
+ }
+
+ /**
* @param INotification $notification
* @return null
* @throws \InvalidArgumentException When the notification is not valid
diff --git a/lib/private/preview.php b/lib/private/preview.php
index 978da1161c2..db2a56f9fa5 100644
--- a/lib/private/preview.php
+++ b/lib/private/preview.php
@@ -772,6 +772,12 @@ class Preview {
throw new NotFoundException('File not found.');
}
+ if ($cachedPath = $this->isCached($this->info->getId())) {
+ header('Content-Type: ' . $this->info->getMimetype());
+ $this->userView->readfile($cachedPath);
+ return;
+ }
+
if (is_null($this->preview)) {
$this->getPreview();
}
diff --git a/lib/private/repair.php b/lib/private/repair.php
index bf385af2c2b..533bf05b54c 100644
--- a/lib/private/repair.php
+++ b/lib/private/repair.php
@@ -43,6 +43,7 @@ use OC\Repair\RepairConfig;
use OC\Repair\RepairLegacyStorages;
use OC\Repair\RepairMimeTypes;
use OC\Repair\SearchLuceneTables;
+use OC\Repair\UpdateOutdatedOcsIds;
class Repair extends BasicEmitter {
/**
@@ -101,7 +102,7 @@ class Repair extends BasicEmitter {
* @return array of RepairStep instances
*/
public static function getRepairSteps() {
- return array(
+ return [
new RepairMimeTypes(),
new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new RepairConfig(),
@@ -111,7 +112,8 @@ class Repair extends BasicEmitter {
new DropOldTables(\OC::$server->getDatabaseConnection()),
new DropOldJobs(\OC::$server->getJobList()),
new RemoveGetETagEntries(\OC::$server->getDatabaseConnection()),
- );
+ new UpdateOutdatedOcsIds(\OC::$server->getConfig()),
+ ];
}
/**
diff --git a/lib/private/server.php b/lib/private/server.php
index 9657afbdaec..d5f4f532c1c 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -460,7 +460,7 @@ class Server extends SimpleContainer implements IServerContainer {
if (!($memcache instanceof \OC\Memcache\NullCache)) {
return new MemcacheLockingProvider($memcache);
}
- return new DBLockingProvider($c->getDatabaseConnection(), $c->getLogger());
+ return new DBLockingProvider($c->getDatabaseConnection(), $c->getLogger(), new TimeFactory());
}
return new NoopLockingProvider();
});
diff --git a/lib/repair/updateoutdatedocsids.php b/lib/repair/updateoutdatedocsids.php
new file mode 100644
index 00000000000..afc9e968cad
--- /dev/null
+++ b/lib/repair/updateoutdatedocsids.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * @author Lukas Reschke <l8kas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Repair;
+
+use OC\Hooks\BasicEmitter;
+use OC\RepairStep;
+use OCP\IConfig;
+
+/**
+ * Class UpdateOutdatedOcsIds is used to update invalid outdated OCS IDs, this is
+ * for example the case when an application has had another OCS ID in the past such
+ * as for contacts and calendar when apps.owncloud.com migrated to a unified identifier
+ * for multiple versions.
+ *
+ * @package OC\Repair
+ */
+class UpdateOutdatedOcsIds extends BasicEmitter implements RepairStep {
+ /** @var IConfig */
+ private $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName() {
+ return 'Repair outdated OCS IDs';
+ }
+
+ /**
+ * @param string $appName
+ * @param string $oldId
+ * @param string $newId
+ * @return bool True if updated, false otherwise
+ */
+ public function fixOcsId($appName, $oldId, $newId) {
+ $existingId = $this->config->getAppValue($appName, 'ocsid');
+
+ if($existingId === $oldId) {
+ $this->config->setAppValue($appName, 'ocsid', $newId);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run() {
+ $appsToUpdate = [
+ 'contacts' => [
+ 'old' => '166044',
+ 'new' => '168708',
+ ],
+ 'calendar' => [
+ 'old' => '166043',
+ 'new' => '168707',
+ ],
+ 'bookmarks' => [
+ 'old' => '166042',
+ 'new' => '168710',
+ ],
+ 'search_lucene' => [
+ 'old' => '166057',
+ 'new' => '168709',
+ ],
+ 'documents' => [
+ 'old' => '166045',
+ 'new' => '168711',
+ ]
+ ];
+
+ foreach($appsToUpdate as $appName => $ids) {
+ if ($this->fixOcsId($appName, $ids['old'], $ids['new'])) {
+ $this->emit(
+ '\OC\Repair',
+ 'info',
+ [sprintf('Fixed invalid %s OCS id', $appName)]
+ );
+ }
+ }
+ }
+}
diff --git a/settings/ajax/navigationdetect.php b/settings/ajax/navigationdetect.php
index d7c1cbc5a12..5d3b34e10ef 100644
--- a/settings/ajax/navigationdetect.php
+++ b/settings/ajax/navigationdetect.php
@@ -23,14 +23,6 @@
OC_Util::checkAdminUser();
OCP\JSON::callCheck();
-$app = (string)$_GET['app'];
-$app = OC_App::cleanAppId($app);
+$navigation = \OC_App::getNavigation();
-$navigation = OC_App::getAppNavigationEntries($app);
-
-$navIds = array();
-foreach ($navigation as $nav) {
- $navIds[] = $nav['id'];
-}
-
-OCP\JSON::success(array('nav_ids' => array_values($navIds), 'nav_entries' => $navigation));
+OCP\JSON::success(['nav_entries' => $navigation]);
diff --git a/settings/js/apps.js b/settings/js/apps.js
index d1de3d727c0..f775ecad620 100644
--- a/settings/js/apps.js
+++ b/settings/js/apps.js
@@ -219,10 +219,10 @@ OC.Settings.Apps = OC.Settings.Apps || {
element.val(t('settings','Disable'));
appItem.addClass('appwarning');
} else {
+ OC.Settings.Apps.rebuildNavigation();
appItem.data('active',false);
appItem.data('groups', '');
element.data('active',false);
- OC.Settings.Apps.removeNavigation(appId);
appItem.removeClass('active');
element.val(t('settings','Enable'));
element.parent().find(".groups-enable").hide();
@@ -245,7 +245,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
element.val(t('settings','Enable'));
appItem.addClass('appwarning');
} else {
- OC.Settings.Apps.addNavigation(appId);
+ OC.Settings.Apps.rebuildNavigation();
appItem.data('active',true);
element.data('active',true);
appItem.addClass('active');
@@ -278,7 +278,6 @@ OC.Settings.Apps = OC.Settings.Apps || {
appItem.data('errormsg', t('settings', 'Error while enabling app'));
appItem.data('active',false);
appItem.addClass('appwarning');
- OC.Settings.Apps.removeNavigation(appId);
element.val(t('settings','Enable'));
});
}
@@ -312,7 +311,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
OC.Settings.Apps.showErrorMessage(appId, t('settings','Error while uninstalling app'));
element.val(t('settings','Uninstall'));
} else {
- OC.Settings.Apps.removeNavigation(appId);
+ OC.Settings.Apps.rebuildNavigation();
element.parent().fadeOut(function() {
element.remove();
});
@@ -320,23 +319,15 @@ OC.Settings.Apps = OC.Settings.Apps || {
},'json');
},
- removeNavigation: function(appId){
- $.getJSON(OC.filePath('settings', 'ajax', 'navigationdetect.php'), {app: appId}).done(function(response){
- if(response.status === 'success'){
- var navIds=response.nav_ids;
- for(var i=0; i< navIds.length; i++){
- $('#apps ul').children('li[data-id="'+navIds[i]+'"]').remove();
- }
- }
- });
- },
- addNavigation: function(appid){
- $.getJSON(OC.filePath('settings', 'ajax', 'navigationdetect.php'), {app: appid}).done(function(response){
+ rebuildNavigation: function() {
+ $.getJSON(OC.filePath('settings', 'ajax', 'navigationdetect.php')).done(function(response){
if(response.status === 'success'){
+ var idsToKeep = {};
var navEntries=response.nav_entries;
+ var container = $('#apps ul');
for(var i=0; i< navEntries.length; i++){
var entry = navEntries[i];
- var container = $('#apps ul');
+ idsToKeep[entry.id] = true;
if(container.children('li[data-id="'+entry.id+'"]').length === 0){
var li=$('<li></li>');
@@ -377,6 +368,12 @@ OC.Settings.Apps = OC.Settings.Apps || {
}
}
}
+
+ container.children('li[data-id]').each(function(index, el) {
+ if (!idsToKeep[$(el).data('id')]) {
+ $(el).remove();
+ }
+ });
}
});
},
diff --git a/settings/l10n/da.js b/settings/l10n/da.js
index 1b328cc7e3f..61b012de4f7 100644
--- a/settings/l10n/da.js
+++ b/settings/l10n/da.js
@@ -30,7 +30,7 @@ OC.L10N.register(
"Unable to change password" : "Kunne ikke ændre kodeord",
"Enabled" : "Aktiveret",
"Not enabled" : "Slået fra",
- "installing and updating apps via the app store or Federated Cloud Sharing" : "installation og opdatering af apps via app-butikken eller Federated Cloud Sharing",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "installation og opdatering af apps via app-butikken eller sammensluttet Cloud deling",
"Federated Cloud Sharing" : "Sammensluttet Cloud deling",
"cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL bruger en forældet %s version (%s). Husk at opdatere dit styresystem ellers vil funktioner såsom %s ikke fungere pålideligt.",
"A problem occurred, please check your log files (Error: %s)" : "Der opstod en fejl - tjek venligst dine logfiler (fejl: %s)",
@@ -55,8 +55,8 @@ OC.L10N.register(
"Email saved" : "E-mailadressen er gemt",
"Are you really sure you want add \"{domain}\" as trusted domain?" : "Sikker på at du vil tilføje \"{domain}\" som et domæne du har tiilid til?",
"Add trusted domain" : "Tilføj et domæne som du har tillid til",
- "Migration in progress. Please wait until the migration is finished" : "Overflytning er i gang. Vent venligst indtil overflytningen er afsluttet",
- "Migration started …" : "Overflytning er påbegyndt...",
+ "Migration in progress. Please wait until the migration is finished" : "Immigration er i gang. Vent venligst indtil overflytningen er afsluttet",
+ "Migration started …" : "Migrering er påbegyndt...",
"Sending..." : "Sender...",
"Official" : "Officiel",
"Approved" : "Godkendt",
@@ -64,7 +64,7 @@ OC.L10N.register(
"All" : "Alle",
"Official apps are developed by and within the ownCloud community. They offer functionality central to ownCloud and are ready for production use." : "Officielt program er udviklet af ownCloud fællesskabet. Funktionerne spiller en central rolle i ownCloud og kan bruges i produktionsmiljøer.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Godkendte programmer er udviklet af betroet udviklere som har bestået en let sikkerheds gennemgang. De er aktivt vedligeholdt i et åben kode lager og udviklerne vurdere programmet til at være stabilt for normalt brug.",
- "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dette program er ikke kontrolleret for sikkerhedsproblemer, og er nyt eller kendt for at være ustabilt. Installer for egen risiko.",
+ "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dette program er ikke kontrolleret for sikkerhedsproblemer, og er nyt eller kendt for at være ustabilt. Installer på eget ansvar.",
"Update to %s" : "Opdatér til %s",
"Please wait...." : "Vent venligst...",
"Error while disabling app" : "Kunne ikke deaktivere app",
@@ -77,7 +77,7 @@ OC.L10N.register(
"Uninstalling ...." : "Afinstallerer...",
"Error while uninstalling app" : "Fejl under afinstallering af app",
"Uninstall" : "Afinstallér",
- "An error occurred: {message}" : "En fejl opstod:{message}",
+ "An error occurred: {message}" : "Der opstod en fejl:{message}",
"Select a profile picture" : "Vælg et profilbillede",
"Very weak password" : "Meget svagt kodeord",
"Weak password" : "Svagt kodeord",
@@ -133,7 +133,7 @@ OC.L10N.register(
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Det var ikke muligt at udføre cronjobbet via kommandolinjefladen CLI. Følgende tekniske fejl fremkom:",
"Transactional file locking is using the database as locking backend, for best performance it's advised to configure a memcache for locking. See the <a target=\"_blank\" href=\"%s\">documentation ↗</a> for more information." : "Transaktions låsning af filer bliver brugt af databasen som lås til backend, for den bedste ydelse tilrådes det at konfigurere memcache. Se <a target=\"_blank\" href=\"%s\">documentation ↗</a> for mere information",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Dobbelttjek venligst <a target=\"_blank\" href=\"%s\">, og tjek om der er fejl eller advarsler i <a href=\"#log-section\">loggen</a>.",
- "All checks passed." : "Alle tjek blev gennemført.",
+ "All checks passed." : "Alle tjek blev bestået.",
"Open documentation" : "Åben dokumentation",
"Allow apps to use the Share API" : "Tillad apps til at bruge Share API",
"Allow users to share via link" : "Tillad brugere at dele via link",
@@ -157,7 +157,7 @@ OC.L10N.register(
"Use system's cron service to call the cron.php file every 15 minutes." : "Brug systemets cron service til at kalde cron.php hver 15. minut",
"Enable server-side encryption" : "Slå kryptering til på serversiden",
"Please read carefully before activating server-side encryption: " : "Læs venligst dette omhyggeligt, før der aktivere kryptering på serversiden:",
- "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Kryptering på serversiden er en envejsproces. Når krypteringen slås til, så vil alle filer fremefter blive krypteret på serveren, og det vil ikke være muligt at slå kryptering fra efterfølgende",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Kryptering på serversiden er en envejsproces. Når krypteringen slås til, så vil alle filer fremover blive krypteret på serveren, og det vil ikke være muligt at slå kryptering fra efterfølgende",
"Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "Enhver med priviligeret adgang til din ownCloud-server kan dekryptere dine filer, enten ved at opsnappe forespørgsler eller aflæse brugerkodeord, der bliver lagret i sessionsfiler med klartekst. Kryptering af serversiden beskytter derfor ikke mod ondsindede administratorer, men kan hjælpe til at beskytte dine data når de lagres hos eksterne værter.",
"Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Afhængig af det faktiske krypteringsmodul, så øges den generelle filstørrelse (med 35%% eller mere ved brug af standardmodulet)",
"You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Du bør jævnligt foretage sikkerhedskopiering af alle krypteringsnøgler, for at forhindre permanente tab af data (data/<user>/files_encryption and data/files_encryption)",
@@ -165,9 +165,9 @@ OC.L10N.register(
"Enable encryption" : "Slå kryptering til",
"No encryption module loaded, please enable an encryption module in the app menu." : "Der er ikke indlæst et krypteringsmodul - slå venligst et krypteringsmodul til i app-menuen.",
"Select default encryption module:" : "Vælg standardmodulet til kryptering:",
- "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Du skal overflytte dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen. Slå venligst \"Standardmodul til kryptering\" til, og kør \"occ encryption:migrate\"",
- "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Du skal overflytte dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen.",
- "Start migration" : "Påbegynd overflytning",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Du skal immigrere dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen. Slå venligst \"Standardmodul til kryptering\" til, og kør \"occ encryption:migrate\"",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Du skal immigrere dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen.",
+ "Start migration" : "Påbegynd immigrering",
"This is used for sending out notifications." : "Dette anvendes til udsendelse af notifikationer.",
"Send mode" : "Tilstand for afsendelse",
"Encryption" : "Kryptering",
diff --git a/settings/l10n/da.json b/settings/l10n/da.json
index 8d2aac4bb1e..2f18fedf629 100644
--- a/settings/l10n/da.json
+++ b/settings/l10n/da.json
@@ -28,7 +28,7 @@
"Unable to change password" : "Kunne ikke ændre kodeord",
"Enabled" : "Aktiveret",
"Not enabled" : "Slået fra",
- "installing and updating apps via the app store or Federated Cloud Sharing" : "installation og opdatering af apps via app-butikken eller Federated Cloud Sharing",
+ "installing and updating apps via the app store or Federated Cloud Sharing" : "installation og opdatering af apps via app-butikken eller sammensluttet Cloud deling",
"Federated Cloud Sharing" : "Sammensluttet Cloud deling",
"cURL is using an outdated %s version (%s). Please update your operating system or features such as %s will not work reliably." : "cURL bruger en forældet %s version (%s). Husk at opdatere dit styresystem ellers vil funktioner såsom %s ikke fungere pålideligt.",
"A problem occurred, please check your log files (Error: %s)" : "Der opstod en fejl - tjek venligst dine logfiler (fejl: %s)",
@@ -53,8 +53,8 @@
"Email saved" : "E-mailadressen er gemt",
"Are you really sure you want add \"{domain}\" as trusted domain?" : "Sikker på at du vil tilføje \"{domain}\" som et domæne du har tiilid til?",
"Add trusted domain" : "Tilføj et domæne som du har tillid til",
- "Migration in progress. Please wait until the migration is finished" : "Overflytning er i gang. Vent venligst indtil overflytningen er afsluttet",
- "Migration started …" : "Overflytning er påbegyndt...",
+ "Migration in progress. Please wait until the migration is finished" : "Immigration er i gang. Vent venligst indtil overflytningen er afsluttet",
+ "Migration started …" : "Migrering er påbegyndt...",
"Sending..." : "Sender...",
"Official" : "Officiel",
"Approved" : "Godkendt",
@@ -62,7 +62,7 @@
"All" : "Alle",
"Official apps are developed by and within the ownCloud community. They offer functionality central to ownCloud and are ready for production use." : "Officielt program er udviklet af ownCloud fællesskabet. Funktionerne spiller en central rolle i ownCloud og kan bruges i produktionsmiljøer.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Godkendte programmer er udviklet af betroet udviklere som har bestået en let sikkerheds gennemgang. De er aktivt vedligeholdt i et åben kode lager og udviklerne vurdere programmet til at være stabilt for normalt brug.",
- "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dette program er ikke kontrolleret for sikkerhedsproblemer, og er nyt eller kendt for at være ustabilt. Installer for egen risiko.",
+ "This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Dette program er ikke kontrolleret for sikkerhedsproblemer, og er nyt eller kendt for at være ustabilt. Installer på eget ansvar.",
"Update to %s" : "Opdatér til %s",
"Please wait...." : "Vent venligst...",
"Error while disabling app" : "Kunne ikke deaktivere app",
@@ -75,7 +75,7 @@
"Uninstalling ...." : "Afinstallerer...",
"Error while uninstalling app" : "Fejl under afinstallering af app",
"Uninstall" : "Afinstallér",
- "An error occurred: {message}" : "En fejl opstod:{message}",
+ "An error occurred: {message}" : "Der opstod en fejl:{message}",
"Select a profile picture" : "Vælg et profilbillede",
"Very weak password" : "Meget svagt kodeord",
"Weak password" : "Svagt kodeord",
@@ -131,7 +131,7 @@
"It was not possible to execute the cronjob via CLI. The following technical errors have appeared:" : "Det var ikke muligt at udføre cronjobbet via kommandolinjefladen CLI. Følgende tekniske fejl fremkom:",
"Transactional file locking is using the database as locking backend, for best performance it's advised to configure a memcache for locking. See the <a target=\"_blank\" href=\"%s\">documentation ↗</a> for more information." : "Transaktions låsning af filer bliver brugt af databasen som lås til backend, for den bedste ydelse tilrådes det at konfigurere memcache. Se <a target=\"_blank\" href=\"%s\">documentation ↗</a> for mere information",
"Please double check the <a target=\"_blank\" href=\"%s\">installation guides ↗</a>, and check for any errors or warnings in the <a href=\"#log-section\">log</a>." : "Dobbelttjek venligst <a target=\"_blank\" href=\"%s\">, og tjek om der er fejl eller advarsler i <a href=\"#log-section\">loggen</a>.",
- "All checks passed." : "Alle tjek blev gennemført.",
+ "All checks passed." : "Alle tjek blev bestået.",
"Open documentation" : "Åben dokumentation",
"Allow apps to use the Share API" : "Tillad apps til at bruge Share API",
"Allow users to share via link" : "Tillad brugere at dele via link",
@@ -155,7 +155,7 @@
"Use system's cron service to call the cron.php file every 15 minutes." : "Brug systemets cron service til at kalde cron.php hver 15. minut",
"Enable server-side encryption" : "Slå kryptering til på serversiden",
"Please read carefully before activating server-side encryption: " : "Læs venligst dette omhyggeligt, før der aktivere kryptering på serversiden:",
- "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Kryptering på serversiden er en envejsproces. Når krypteringen slås til, så vil alle filer fremefter blive krypteret på serveren, og det vil ikke være muligt at slå kryptering fra efterfølgende",
+ "Server-side encryption is a one way process. Once encryption is enabled, all files from that point forward will be encrypted on the server and it will not be possible to disable encryption at a later date" : "Kryptering på serversiden er en envejsproces. Når krypteringen slås til, så vil alle filer fremover blive krypteret på serveren, og det vil ikke være muligt at slå kryptering fra efterfølgende",
"Anyone who has privileged access to your ownCloud server can decrypt your files either by intercepting requests or reading out user passwords which are stored in plain text session files. Server-side encryption does therefore not protect against malicious administrators but is useful for protecting your data on externally hosted storage." : "Enhver med priviligeret adgang til din ownCloud-server kan dekryptere dine filer, enten ved at opsnappe forespørgsler eller aflæse brugerkodeord, der bliver lagret i sessionsfiler med klartekst. Kryptering af serversiden beskytter derfor ikke mod ondsindede administratorer, men kan hjælpe til at beskytte dine data når de lagres hos eksterne værter.",
"Depending on the actual encryption module the general file size is increased (by 35%% or more when using the default module)" : "Afhængig af det faktiske krypteringsmodul, så øges den generelle filstørrelse (med 35%% eller mere ved brug af standardmodulet)",
"You should regularly backup all encryption keys to prevent permanent data loss (data/<user>/files_encryption and data/files_encryption)" : "Du bør jævnligt foretage sikkerhedskopiering af alle krypteringsnøgler, for at forhindre permanente tab af data (data/<user>/files_encryption and data/files_encryption)",
@@ -163,9 +163,9 @@
"Enable encryption" : "Slå kryptering til",
"No encryption module loaded, please enable an encryption module in the app menu." : "Der er ikke indlæst et krypteringsmodul - slå venligst et krypteringsmodul til i app-menuen.",
"Select default encryption module:" : "Vælg standardmodulet til kryptering:",
- "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Du skal overflytte dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen. Slå venligst \"Standardmodul til kryptering\" til, og kør \"occ encryption:migrate\"",
- "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Du skal overflytte dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen.",
- "Start migration" : "Påbegynd overflytning",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one. Please enable the \"Default encryption module\" and run 'occ encryption:migrate'" : "Du skal immigrere dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen. Slå venligst \"Standardmodul til kryptering\" til, og kør \"occ encryption:migrate\"",
+ "You need to migrate your encryption keys from the old encryption (ownCloud <= 8.0) to the new one." : "Du skal immigrere dine krypteringsnøgler fra den gamle kryptering (ownCloud <= 8.0) til den nye af slagsen.",
+ "Start migration" : "Påbegynd immigrering",
"This is used for sending out notifications." : "Dette anvendes til udsendelse af notifikationer.",
"Send mode" : "Tilstand for afsendelse",
"Encryption" : "Kryptering",
diff --git a/settings/l10n/it.js b/settings/l10n/it.js
index 4e6fab34c74..4279a8d41ca 100644
--- a/settings/l10n/it.js
+++ b/settings/l10n/it.js
@@ -136,7 +136,7 @@ OC.L10N.register(
"All checks passed." : "Tutti i controlli passati.",
"Open documentation" : "Apri la documentazione",
"Allow apps to use the Share API" : "Consenti alle applicazioni di utilizzare le API di condivisione",
- "Allow users to share via link" : "Consenti agli utenti di condivere tramite collegamento",
+ "Allow users to share via link" : "Consenti agli utenti di condividere tramite collegamento",
"Enforce password protection" : "Imponi la protezione con password",
"Allow public uploads" : "Consenti caricamenti pubblici",
"Allow users to send mail notification for shared files" : "Consenti agli utenti di inviare email di notifica per i file condivisi",
diff --git a/settings/l10n/it.json b/settings/l10n/it.json
index 9c2d6fd6a91..416d5706280 100644
--- a/settings/l10n/it.json
+++ b/settings/l10n/it.json
@@ -134,7 +134,7 @@
"All checks passed." : "Tutti i controlli passati.",
"Open documentation" : "Apri la documentazione",
"Allow apps to use the Share API" : "Consenti alle applicazioni di utilizzare le API di condivisione",
- "Allow users to share via link" : "Consenti agli utenti di condivere tramite collegamento",
+ "Allow users to share via link" : "Consenti agli utenti di condividere tramite collegamento",
"Enforce password protection" : "Imponi la protezione con password",
"Allow public uploads" : "Consenti caricamenti pubblici",
"Allow users to send mail notification for shared files" : "Consenti agli utenti di inviare email di notifica per i file condivisi",
diff --git a/tests/core/command/encryption/decryptalltest.php b/tests/core/command/encryption/decryptalltest.php
index ef36d6d2827..972ea03150c 100644
--- a/tests/core/command/encryption/decryptalltest.php
+++ b/tests/core/command/encryption/decryptalltest.php
@@ -79,7 +79,8 @@ class DecryptAllTest extends TestCase {
}
- public function testConstructDesctruct() {
+ public function testSingleUserAndTrashbin() {
+
// on construct we enable single-user-mode and disable the trash bin
$this->config->expects($this->at(1))
->method('setSystemValue')
@@ -103,6 +104,7 @@ class DecryptAllTest extends TestCase {
$this->decryptAll,
$this->questionHelper
);
+ $this->invokePrivate($instance, 'forceSingleUserAndTrashbin');
$this->assertTrue(
$this->invokePrivate($instance, 'wasTrashbinEnabled')
@@ -111,6 +113,7 @@ class DecryptAllTest extends TestCase {
$this->assertFalse(
$this->invokePrivate($instance, 'wasSingleUserModeEnabled')
);
+ $this->invokePrivate($instance, 'resetSingleUserAndTrashbin');
}
/**
@@ -187,7 +190,7 @@ class DecryptAllTest extends TestCase {
->with('core', 'encryption_enabled', 'no');
// make sure that we enable encryption again after a exception was thrown
- $this->config->expects($this->at(1))
+ $this->config->expects($this->at(3))
->method('setAppValue')
->with('core', 'encryption_enabled', 'yes');
diff --git a/tests/core/command/encryption/encryptalltest.php b/tests/core/command/encryption/encryptalltest.php
index 9f7f7375044..128b4caa148 100644
--- a/tests/core/command/encryption/encryptalltest.php
+++ b/tests/core/command/encryption/encryptalltest.php
@@ -85,7 +85,9 @@ class EncryptAllTest extends TestCase {
$this->config->expects($this->at(1))->method('setSystemValue')->with('singleuser', true);
$this->config->expects($this->at(2))->method('setSystemValue')->with('singleuser', false);
- new EncryptAll($this->encryptionManager, $this->appManager, $this->config, $this->questionHelper);
+ $instance = new EncryptAll($this->encryptionManager, $this->appManager, $this->config, $this->questionHelper);
+ $this->invokePrivate($instance, 'forceSingleUserAndTrashbin');
+ $this->invokePrivate($instance, 'resetSingleUserAndTrashbin');
}
/**
diff --git a/tests/lib/connector/sabre/requesttest/downloadtest.php b/tests/lib/connector/sabre/requesttest/downloadtest.php
new file mode 100644
index 00000000000..67dd9f52308
--- /dev/null
+++ b/tests/lib/connector/sabre/requesttest/downloadtest.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Connector\Sabre\RequestTest;
+
+use OCP\AppFramework\Http;
+use OCP\Lock\ILockingProvider;
+
+class DownloadTest extends RequestTest {
+ public function testDownload() {
+ $user = $this->getUniqueID();
+ $view = $this->setupUser($user, 'pass');
+
+ $view->file_put_contents('foo.txt', 'bar');
+
+ $response = $this->request($view, $user, 'pass', 'GET', '/foo.txt');
+ $this->assertEquals(Http::STATUS_OK, $response->getStatus());
+ $this->assertEquals(stream_get_contents($response->getBody()), 'bar');
+ }
+
+ /**
+ * @expectedException \OC\Connector\Sabre\Exception\FileLocked
+ */
+ public function testDownloadWriteLocked() {
+ $user = $this->getUniqueID();
+ $view = $this->setupUser($user, 'pass');
+
+ $view->file_put_contents('foo.txt', 'bar');
+
+ $view->lockFile('/foo.txt', ILockingProvider::LOCK_EXCLUSIVE);
+
+ $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
+ }
+
+ public function testDownloadReadLocked() {
+ $user = $this->getUniqueID();
+ $view = $this->setupUser($user, 'pass');
+
+ $view->file_put_contents('foo.txt', 'bar');
+
+ $view->lockFile('/foo.txt', ILockingProvider::LOCK_SHARED);
+
+ $response = $this->request($view, $user, 'pass', 'GET', '/foo.txt', 'asd');
+ $this->assertEquals(Http::STATUS_OK, $response->getStatus());
+ $this->assertEquals(stream_get_contents($response->getBody()), 'bar');
+ }
+}
diff --git a/tests/lib/connector/sabre/requesttest/encryptionuploadtest.php b/tests/lib/connector/sabre/requesttest/encryptionuploadtest.php
new file mode 100644
index 00000000000..f1849c94760
--- /dev/null
+++ b/tests/lib/connector/sabre/requesttest/encryptionuploadtest.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Connector\Sabre\RequestTest;
+
+use OC\Files\View;
+use Test\Traits\EncryptionTrait;
+
+class EncryptionUploadTest extends UploadTest {
+ use EncryptionTrait;
+
+ protected function setupUser($name, $password) {
+ $this->createUser($name, $password);
+ $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
+ $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
+ $this->setupForUser($name, $password);
+ $this->loginWithEncryption($name);
+ return new View('/' . $name . '/files');
+ }
+}
diff --git a/tests/lib/connector/sabre/requesttest/requesttest.php b/tests/lib/connector/sabre/requesttest/requesttest.php
index 7f33dcf817b..4d4c8173caa 100644
--- a/tests/lib/connector/sabre/requesttest/requesttest.php
+++ b/tests/lib/connector/sabre/requesttest/requesttest.php
@@ -45,13 +45,15 @@ abstract class RequestTest extends TestCase {
\OC::$server->getDatabaseConnection(),
\OC::$server->getUserSession(),
\OC::$server->getMountManager(),
- \OC::$server->getTagManager()
+ \OC::$server->getTagManager(),
+ \OC::$server->getEventDispatcher()
);
}
protected function setupUser($name, $password) {
$this->createUser($name, $password);
- $this->registerMount($name, '\OC\Files\Storage\Temporary', '/' . $name);
+ $tmpFolder = \OC::$server->getTempManager()->getTemporaryFolder();
+ $this->registerMount($name, '\OC\Files\Storage\Local', '/' . $name, ['datadir' => $tmpFolder]);
$this->loginAsUser($name);
return new View('/' . $name . '/files');
}
diff --git a/tests/lib/connector/sabre/requesttest/sapi.php b/tests/lib/connector/sabre/requesttest/sapi.php
index 7072b8bd286..cda9fdb70f5 100644
--- a/tests/lib/connector/sabre/requesttest/sapi.php
+++ b/tests/lib/connector/sabre/requesttest/sapi.php
@@ -41,7 +41,15 @@ class Sapi {
* @return void
*/
public function sendResponse(Response $response) {
- $this->response = $response;
+ // we need to copy the body since we close the source stream
+ $copyStream = fopen('php://temp', 'r+');
+ if (is_string($response->getBody())) {
+ fwrite($copyStream, $response->getBody());
+ } else if (is_resource($response->getBody())) {
+ stream_copy_to_stream($response->getBody(), $copyStream);
+ }
+ rewind($copyStream);
+ $this->response = new Response($response->getStatus(), $response->getHeaders(), $copyStream);
}
/**
diff --git a/tests/lib/connector/sabre/requesttest/uploadtest.php b/tests/lib/connector/sabre/requesttest/uploadtest.php
index b8cd44afda7..8f39aff81b9 100644
--- a/tests/lib/connector/sabre/requesttest/uploadtest.php
+++ b/tests/lib/connector/sabre/requesttest/uploadtest.php
@@ -8,6 +8,8 @@
namespace Test\Connector\Sabre\RequestTest;
+use OC\AppFramework\Http;
+
class UploadTest extends RequestTest {
public function testBasicUpload() {
$user = $this->getUniqueID();
@@ -16,7 +18,7 @@ class UploadTest extends RequestTest {
$this->assertFalse($view->file_exists('foo.txt'));
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
- $this->assertEquals(201, $response->getStatus());
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
$this->assertTrue($view->file_exists('foo.txt'));
$this->assertEquals('asd', $view->file_get_contents('foo.txt'));
@@ -33,7 +35,7 @@ class UploadTest extends RequestTest {
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt', 'asd');
- $this->assertEquals(204, $response->getStatus());
+ $this->assertEquals(Http::STATUS_NO_CONTENT, $response->getStatus());
$this->assertEquals('asd', $view->file_get_contents('foo.txt'));
$info = $view->getFileInfo('foo.txt');
@@ -53,7 +55,7 @@ class UploadTest extends RequestTest {
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
- $this->assertEquals(201, $response->getStatus());
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
$this->assertTrue($view->file_exists('foo.txt'));
$this->assertEquals('asdbar', $view->file_get_contents('foo.txt'));
@@ -70,12 +72,12 @@ class UploadTest extends RequestTest {
$view->file_put_contents('foo.txt', 'bar');
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
- $this->assertEquals(201, $response->getStatus());
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
$this->assertEquals('bar', $view->file_get_contents('foo.txt'));
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
- $this->assertEquals(201, $response->getStatus());
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
$this->assertEquals('asdbar', $view->file_get_contents('foo.txt'));
@@ -91,7 +93,7 @@ class UploadTest extends RequestTest {
$this->assertFalse($view->file_exists('foo.txt'));
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-1', 'bar', ['OC-Chunked' => '1']);
- $this->assertEquals(201, $response->getStatus());
+ $this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
$this->assertFalse($view->file_exists('foo.txt'));
$response = $this->request($view, $user, 'pass', 'PUT', '/foo.txt-chunking-123-2-0', 'asd', ['OC-Chunked' => '1']);
diff --git a/tests/lib/lock/dblockingprovider.php b/tests/lib/lock/dblockingprovider.php
index fd6550d9c47..2360052b4a0 100644
--- a/tests/lib/lock/dblockingprovider.php
+++ b/tests/lib/lock/dblockingprovider.php
@@ -21,7 +21,13 @@
namespace Test\Lock;
+use OCP\Lock\ILockingProvider;
+
class DBLockingProvider extends LockingProvider {
+ /**
+ * @var \OC\Lock\DBLockingProvider
+ */
+ protected $instance;
/**
* @var \OCP\IDBConnection
@@ -29,15 +35,63 @@ class DBLockingProvider extends LockingProvider {
private $connection;
/**
+ * @var \OCP\AppFramework\Utility\ITimeFactory
+ */
+ private $timeFactory;
+
+ private $currentTime;
+
+ public function setUp() {
+ $this->currentTime = time();
+ $this->timeFactory = $this->getMock('\OCP\AppFramework\Utility\ITimeFactory');
+ $this->timeFactory->expects($this->any())
+ ->method('getTime')
+ ->will($this->returnCallback(function () {
+ return $this->currentTime;
+ }));
+ parent::setUp();
+ }
+
+ /**
* @return \OCP\Lock\ILockingProvider
*/
protected function getInstance() {
$this->connection = \OC::$server->getDatabaseConnection();
- return new \OC\Lock\DBLockingProvider($this->connection, \OC::$server->getLogger());
+ return new \OC\Lock\DBLockingProvider($this->connection, \OC::$server->getLogger(), $this->timeFactory);
}
public function tearDown() {
$this->connection->executeQuery('DELETE FROM `*PREFIX*file_locks`');
parent::tearDown();
}
+
+ public function testCleanEmptyLocks() {
+ $this->currentTime = 100;
+ $this->instance->acquireLock('foo', ILockingProvider::LOCK_EXCLUSIVE);
+ $this->instance->acquireLock('asd', ILockingProvider::LOCK_EXCLUSIVE);
+
+ $this->currentTime = 200;
+ $this->instance->acquireLock('bar', ILockingProvider::LOCK_EXCLUSIVE);
+ $this->instance->changeLock('asd', ILockingProvider::LOCK_SHARED);
+
+ $this->currentTime = 150 + \OC\Lock\DBLockingProvider::TTL;
+
+ $this->assertEquals(3, $this->getLockEntryCount());
+
+ $this->instance->cleanEmptyLocks();
+
+ $this->assertEquals(3, $this->getLockEntryCount());
+
+ $this->instance->releaseAll();
+
+ $this->instance->cleanEmptyLocks();
+
+ $this->assertEquals(2, $this->getLockEntryCount());
+ }
+
+ private function getLockEntryCount() {
+ $query = $this->connection->prepare('SELECT count(*) FROM `*PREFIX*file_locks`');
+ $query->execute();
+ return $query->fetchColumn();
+ }
}
diff --git a/tests/lib/repair/updateoutdatedocsids.php b/tests/lib/repair/updateoutdatedocsids.php
new file mode 100644
index 00000000000..3669a64371f
--- /dev/null
+++ b/tests/lib/repair/updateoutdatedocsids.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * @author Lukas Reschke <l8kas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace Test\Repair;
+
+use OCP\IConfig;
+use Test\TestCase;
+
+/**
+ * Class UpdateOutdatedOcsIds
+ *
+ * @package Test\Repair
+ */
+class UpdateOutdatedOcsIds extends TestCase {
+ /** @var IConfig */
+ private $config;
+ /** @var \OC\Repair\UpdateOutdatedOcsIds */
+ private $updateOutdatedOcsIds;
+
+ public function setUp() {
+ parent::setUp();
+ $this->config = $this->getMockBuilder('\\OCP\\IConfig')->getMock();
+ $this->updateOutdatedOcsIds = new \OC\Repair\UpdateOutdatedOcsIds($this->config);
+ }
+
+ public function testGetName() {
+ $this->assertSame('Repair outdated OCS IDs', $this->updateOutdatedOcsIds->getName());
+ }
+
+ public function testFixOcsIdNoOcsId() {
+ $this->config
+ ->expects($this->once())
+ ->method('getAppValue')
+ ->with('MyNotInstalledApp', 'ocsid')
+ ->will($this->returnValue(''));
+ $this->assertFalse($this->updateOutdatedOcsIds->fixOcsId('MyNotInstalledApp', '1337', '0815'));
+ }
+
+ public function testFixOcsIdUpdateOcsId() {
+ $this->config
+ ->expects($this->at(0))
+ ->method('getAppValue')
+ ->with('MyInstalledApp', 'ocsid')
+ ->will($this->returnValue('1337'));
+ $this->config
+ ->expects($this->at(1))
+ ->method('setAppValue')
+ ->with('MyInstalledApp', 'ocsid', '0815');
+
+ $this->assertTrue($this->updateOutdatedOcsIds->fixOcsId('MyInstalledApp', '1337', '0815'));
+ }
+
+ public function testFixOcsIdAlreadyFixed() {
+ $this->config
+ ->expects($this->once())
+ ->method('getAppValue')
+ ->with('MyAlreadyFixedAppId', 'ocsid')
+ ->will($this->returnValue('0815'));
+
+ $this->assertFalse($this->updateOutdatedOcsIds->fixOcsId('MyAlreadyFixedAppId', '1337', '0815'));
+ }
+}
diff --git a/tests/lib/traits/encryptiontrait.php b/tests/lib/traits/encryptiontrait.php
new file mode 100644
index 00000000000..92ba3734873
--- /dev/null
+++ b/tests/lib/traits/encryptiontrait.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (c) 2015 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Traits;
+
+use OC\Encryption\Util;
+use OC\Files\View;
+use OCA\Encryption\AppInfo\Application;
+use OCA\Encryption\KeyManager;
+use OCA\Encryption\Users\Setup;
+use OC\Files\Filesystem;
+
+/**
+ * Enables encryption
+ */
+trait EncryptionTrait {
+ // from MountProviderTrait
+ abstract protected function registerStorageWrapper($name, $wrapper);
+
+ // from phpunit
+ abstract protected function markTestSkipped($reason = '');
+ abstract protected function assertTrue($condition, $message = '');
+
+ private $encryptionWasEnabled;
+
+ private $originalEncryptionModule;
+
+ /**
+ * @var \OCP\IConfig
+ */
+ private $config;
+
+ /**
+ * @var \OCA\Encryption\AppInfo\Application
+ */
+ private $encryptionApp;
+
+ protected function loginWithEncryption($user = '') {
+ \OC_Util::tearDownFS();
+ \OC_User::setUserId('');
+ // needed for fully logout
+ \OC::$server->getUserSession()->setUser(null);
+
+ Filesystem::tearDown();
+ \OC_User::setUserId($user);
+ $this->postLogin();
+ \OC_Util::setupFS($user);
+ if (\OC_User::userExists($user)) {
+ \OC::$server->getUserFolder($user);
+ }
+ }
+
+ protected function setupForUser($name, $password) {
+ \OC_Util::tearDownFS();
+ \OC_Util::setupFS($name);
+ $container = $this->encryptionApp->getContainer();
+ /** @var KeyManager $keyManager */
+ $keyManager = $container->query('KeyManager');
+ /** @var Setup $userSetup */
+ $userSetup = $container->query('UserSetup');
+ $userSetup->setupServerSide($name, $password);
+ $keyManager->init($name, $password);
+ }
+
+ protected function postLogin() {
+ $util = new Util(
+ new View(),
+ \OC::$server->getUserManager(),
+ \OC::$server->getGroupManager(),
+ \OC::$server->getConfig()
+ );
+ $this->registerStorageWrapper('oc_encryption', array($util, 'wrapStorage'));
+ }
+
+ protected function setUpEncryptionTrait() {
+ $isReady = \OC::$server->getEncryptionManager()->isReady();
+ if (!$isReady) {
+ $this->markTestSkipped('Encryption not ready');
+ }
+
+ \OC_App::loadApp('encryption');
+
+ $this->encryptionApp = new Application([], $isReady);
+
+ $this->config = \OC::$server->getConfig();
+ $this->encryptionWasEnabled = $this->config->getAppValue('core', 'encryption_enabled', 'no');
+ $this->originalEncryptionModule = $this->config->getAppValue('core', 'default_encryption_module');
+ $this->config->setAppValue('core', 'default_encryption_module', \OCA\Encryption\Crypto\Encryption::ID);
+ $this->config->setAppValue('core', 'encryption_enabled', 'yes');
+ $this->assertTrue(\OC::$server->getEncryptionManager()->isEnabled());
+ }
+
+ protected function tearDownEncryptionTrait() {
+ if ($this->config) {
+ $this->config->setAppValue('core', 'encryption_enabled', $this->encryptionWasEnabled);
+ $this->config->setAppValue('core', 'default_encryption_module', $this->originalEncryptionModule);
+ }
+ }
+}
diff --git a/tests/lib/traits/mountprovidertrait.php b/tests/lib/traits/mountprovidertrait.php
index 66eca1597c8..bccb5b693ee 100644
--- a/tests/lib/traits/mountprovidertrait.php
+++ b/tests/lib/traits/mountprovidertrait.php
@@ -32,7 +32,7 @@ trait MountProviderTrait {
if (!isset($this->mounts[$userId])) {
$this->mounts[$userId] = [];
}
- $this->mounts[$userId][] = new MountPoint($storage, $mountPoint, $arguments, $this->storageFactory);
+ $this->mounts[$userId][] = ['storage' => $storage, 'mountPoint' => $mountPoint, 'arguments' => $arguments];
}
protected function registerStorageWrapper($name, $wrapper) {
@@ -46,7 +46,9 @@ trait MountProviderTrait {
->method('getMountsForUser')
->will($this->returnCallback(function (IUser $user) {
if (isset($this->mounts[$user->getUID()])) {
- return $this->mounts[$user->getUID()];
+ return array_map(function ($config) {
+ return new MountPoint($config['storage'], $config['mountPoint'], $config['arguments'], $this->storageFactory);
+ }, $this->mounts[$user->getUID()]);
} else {
return [];
}
diff --git a/version.php b/version.php
index cfc4db82995..711d82f1ca1 100644
--- a/version.php
+++ b/version.php
@@ -23,12 +23,12 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = [8, 2, 0, 5];
+$OC_Version = array(8, 2, 0, 6);
// The human readable string
-$OC_VersionString = '8.2 pre alpha';
+$OC_VersionString = '8.2 beta1';
-$OC_VersionCanBeUpgradedFrom = [8, 1];
+$OC_VersionCanBeUpgradedFrom = array(8, 1);
// The ownCloud channel
$OC_Channel = 'git';