summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/encryption/controller/settingscontroller.php4
-rw-r--r--apps/encryption/hooks/userhooks.php6
-rw-r--r--apps/encryption/lib/crypto/crypt.php144
-rw-r--r--apps/encryption/lib/keymanager.php15
-rw-r--r--apps/encryption/lib/recovery.php5
-rw-r--r--apps/encryption/tests/controller/SettingsControllerTest.php2
-rw-r--r--apps/encryption/tests/hooks/UserHooksTest.php2
-rw-r--r--apps/encryption/tests/lib/KeyManagerTest.php2
-rw-r--r--apps/encryption/tests/lib/RecoveryTest.php2
-rw-r--r--apps/encryption/tests/lib/crypto/cryptTest.php111
-rw-r--r--apps/encryption/vendor/pbkdf2fallback.php87
-rw-r--r--apps/files/appinfo/update.php9
-rw-r--r--apps/files/appinfo/version2
-rw-r--r--apps/files/css/detailsView.css9
-rw-r--r--apps/files/css/files.css5
-rw-r--r--apps/files/js/detailtabview.js2
-rw-r--r--apps/files/js/filelist.js1
-rw-r--r--apps/files/js/mainfileinfodetailview.js4
-rw-r--r--apps/files/tests/ajax_rename.php2
-rw-r--r--apps/files/tests/js/filelistSpec.js29
-rw-r--r--apps/files_external/ajax/applicable.php11
-rw-r--r--apps/files_external/appinfo/routes.php2
-rw-r--r--apps/files_external/js/settings.js9
-rw-r--r--apps/files_external/lib/amazons3.php8
-rw-r--r--apps/files_external/lib/api.php2
-rw-r--r--apps/files_external/lib/config.php25
-rw-r--r--apps/files_external/lib/dropbox.php4
-rw-r--r--apps/files_external/lib/failedstorage.php8
-rw-r--r--apps/files_external/lib/google.php6
-rw-r--r--apps/files_external/lib/sessionstoragewrapper.php2
-rw-r--r--apps/files_external/lib/swift.php6
-rw-r--r--apps/files_external/service/backendservice.php4
-rw-r--r--apps/files_external/service/storagesservice.php2
-rw-r--r--apps/files_external/service/userglobalstoragesservice.php25
-rw-r--r--apps/files_external/settings.php2
-rw-r--r--apps/files_external/templates/list.php2
-rw-r--r--apps/files_external/tests/service/userstoragesservicetest.php8
-rw-r--r--apps/files_sharing/ajax/testremote.php46
-rw-r--r--apps/files_sharing/api/server2server.php22
-rw-r--r--apps/files_sharing/appinfo/application.php6
-rw-r--r--apps/files_sharing/appinfo/routes.php11
-rw-r--r--apps/files_sharing/css/settings-personal.css1
-rw-r--r--apps/files_sharing/lib/controllers/externalsharescontroller.php50
-rw-r--r--apps/files_sharing/lib/external/storage.php2
-rw-r--r--apps/files_sharing/lib/sharedstorage.php18
-rw-r--r--apps/files_sharing/tests/controller/externalsharecontroller.php187
-rw-r--r--apps/user_ldap/ajax/setConfiguration.php2
-rw-r--r--apps/user_ldap/appinfo/update.php10
-rw-r--r--apps/user_ldap/appinfo/version2
-rw-r--r--apps/user_ldap/js/wizard/wizardTabAdvanced.js14
-rw-r--r--apps/user_ldap/lib/configuration.php3
-rw-r--r--apps/user_ldap/templates/settings.php1
-rw-r--r--config/config.sample.php23
-rw-r--r--core/application.php10
-rw-r--r--core/avatar/avatarcontroller.php1
-rw-r--r--core/command/log/manage.php171
-rw-r--r--core/command/log/owncloud.php124
-rw-r--r--core/css/apps.css26
-rw-r--r--core/css/mobile.css4
-rw-r--r--core/css/styles.css11
-rw-r--r--core/js/config.php40
-rw-r--r--core/js/jquery.avatar.js4
-rw-r--r--core/js/share.js6
-rw-r--r--core/js/tests/specHelper.js32
-rw-r--r--core/lostpassword/controller/lostcontroller.php24
-rw-r--r--core/register_command.php3
-rw-r--r--core/templates/layout.user.php2
-rw-r--r--core/templates/update.admin.php22
-rw-r--r--cron.php5
-rw-r--r--lib/base.php91
-rw-r--r--lib/private/activity/event.php250
-rw-r--r--lib/private/activitymanager.php132
-rw-r--r--lib/private/app.php2
-rw-r--r--lib/private/app/appmanager.php69
-rw-r--r--lib/private/appframework/http/request.php22
-rw-r--r--lib/private/backgroundjob/joblist.php17
-rw-r--r--lib/private/config.php6
-rw-r--r--lib/private/files/fileinfo.php2
-rw-r--r--lib/private/http/client/client.php5
-rw-r--r--lib/private/server.php49
-rw-r--r--lib/private/session/cryptosessiondata.php147
-rw-r--r--lib/private/session/cryptowrapper.php96
-rw-r--r--lib/private/template.php2
-rw-r--r--lib/private/util.php8
-rw-r--r--lib/public/activity/iconsumer.php16
-rw-r--r--lib/public/activity/ievent.php200
-rw-r--r--lib/public/activity/imanager.php78
-rw-r--r--lib/public/http/client/iclient.php5
-rw-r--r--settings/ajax/togglegroups.php3
-rw-r--r--settings/css/settings.css5
-rw-r--r--settings/js/admin.js6
-rw-r--r--settings/js/personal.js2
-rw-r--r--settings/js/users/users.js11
-rw-r--r--settings/templates/admin.php3
-rw-r--r--settings/templates/users/part.grouplist.php2
-rw-r--r--status.php1
-rw-r--r--tests/core/command/log/managetest.php181
-rw-r--r--tests/core/command/log/owncloudtest.php121
-rw-r--r--tests/core/lostpassword/controller/lostcontrollertest.php123
-rw-r--r--tests/lib/activitymanager.php197
-rw-r--r--tests/lib/app/manager.php70
-rw-r--r--tests/lib/appframework/controller/ApiControllerTest.php1
-rw-r--r--tests/lib/appframework/controller/ControllerTest.php1
-rw-r--r--tests/lib/appframework/controller/OCSControllerTest.php4
-rw-r--r--tests/lib/appframework/dependencyinjection/DIContainerTest.php1
-rw-r--r--tests/lib/appframework/http/DispatcherTest.php6
-rw-r--r--tests/lib/appframework/http/RequestTest.php117
-rw-r--r--tests/lib/appframework/middleware/MiddlewareDispatcherTest.php1
-rw-r--r--tests/lib/appframework/middleware/MiddlewareTest.php1
-rw-r--r--tests/lib/appframework/middleware/security/CORSMiddlewareTest.php10
-rw-r--r--tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php1
-rw-r--r--tests/lib/appframework/middleware/sessionmiddlewaretest.php1
-rw-r--r--tests/lib/backgroundjob/joblist.php26
-rw-r--r--tests/lib/connector/sabre/requesttest/requesttest.php50
-rw-r--r--tests/lib/server.php1
-rw-r--r--tests/lib/session/cryptosessiondatatest.php53
-rw-r--r--tests/lib/session/cryptowrappingtest.php82
-rw-r--r--tests/lib/testcase.php33
-rw-r--r--tests/lib/traits/mountprovidertrait.php56
-rw-r--r--tests/lib/traits/usertrait.php32
-rw-r--r--tests/lib/util.php2
121 files changed, 3412 insertions, 441 deletions
diff --git a/apps/encryption/controller/settingscontroller.php b/apps/encryption/controller/settingscontroller.php
index 641c97e1d6e..2a668f7cd4a 100644
--- a/apps/encryption/controller/settingscontroller.php
+++ b/apps/encryption/controller/settingscontroller.php
@@ -100,10 +100,10 @@ class SettingsController extends Controller {
if ($passwordCorrect !== false) {
$encryptedKey = $this->keyManager->getPrivateKey($uid);
- $decryptedKey = $this->crypt->decryptPrivateKey($encryptedKey, $oldPassword);
+ $decryptedKey = $this->crypt->decryptPrivateKey($encryptedKey, $oldPassword, $uid);
if ($decryptedKey) {
- $encryptedKey = $this->crypt->symmetricEncryptFileContent($decryptedKey, $newPassword);
+ $encryptedKey = $this->crypt->encryptPrivateKey($decryptedKey, $newPassword, $uid);
$header = $this->crypt->generateHeader();
if ($encryptedKey) {
$this->keyManager->setPrivateKey($uid, $header . $encryptedKey);
diff --git a/apps/encryption/hooks/userhooks.php b/apps/encryption/hooks/userhooks.php
index a86b8662781..8b6f17bec6d 100644
--- a/apps/encryption/hooks/userhooks.php
+++ b/apps/encryption/hooks/userhooks.php
@@ -220,8 +220,7 @@ class UserHooks implements IHook {
if ($user && $params['uid'] === $user->getUID() && $privateKey) {
// Encrypt private key with new user pwd as passphrase
- $encryptedPrivateKey = $this->crypt->symmetricEncryptFileContent($privateKey,
- $params['password']);
+ $encryptedPrivateKey = $this->crypt->encryptPrivateKey($privateKey, $params['password'], $params['uid']);
// Save private key
if ($encryptedPrivateKey) {
@@ -259,8 +258,7 @@ class UserHooks implements IHook {
$this->keyManager->setPublicKey($user, $keyPair['publicKey']);
// Encrypt private key with new password
- $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
- $newUserPassword);
+ $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $newUserPassword, $user);
if ($encryptedKey) {
$this->keyManager->setPrivateKey($user, $this->crypt->generateHeader() . $encryptedKey);
diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index f3cf38fb96c..6c4c108f50a 100644
--- a/apps/encryption/lib/crypto/crypt.php
+++ b/apps/encryption/lib/crypto/crypt.php
@@ -30,6 +30,7 @@ use OC\Encryption\Exceptions\DecryptionFailedException;
use OC\Encryption\Exceptions\EncryptionFailedException;
use OCA\Encryption\Exceptions\MultiKeyDecryptException;
use OCA\Encryption\Exceptions\MultiKeyEncryptException;
+use OCA\Encryption\Vendor\PBKDF2Fallback;
use OCP\Encryption\Exceptions\GenericEncryptionException;
use OCP\IConfig;
use OCP\ILogger;
@@ -42,6 +43,10 @@ class Crypt {
// default cipher from old ownCloud versions
const LEGACY_CIPHER = 'AES-128-CFB';
+ // default key format, old ownCloud version encrypted the private key directly
+ // with the user password
+ const LEGACY_KEY_FORMAT = 'password';
+
const HEADER_START = 'HBEGIN';
const HEADER_END = 'HEND';
/**
@@ -58,6 +63,11 @@ class Crypt {
private $config;
/**
+ * @var array
+ */
+ private $supportedKeyFormats;
+
+ /**
* @param ILogger $logger
* @param IUserSession $userSession
* @param IConfig $config
@@ -66,6 +76,7 @@ class Crypt {
$this->logger = $logger;
$this->user = $userSession && $userSession->isLoggedIn() ? $userSession->getUser() : false;
$this->config = $config;
+ $this->supportedKeyFormats = ['hash', 'password'];
}
/**
@@ -161,10 +172,23 @@ class Crypt {
/**
* generate header for encrypted file
+ *
+ * @param string $keyFormat (can be 'hash' or 'password')
+ * @return string
+ * @throws \InvalidArgumentException
*/
- public function generateHeader() {
+ public function generateHeader($keyFormat = 'hash') {
+
+ if (in_array($keyFormat, $this->supportedKeyFormats, true) === false) {
+ throw new \InvalidArgumentException('key format "' . $keyFormat . '" is not supported');
+ }
+
$cipher = $this->getCipher();
- $header = self::HEADER_START . ':cipher:' . $cipher . ':' . self::HEADER_END;
+
+ $header = self::HEADER_START
+ . ':cipher:' . $cipher
+ . ':keyFormat:' . $keyFormat
+ . ':' . self::HEADER_END;
return $header;
}
@@ -212,6 +236,25 @@ class Crypt {
}
/**
+ * get key size depending on the cipher
+ *
+ * @param string $cipher supported ('AES-256-CFB' and 'AES-128-CFB')
+ * @return int
+ * @throws \InvalidArgumentException
+ */
+ protected function getKeySize($cipher) {
+ if ($cipher === 'AES-256-CFB') {
+ return 32;
+ } else if ($cipher === 'AES-128-CFB') {
+ return 16;
+ }
+
+ throw new \InvalidArgumentException(
+ 'Wrong cipher defined only AES-128-CFB and AES-256-CFB are supported.'
+ );
+ }
+
+ /**
* get legacy cipher
*
* @return string
@@ -238,11 +281,71 @@ class Crypt {
}
/**
+ * generate password hash used to encrypt the users private key
+ *
+ * @param string $password
+ * @param string $cipher
+ * @param string $uid only used for user keys
+ * @return string
+ */
+ protected function generatePasswordHash($password, $cipher, $uid = '') {
+ $instanceId = $this->config->getSystemValue('instanceid');
+ $instanceSecret = $this->config->getSystemValue('secret');
+ $salt = hash('sha256', $uid . $instanceId . $instanceSecret, true);
+ $keySize = $this->getKeySize($cipher);
+
+ if (function_exists('hash_pbkdf2')) {
+ $hash = hash_pbkdf2(
+ 'sha256',
+ $password,
+ $salt,
+ 100000,
+ $keySize,
+ true
+ );
+ } else {
+ // fallback to 3rdparty lib for PHP <= 5.4.
+ // FIXME: Can be removed as soon as support for PHP 5.4 was dropped
+ $fallback = new PBKDF2Fallback();
+ $hash = $fallback->pbkdf2(
+ 'sha256',
+ $password,
+ $salt,
+ 100000,
+ $keySize,
+ true
+ );
+ }
+
+ return $hash;
+ }
+
+ /**
+ * encrypt private key
+ *
* @param string $privateKey
* @param string $password
+ * @param string $uid for regular users, empty for system keys
* @return bool|string
*/
- public function decryptPrivateKey($privateKey, $password = '') {
+ public function encryptPrivateKey($privateKey, $password, $uid = '') {
+ $cipher = $this->getCipher();
+ $hash = $this->generatePasswordHash($password, $cipher, $uid);
+ $encryptedKey = $this->symmetricEncryptFileContent(
+ $privateKey,
+ $hash
+ );
+
+ return $encryptedKey;
+ }
+
+ /**
+ * @param string $privateKey
+ * @param string $password
+ * @param string $uid for regular users, empty for system keys
+ * @return bool|string
+ */
+ public function decryptPrivateKey($privateKey, $password = '', $uid = '') {
$header = $this->parseHeader($privateKey);
@@ -252,6 +355,16 @@ class Crypt {
$cipher = self::LEGACY_CIPHER;
}
+ if (isset($header['keyFormat'])) {
+ $keyFormat = $header['keyFormat'];
+ } else {
+ $keyFormat = self::LEGACY_KEY_FORMAT;
+ }
+
+ if ($keyFormat === 'hash') {
+ $password = $this->generatePasswordHash($password, $cipher, $uid);
+ }
+
// If we found a header we need to remove it from the key we want to decrypt
if (!empty($header)) {
$privateKey = substr($privateKey,
@@ -263,18 +376,29 @@ class Crypt {
$password,
$cipher);
- // Check if this is a valid private key
+ if ($this->isValidPrivateKey($plainKey) === false) {
+ return false;
+ }
+
+ return $plainKey;
+ }
+
+ /**
+ * check if it is a valid private key
+ *
+ * @param $plainKey
+ * @return bool
+ */
+ protected function isValidPrivateKey($plainKey) {
$res = openssl_get_privatekey($plainKey);
if (is_resource($res)) {
$sslInfo = openssl_pkey_get_details($res);
- if (!isset($sslInfo['key'])) {
- return false;
+ if (isset($sslInfo['key'])) {
+ return true;
}
- } else {
- return false;
}
- return $plainKey;
+ return true;
}
/**
@@ -358,7 +482,7 @@ class Crypt {
* @param $data
* @return array
*/
- private function parseHeader($data) {
+ protected function parseHeader($data) {
$result = [];
if (substr($data, 0, strlen(self::HEADER_START)) === self::HEADER_START) {
diff --git a/apps/encryption/lib/keymanager.php b/apps/encryption/lib/keymanager.php
index 8c8c1f8fd78..6c793e5964f 100644
--- a/apps/encryption/lib/keymanager.php
+++ b/apps/encryption/lib/keymanager.php
@@ -146,7 +146,7 @@ class KeyManager {
Encryption::ID);
// Encrypt private key empty passphrase
- $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'], '');
+ $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], '');
$header = $this->crypt->generateHeader();
$this->setSystemPrivateKey($this->publicShareKeyId, $header . $encryptedKey);
}
@@ -184,8 +184,7 @@ class KeyManager {
*/
public function checkRecoveryPassword($password) {
$recoveryKey = $this->keyStorage->getSystemUserKey($this->recoveryKeyId . '.privateKey', Encryption::ID);
- $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey,
- $password);
+ $decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $password);
if ($decryptedRecoveryKey) {
return true;
@@ -203,8 +202,8 @@ class KeyManager {
// Save Public Key
$this->setPublicKey($uid, $keyPair['publicKey']);
- $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
- $password);
+ $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password, $uid);
+
$header = $this->crypt->generateHeader();
if ($encryptedKey) {
@@ -226,8 +225,7 @@ class KeyManager {
$keyPair['publicKey'],
Encryption::ID);
- $encryptedKey = $this->crypt->symmetricEncryptFileContent($keyPair['privateKey'],
- $password);
+ $encryptedKey = $this->crypt->encryptPrivateKey($keyPair['privateKey'], $password);
$header = $this->crypt->generateHeader();
if ($encryptedKey) {
@@ -308,8 +306,7 @@ class KeyManager {
try {
$privateKey = $this->getPrivateKey($uid);
- $privateKey = $this->crypt->decryptPrivateKey($privateKey,
- $passPhrase);
+ $privateKey = $this->crypt->decryptPrivateKey($privateKey, $passPhrase, $uid);
} catch (PrivateKeyMissingException $e) {
return false;
} catch (DecryptionFailedException $e) {
diff --git a/apps/encryption/lib/recovery.php b/apps/encryption/lib/recovery.php
index e31a14fba63..b22e3265628 100644
--- a/apps/encryption/lib/recovery.php
+++ b/apps/encryption/lib/recovery.php
@@ -136,7 +136,7 @@ class Recovery {
public function changeRecoveryKeyPassword($newPassword, $oldPassword) {
$recoveryKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
$decryptedRecoveryKey = $this->crypt->decryptPrivateKey($recoveryKey, $oldPassword);
- $encryptedRecoveryKey = $this->crypt->symmetricEncryptFileContent($decryptedRecoveryKey, $newPassword);
+ $encryptedRecoveryKey = $this->crypt->encryptPrivateKey($decryptedRecoveryKey, $newPassword);
$header = $this->crypt->generateHeader();
if ($encryptedRecoveryKey) {
$this->keyManager->setSystemPrivateKey($this->keyManager->getRecoveryKeyId(), $header . $encryptedRecoveryKey);
@@ -263,8 +263,7 @@ class Recovery {
public function recoverUsersFiles($recoveryPassword, $user) {
$encryptedKey = $this->keyManager->getSystemPrivateKey($this->keyManager->getRecoveryKeyId());
- $privateKey = $this->crypt->decryptPrivateKey($encryptedKey,
- $recoveryPassword);
+ $privateKey = $this->crypt->decryptPrivateKey($encryptedKey, $recoveryPassword);
$this->recoverAllFiles('/' . $user . '/files/', $privateKey, $user);
}
diff --git a/apps/encryption/tests/controller/SettingsControllerTest.php b/apps/encryption/tests/controller/SettingsControllerTest.php
index ed8135b9c4d..d985c7d7d25 100644
--- a/apps/encryption/tests/controller/SettingsControllerTest.php
+++ b/apps/encryption/tests/controller/SettingsControllerTest.php
@@ -188,7 +188,7 @@ class SettingsControllerTest extends TestCase {
$this->cryptMock
->expects($this->once())
- ->method('symmetricEncryptFileContent')
+ ->method('encryptPrivateKey')
->willReturn('encryptedKey');
$this->cryptMock
diff --git a/apps/encryption/tests/hooks/UserHooksTest.php b/apps/encryption/tests/hooks/UserHooksTest.php
index 921c924d015..aa16a4d8703 100644
--- a/apps/encryption/tests/hooks/UserHooksTest.php
+++ b/apps/encryption/tests/hooks/UserHooksTest.php
@@ -114,7 +114,7 @@ class UserHooksTest extends TestCase {
->willReturnOnConsecutiveCalls(true, false);
$this->cryptMock->expects($this->exactly(4))
- ->method('symmetricEncryptFileContent')
+ ->method('encryptPrivateKey')
->willReturn(true);
$this->cryptMock->expects($this->any())
diff --git a/apps/encryption/tests/lib/KeyManagerTest.php b/apps/encryption/tests/lib/KeyManagerTest.php
index 0bac5e0341b..71b00cf254a 100644
--- a/apps/encryption/tests/lib/KeyManagerTest.php
+++ b/apps/encryption/tests/lib/KeyManagerTest.php
@@ -260,7 +260,7 @@ class KeyManagerTest extends TestCase {
->method('setSystemUserKey')
->willReturn(true);
$this->cryptMock->expects($this->any())
- ->method('symmetricEncryptFileContent')
+ ->method('encryptPrivateKey')
->with($this->equalTo('privateKey'), $this->equalTo('pass'))
->willReturn('decryptedPrivateKey');
diff --git a/apps/encryption/tests/lib/RecoveryTest.php b/apps/encryption/tests/lib/RecoveryTest.php
index 8d5d31af0b8..c0624a36be9 100644
--- a/apps/encryption/tests/lib/RecoveryTest.php
+++ b/apps/encryption/tests/lib/RecoveryTest.php
@@ -96,7 +96,7 @@ class RecoveryTest extends TestCase {
->method('decryptPrivateKey');
$this->cryptMock->expects($this->once())
- ->method('symmetricEncryptFileContent')
+ ->method('encryptPrivateKey')
->willReturn(true);
$this->assertTrue($this->instance->changeRecoveryKeyPassword('password',
diff --git a/apps/encryption/tests/lib/crypto/cryptTest.php b/apps/encryption/tests/lib/crypto/cryptTest.php
index 14ed1513e1e..3c7767a8908 100644
--- a/apps/encryption/tests/lib/crypto/cryptTest.php
+++ b/apps/encryption/tests/lib/crypto/cryptTest.php
@@ -98,18 +98,41 @@ class cryptTest extends TestCase {
/**
- * test generateHeader
+ * test generateHeader with valid key formats
+ *
+ * @dataProvider dataTestGenerateHeader
*/
- public function testGenerateHeader() {
+ public function testGenerateHeader($keyFormat, $expected) {
$this->config->expects($this->once())
->method('getSystemValue')
->with($this->equalTo('cipher'), $this->equalTo('AES-256-CFB'))
->willReturn('AES-128-CFB');
- $this->assertSame('HBEGIN:cipher:AES-128-CFB:HEND',
- $this->crypt->generateHeader()
- );
+ if ($keyFormat) {
+ $result = $this->crypt->generateHeader($keyFormat);
+ } else {
+ $result = $this->crypt->generateHeader();
+ }
+
+ $this->assertSame($expected, $result);
+ }
+
+ /**
+ * test generateHeader with invalid key format
+ *
+ * @expectedException \InvalidArgumentException
+ */
+ public function testGenerateHeaderInvalid() {
+ $this->crypt->generateHeader('unknown');
+ }
+
+ public function dataTestGenerateHeader() {
+ return [
+ [null, 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash:HEND'],
+ ['password', 'HBEGIN:cipher:AES-128-CFB:keyFormat:password:HEND'],
+ ['hash', 'HBEGIN:cipher:AES-128-CFB:keyFormat:hash:HEND']
+ ];
}
/**
@@ -262,4 +285,82 @@ class cryptTest extends TestCase {
}
+ /**
+ * test return values of valid ciphers
+ *
+ * @dataProvider dataTestGetKeySize
+ */
+ public function testGetKeySize($cipher, $expected) {
+ $result = $this->invokePrivate($this->crypt, 'getKeySize', [$cipher]);
+ $this->assertSame($expected, $result);
+ }
+
+ /**
+ * test exception if cipher is unknown
+ *
+ * @expectedException \InvalidArgumentException
+ */
+ public function testGetKeySizeFailure() {
+ $this->invokePrivate($this->crypt, 'getKeySize', ['foo']);
+ }
+
+ public function dataTestGetKeySize() {
+ return [
+ ['AES-256-CFB', 32],
+ ['AES-128-CFB', 16],
+ ];
+ }
+
+ /**
+ * @dataProvider dataTestDecryptPrivateKey
+ */
+ public function testDecryptPrivateKey($header, $privateKey, $expectedCipher, $isValidKey, $expected) {
+ /** @var \OCA\Encryption\Crypto\Crypt | \PHPUnit_Framework_MockObject_MockObject $crypt */
+ $crypt = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')
+ ->setConstructorArgs(
+ [
+ $this->logger,
+ $this->userSession,
+ $this->config
+ ]
+ )
+ ->setMethods(
+ [
+ 'parseHeader',
+ 'generatePasswordHash',
+ 'symmetricDecryptFileContent',
+ 'isValidPrivateKey'
+ ]
+ )
+ ->getMock();
+
+ $crypt->expects($this->once())->method('parseHeader')->willReturn($header);
+ if (isset($header['keyFormat']) && $header['keyFormat'] === 'hash') {
+ $crypt->expects($this->once())->method('generatePasswordHash')->willReturn('hash');
+ $password = 'hash';
+ } else {
+ $crypt->expects($this->never())->method('generatePasswordHash');
+ $password = 'password';
+ }
+
+ $crypt->expects($this->once())->method('symmetricDecryptFileContent')
+ ->with('privateKey', $password, $expectedCipher)->willReturn('key');
+ $crypt->expects($this->once())->method('isValidPrivateKey')->willReturn($isValidKey);
+
+ $result = $crypt->decryptPrivateKey($privateKey, 'password');
+
+ $this->assertSame($expected, $result);
+ }
+
+ public function dataTestDecryptPrivateKey() {
+ return [
+ [['cipher' => 'AES-128-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-128-CFB', true, 'key'],
+ [['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
+ [['cipher' => 'AES-256-CFB', 'keyFormat' => 'password'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', false, false],
+ [['cipher' => 'AES-256-CFB', 'keyFormat' => 'hash'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
+ [['cipher' => 'AES-256-CFB'], 'HBEGIN:HENDprivateKey', 'AES-256-CFB', true, 'key'],
+ [[], 'privateKey', 'AES-128-CFB', true, 'key'],
+ ];
+ }
+
}
diff --git a/apps/encryption/vendor/pbkdf2fallback.php b/apps/encryption/vendor/pbkdf2fallback.php
new file mode 100644
index 00000000000..ca579f8e7dc
--- /dev/null
+++ b/apps/encryption/vendor/pbkdf2fallback.php
@@ -0,0 +1,87 @@
+<?php
+/* Note; This class can be removed as soon as we drop PHP 5.4 support.
+ *
+ *
+ * Password Hashing With PBKDF2 (http://crackstation.net/hashing-security.htm).
+ * Copyright (c) 2013, Taylor Hornby
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace OCA\Encryption\Vendor;
+
+class PBKDF2Fallback {
+
+ /*
+ * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
+ * $algorithm - The hash algorithm to use. Recommended: SHA256
+ * $password - The password.
+ * $salt - A salt that is unique to the password.
+ * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
+ * $key_length - The length of the derived key in bytes.
+ * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
+ * Returns: A $key_length-byte key derived from the password and salt.
+ *
+ * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
+ *
+ * This implementation of PBKDF2 was originally created by https://defuse.ca
+ * With improvements by http://www.variations-of-shadow.com
+ */
+ public function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false) {
+ $algorithm = strtolower($algorithm);
+ if (!in_array($algorithm, hash_algos(), true))
+ trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
+ if ($count <= 0 || $key_length <= 0)
+ trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
+
+ if (function_exists("hash_pbkdf2")) {
+ // The output length is in NIBBLES (4-bits) if $raw_output is false!
+ if (!$raw_output) {
+ $key_length = $key_length * 2;
+ }
+ return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
+ }
+
+ $hash_length = strlen(hash($algorithm, "", true));
+ $block_count = ceil($key_length / $hash_length);
+
+ $output = "";
+ for ($i = 1; $i <= $block_count; $i++) {
+ // $i encoded as 4 bytes, big endian.
+ $last = $salt . pack("N", $i);
+ // first iteration
+ $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
+ // perform the other $count - 1 iterations
+ for ($j = 1; $j < $count; $j++) {
+ $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
+ }
+ $output .= $xorsum;
+ }
+
+ if ($raw_output)
+ return substr($output, 0, $key_length);
+ else
+ return bin2hex(substr($output, 0, $key_length));
+ }
+}
diff --git a/apps/files/appinfo/update.php b/apps/files/appinfo/update.php
index 2691c05c348..ff1369bb1a5 100644
--- a/apps/files/appinfo/update.php
+++ b/apps/files/appinfo/update.php
@@ -94,3 +94,12 @@ if ($installedVersion === '1.1.9' && (
}
}
}
+
+/**
+ * migrate old constant DEBUG to new config value 'debug'
+ *
+ * TODO: remove this in ownCloud 8.3
+ */
+if(defined('DEBUG') && DEBUG === true) {
+ \OC::$server->getConfig()->setSystemValue('debug', true);
+}
diff --git a/apps/files/appinfo/version b/apps/files/appinfo/version
index 5ed5faa5f16..9ee1f786d50 100644
--- a/apps/files/appinfo/version
+++ b/apps/files/appinfo/version
@@ -1 +1 @@
-1.1.10
+1.1.11
diff --git a/apps/files/css/detailsView.css b/apps/files/css/detailsView.css
index 76629cb790f..dafd8c24573 100644
--- a/apps/files/css/detailsView.css
+++ b/apps/files/css/detailsView.css
@@ -12,11 +12,11 @@
}
#app-sidebar .thumbnail {
- width: 50px;
- height: 50px;
+ width: 75px;
+ height: 75px;
float: left;
margin-right: 10px;
- background-size: 50px;
+ background-size: 75px;
}
#app-sidebar .ellipsis {
@@ -27,7 +27,8 @@
#app-sidebar .fileName {
font-size: 16px;
- padding-top: 3px;
+ padding-top: 13px;
+ padding-bottom: 3px;
}
#app-sidebar .file-details {
diff --git a/apps/files/css/files.css b/apps/files/css/files.css
index 26ba86b28c8..d66eece94d9 100644
--- a/apps/files/css/files.css
+++ b/apps/files/css/files.css
@@ -275,6 +275,11 @@ table.multiselect thead th {
font-weight: bold;
border-bottom: 0;
}
+
+#app-content.with-app-sidebar table.multiselect thead{
+ margin-right: 27%;
+}
+
table.multiselect #headerName {
position: relative;
width: 9999px; /* when we use 100%, the styling breaks on mobile … table styling */
diff --git a/apps/files/js/detailtabview.js b/apps/files/js/detailtabview.js
index 67f8b535abd..b0e170bc4e7 100644
--- a/apps/files/js/detailtabview.js
+++ b/apps/files/js/detailtabview.js
@@ -88,6 +88,8 @@
});
DetailTabView._TAB_COUNT = 0;
+ OCA.Files = OCA.Files || {};
+
OCA.Files.DetailTabView = DetailTabView;
})();
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index eb46f155269..e294e2f3c09 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -673,6 +673,7 @@
id: parseInt($el.attr('data-id'), 10),
name: $el.attr('data-file'),
mimetype: $el.attr('data-mime'),
+ mtime: parseInt($el.attr('data-mtime'), 10),
type: $el.attr('data-type'),
size: parseInt($el.attr('data-size'), 10),
etag: $el.attr('data-etag'),
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index 6910e5f2be5..8bf22149841 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -125,8 +125,8 @@
path: this.model.getFullPath(),
mime: this.model.get('mimetype'),
etag: this.model.get('etag'),
- x: 50,
- y: 50,
+ x: 75,
+ y: 75,
callback: function(previewUrl) {
$iconDiv.css('background-image', 'url("' + previewUrl + '")');
}
diff --git a/apps/files/tests/ajax_rename.php b/apps/files/tests/ajax_rename.php
index a690c7dcb0c..8abde9094d9 100644
--- a/apps/files/tests/ajax_rename.php
+++ b/apps/files/tests/ajax_rename.php
@@ -116,7 +116,7 @@ class Test_OC_Files_App_Rename extends \Test\TestCase {
$this->assertEquals('abcdef', $result['data']['etag']);
$this->assertFalse(isset($result['data']['tags']));
$this->assertEquals('/', $result['data']['path']);
- $icon = \OC_Helper::mimetypeIcon('dir');
+ $icon = \OC_Helper::mimetypeIcon('dir-external');
$icon = substr($icon, 0, -3) . 'svg';
$this->assertEquals($icon, $result['data']['icon']);
}
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 7ed60084fa9..a6d72a88efd 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -98,6 +98,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'file',
name: 'One.txt',
mimetype: 'text/plain',
+ mtime: 123456789,
size: 12,
etag: 'abc',
permissions: OC.PERMISSION_ALL
@@ -106,6 +107,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'file',
name: 'Two.jpg',
mimetype: 'image/jpeg',
+ mtime: 234567890,
size: 12049,
etag: 'def',
permissions: OC.PERMISSION_ALL
@@ -114,6 +116,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'file',
name: 'Three.pdf',
mimetype: 'application/pdf',
+ mtime: 234560000,
size: 58009,
etag: '123',
permissions: OC.PERMISSION_ALL
@@ -122,6 +125,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'dir',
name: 'somedir',
mimetype: 'httpd/unix-directory',
+ mtime: 134560000,
size: 250,
etag: '456',
permissions: OC.PERMISSION_ALL
@@ -1722,6 +1726,7 @@ describe('OCA.Files.FileList tests', function() {
id: 1,
name: 'One.txt',
mimetype: 'text/plain',
+ mtime: 123456789,
type: 'file',
size: 12,
etag: 'abc',
@@ -1732,6 +1737,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'file',
name: 'Three.pdf',
mimetype: 'application/pdf',
+ mtime: 234560000,
size: 58009,
etag: '123',
permissions: OC.PERMISSION_ALL
@@ -1741,6 +1747,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'dir',
name: 'somedir',
mimetype: 'httpd/unix-directory',
+ mtime: 134560000,
size: 250,
etag: '456',
permissions: OC.PERMISSION_ALL
@@ -1754,6 +1761,7 @@ describe('OCA.Files.FileList tests', function() {
id: 1,
name: 'One.txt',
mimetype: 'text/plain',
+ mtime: 123456789,
type: 'file',
size: 12,
etag: 'abc',
@@ -1764,6 +1772,7 @@ describe('OCA.Files.FileList tests', function() {
type: 'dir',
name: 'somedir',
mimetype: 'httpd/unix-directory',
+ mtime: 134560000,
size: 250,
etag: '456',
permissions: OC.PERMISSION_ALL
@@ -2330,4 +2339,24 @@ describe('OCA.Files.FileList tests', function() {
});
});
});
+ describe('elementToFile', function() {
+ var $tr;
+
+ beforeEach(function() {
+ fileList.setFiles(testFiles);
+ $tr = fileList.findFileEl('One.txt');
+ });
+
+ it('converts data attributes to file info structure', function() {
+ var fileInfo = fileList.elementToFile($tr);
+ expect(fileInfo.id).toEqual(1);
+ expect(fileInfo.name).toEqual('One.txt');
+ expect(fileInfo.mtime).toEqual(123456789);
+ expect(fileInfo.etag).toEqual('abc');
+ expect(fileInfo.permissions).toEqual(OC.PERMISSION_ALL);
+ expect(fileInfo.size).toEqual(12);
+ expect(fileInfo.mimetype).toEqual('text/plain');
+ expect(fileInfo.type).toEqual('file');
+ });
+ });
});
diff --git a/apps/files_external/ajax/applicable.php b/apps/files_external/ajax/applicable.php
index 1b93cc3a1aa..5ae91c8e182 100644
--- a/apps/files_external/ajax/applicable.php
+++ b/apps/files_external/ajax/applicable.php
@@ -37,8 +37,15 @@ if (isset($_GET['offset'])) {
$offset = (int)$_GET['offset'];
}
-$groups = \OC_Group::getGroups($pattern, $limit, $offset);
-$users = \OCP\User::getDisplayNames($pattern, $limit, $offset);
+$groups = [];
+foreach (\OC::$server->getGroupManager()->search($pattern, $limit, $offset) as $group) {
+ $groups[$group->getGID()] = $group->getGID();
+}
+
+$users = [];
+foreach (\OC::$server->getUserManager()->searchDisplayName($pattern, $limit, $offset) as $user) {
+ $users[$user->getUID()] = $user->getDisplayName();
+}
$results = array('groups' => $groups, 'users' => $users);
diff --git a/apps/files_external/appinfo/routes.php b/apps/files_external/appinfo/routes.php
index 213e7b28dc1..4462ad1f274 100644
--- a/apps/files_external/appinfo/routes.php
+++ b/apps/files_external/appinfo/routes.php
@@ -26,7 +26,7 @@
namespace OCA\Files_External\AppInfo;
/**
- * @var $this \OC\Route\Router
+ * @var $this \OCP\Route\IRouter
**/
\OC_Mount_Config::$app->registerRoutes(
$this,
diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js
index 6bf0143f1c0..d3e20e38445 100644
--- a/apps/files_external/js/settings.js
+++ b/apps/files_external/js/settings.js
@@ -704,6 +704,7 @@ MountConfigListView.prototype = {
var $tr = $target.closest('tr');
$el.find('tbody').append($tr.clone());
$el.find('tbody tr').last().find('.mountPoint input').val('');
+ $tr.data('constructing', true);
var selected = $target.find('option:selected').text();
var backend = $target.val();
$tr.find('.backend').text(selected);
@@ -739,6 +740,9 @@ MountConfigListView.prototype = {
$tr.removeAttr('id');
$target.remove();
addSelect2($tr.find('.applicableUsers'), this._userListLimit);
+
+ $tr.removeData('constructing');
+ this.saveStorageConfig($tr);
},
_onSelectAuthMechanism: function(event) {
@@ -753,6 +757,11 @@ MountConfigListView.prototype = {
$.each(authMechanismConfiguration['configuration'], _.partial(
this.writeParameterInput, $td, _, _, ['auth-param']
));
+
+ if ($tr.data('constructing') !== true) {
+ // row is ready, trigger recheck
+ this.saveStorageConfig($tr);
+ }
},
writeParameterInput: function($td, parameter, placeholder, classes) {
diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php
index 40f07b2b22a..7c6ac4cbdd5 100644
--- a/apps/files_external/lib/amazons3.php
+++ b/apps/files_external/lib/amazons3.php
@@ -372,7 +372,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
switch ($mode) {
case 'r':
case 'rb':
- $tmpFile = \OC_Helper::tmpFile();
+ $tmpFile = \OCP\Files::tmpFile();
self::$tmpFiles[$tmpFile] = $path;
try {
@@ -404,7 +404,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
} else {
$ext = '';
}
- $tmpFile = \OC_Helper::tmpFile($ext);
+ $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
@@ -464,7 +464,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
]);
$this->testTimeout();
} else {
- $mimeType = \OC_Helper::getMimetypeDetector()->detectPath($path);
+ $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
$this->getConnection()->putObject([
'Bucket' => $this->bucket,
'Key' => $this->cleanKey($path),
@@ -629,7 +629,7 @@ class AmazonS3 extends \OC\Files\Storage\Common {
'Bucket' => $this->bucket,
'Key' => $this->cleanKey(self::$tmpFiles[$tmpFile]),
'SourceFile' => $tmpFile,
- 'ContentType' => \OC_Helper::getMimeType($tmpFile),
+ 'ContentType' => \OC::$server->getMimeTypeDetector()->detect($tmpFile),
'ContentLength' => filesize($tmpFile)
));
$this->testTimeout();
diff --git a/apps/files_external/lib/api.php b/apps/files_external/lib/api.php
index b9435e33105..015c15c41ff 100644
--- a/apps/files_external/lib/api.php
+++ b/apps/files_external/lib/api.php
@@ -71,7 +71,7 @@ class Api {
*/
public static function getUserMounts($params) {
$entries = array();
- $user = \OC_User::getUser();
+ $user = \OC::$server->getUserSession()->getUser()->getUID();
$mounts = \OC_Mount_Config::getAbsoluteMountPoints($user);
foreach($mounts as $mountPoint => $mount) {
diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php
index 2a523144f7f..62932dc4028 100644
--- a/apps/files_external/lib/config.php
+++ b/apps/files_external/lib/config.php
@@ -86,10 +86,9 @@ class OC_Mount_Config {
self::addStorageIdToConfig($data['user']);
$user = \OC::$server->getUserManager()->get($data['user']);
if (!$user) {
- \OCP\Util::writeLog(
- 'files_external',
+ \OC::$server->getLogger()->warning(
'Cannot init external mount points for non-existant user "' . $data['user'] . '".',
- \OCP\Util::WARN
+ ['app' => 'files_external']
);
return;
}
@@ -281,10 +280,11 @@ class OC_Mount_Config {
*/
public static function readData($user = null) {
if (isset($user)) {
- $jsonFile = OC_User::getHome($user) . '/mount.json';
+ $jsonFile = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
} else {
- $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
- $jsonFile = \OC_Config::getValue('mount_file', $datadir . '/mount.json');
+ $config = \OC::$server->getConfig();
+ $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ $jsonFile = $config->getSystemValue('mount_file', $datadir . '/mount.json');
}
if (is_file($jsonFile)) {
$mountPoints = json_decode(file_get_contents($jsonFile), true);
@@ -303,10 +303,11 @@ class OC_Mount_Config {
*/
public static function writeData($user, $data) {
if (isset($user)) {
- $file = OC_User::getHome($user) . '/mount.json';
+ $file = \OC::$server->getUserManager()->get($user)->getHome() . '/mount.json';
} else {
- $datadir = \OC_Config::getValue('datadirectory', \OC::$SERVERROOT . '/data/');
- $file = \OC_Config::getValue('mount_file', $datadir . '/mount.json');
+ $config = \OC::$server->getConfig();
+ $datadir = $config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data/');
+ $file = $config->getSystemValue('mount_file', $datadir . '/mount.json');
}
foreach ($data as &$applicables) {
@@ -330,7 +331,7 @@ class OC_Mount_Config {
* @return string
*/
public static function dependencyMessage($backends) {
- $l = new \OC_L10N('files_external');
+ $l = \OC::$server->getL10N('files_external');
$message = '';
$dependencyGroups = [];
@@ -357,12 +358,12 @@ class OC_Mount_Config {
/**
* Returns a dependency missing message
*
- * @param OC_L10N $l
+ * @param \OCP\IL10N $l
* @param string $module
* @param string $backend
* @return string
*/
- private static function getSingleDependencyMessage(OC_L10N $l, $module, $backend) {
+ private static function getSingleDependencyMessage(\OCP\IL10N $l, $module, $backend) {
switch (strtolower($module)) {
case 'curl':
return $l->t('<b>Note:</b> The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it.', $backend);
diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php
index 2d1aea1afc8..4ab14d4f3e0 100644
--- a/apps/files_external/lib/dropbox.php
+++ b/apps/files_external/lib/dropbox.php
@@ -244,7 +244,7 @@ class Dropbox extends \OC\Files\Storage\Common {
switch ($mode) {
case 'r':
case 'rb':
- $tmpFile = \OC_Helper::tmpFile();
+ $tmpFile = \OCP\Files::tmpFile();
try {
$data = $this->dropbox->getFile($path);
file_put_contents($tmpFile, $data);
@@ -270,7 +270,7 @@ class Dropbox extends \OC\Files\Storage\Common {
} else {
$ext = '';
}
- $tmpFile = \OC_Helper::tmpFile($ext);
+ $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
diff --git a/apps/files_external/lib/failedstorage.php b/apps/files_external/lib/failedstorage.php
index 6afa98052c2..22ee5326491 100644
--- a/apps/files_external/lib/failedstorage.php
+++ b/apps/files_external/lib/failedstorage.php
@@ -197,4 +197,12 @@ class FailedStorage extends Common {
throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e);
}
+ public function getAvailability() {
+ throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e);
+ }
+
+ public function setAvailability($isAvailable) {
+ throw new StorageNotAvailableException($this->e->getMessage(), $this->e->getCode(), $this->e);
+ }
+
}
diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php
index 2ca550dfe7c..e29b1036244 100644
--- a/apps/files_external/lib/google.php
+++ b/apps/files_external/lib/google.php
@@ -429,7 +429,7 @@ class Google extends \OC\Files\Storage\Common {
$request = new \Google_Http_Request($downloadUrl, 'GET', null, null);
$httpRequest = $this->client->getAuth()->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
- $tmpFile = \OC_Helper::tmpFile($ext);
+ $tmpFile = \OCP\Files::tmpFile($ext);
$data = $httpRequest->getResponseBody();
file_put_contents($tmpFile, $data);
return fopen($tmpFile, $mode);
@@ -449,7 +449,7 @@ class Google extends \OC\Files\Storage\Common {
case 'x+':
case 'c':
case 'c+':
- $tmpFile = \OC_Helper::tmpFile($ext);
+ $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'rb');
@@ -466,7 +466,7 @@ class Google extends \OC\Files\Storage\Common {
$parentFolder = $this->getDriveFile(dirname($path));
if ($parentFolder) {
// TODO Research resumable upload
- $mimetype = \OC_Helper::getMimeType($tmpFile);
+ $mimetype = \OC::$server->getMimeTypeDetector()->detect($tmpFile);
$data = file_get_contents($tmpFile);
$params = array(
'data' => $data,
diff --git a/apps/files_external/lib/sessionstoragewrapper.php b/apps/files_external/lib/sessionstoragewrapper.php
index 91be7eb1903..f8f5aba53a2 100644
--- a/apps/files_external/lib/sessionstoragewrapper.php
+++ b/apps/files_external/lib/sessionstoragewrapper.php
@@ -33,7 +33,7 @@ class SessionStorageWrapper extends PermissionsMask {
/**
* @param array $arguments ['storage' => $storage]
*/
- public function __construct(array $arguments) {
+ public function __construct($arguments) {
// disable sharing permission
$arguments['mask'] = Constants::PERMISSION_ALL & ~Constants::PERMISSION_SHARE;
parent::__construct($arguments);
diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php
index d8107e58fed..6f93f3c84cd 100644
--- a/apps/files_external/lib/swift.php
+++ b/apps/files_external/lib/swift.php
@@ -310,7 +310,7 @@ class Swift extends \OC\Files\Storage\Common {
switch ($mode) {
case 'r':
case 'rb':
- $tmpFile = \OC_Helper::tmpFile();
+ $tmpFile = \OCP\Files::tmpFile();
self::$tmpFiles[$tmpFile] = $path;
try {
$object = $this->getContainer()->getObject($path);
@@ -348,7 +348,7 @@ class Swift extends \OC\Files\Storage\Common {
} else {
$ext = '';
}
- $tmpFile = \OC_Helper::tmpFile($ext);
+ $tmpFile = \OCP\Files::tmpFile($ext);
\OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack'));
if ($this->file_exists($path)) {
$source = $this->fopen($path, 'r');
@@ -387,7 +387,7 @@ class Swift extends \OC\Files\Storage\Common {
$object->saveMetadata($metadata);
return true;
} else {
- $mimeType = \OC_Helper::getMimetypeDetector()->detectPath($path);
+ $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
$customHeaders = array('content-type' => $mimeType);
$metadataHeaders = DataObject::stockHeaders($metadata);
$allHeaders = $customHeaders + $metadataHeaders;
diff --git a/apps/files_external/service/backendservice.php b/apps/files_external/service/backendservice.php
index bee08ecbd15..382834b4c19 100644
--- a/apps/files_external/service/backendservice.php
+++ b/apps/files_external/service/backendservice.php
@@ -140,7 +140,7 @@ class BackendService {
*/
public function getAvailableBackends() {
return array_filter($this->getBackends(), function($backend) {
- return empty($backend->checkDependencies());
+ return !($backend->checkDependencies());
});
}
@@ -256,7 +256,7 @@ class BackendService {
*/
protected function isAllowedUserBackend(Backend $backend) {
if ($this->userMountingAllowed &&
- !empty(array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends))
+ array_intersect($backend->getIdentifierAliases(), $this->userMountingBackends)
) {
return true;
}
diff --git a/apps/files_external/service/storagesservice.php b/apps/files_external/service/storagesservice.php
index 63e71627785..3e2152741e5 100644
--- a/apps/files_external/service/storagesservice.php
+++ b/apps/files_external/service/storagesservice.php
@@ -426,7 +426,7 @@ abstract class StoragesService {
*/
protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray) {
foreach ($applicableArray as $applicable) {
- \OC_Hook::emit(
+ \OCP\Util::emitHook(
Filesystem::CLASSNAME,
$signal,
[
diff --git a/apps/files_external/service/userglobalstoragesservice.php b/apps/files_external/service/userglobalstoragesservice.php
index 78520419556..c59652d057f 100644
--- a/apps/files_external/service/userglobalstoragesservice.php
+++ b/apps/files_external/service/userglobalstoragesservice.php
@@ -76,20 +76,25 @@ class UserGlobalStoragesService extends GlobalStoragesService {
$data = parent::readLegacyConfig();
$userId = $this->getUser()->getUID();
+ // don't use array_filter() with ARRAY_FILTER_USE_KEY, it's PHP 5.6+
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_USER])) {
- $data[\OC_Mount_Config::MOUNT_TYPE_USER] = array_filter(
- $data[\OC_Mount_Config::MOUNT_TYPE_USER], function($key) use ($userId) {
- return (strtolower($key) === strtolower($userId) || $key === 'all');
- }, ARRAY_FILTER_USE_KEY
- );
+ $newData = [];
+ foreach ($data[\OC_Mount_Config::MOUNT_TYPE_USER] as $key => $value) {
+ if (strtolower($key) === strtolower($userId) || $key === 'all') {
+ $newData[$key] = $value;
+ }
+ }
+ $data[\OC_Mount_Config::MOUNT_TYPE_USER] = $newData;
}
if (isset($data[\OC_Mount_Config::MOUNT_TYPE_GROUP])) {
- $data[\OC_Mount_Config::MOUNT_TYPE_GROUP] = array_filter(
- $data[\OC_Mount_Config::MOUNT_TYPE_GROUP], function($key) use ($userId) {
- return ($this->groupManager->isInGroup($userId, $key));
- }, ARRAY_FILTER_USE_KEY
- );
+ $newData = [];
+ foreach ($data[\OC_Mount_Config::MOUNT_TYPE_GROUP] as $key => $value) {
+ if ($this->groupManager->isInGroup($userId, $key)) {
+ $newData[$key] = $value;
+ }
+ }
+ $data[\OC_Mount_Config::MOUNT_TYPE_GROUP] = $newData;
}
return $data;
diff --git a/apps/files_external/settings.php b/apps/files_external/settings.php
index 9cecc0c6a49..29c0553158f 100644
--- a/apps/files_external/settings.php
+++ b/apps/files_external/settings.php
@@ -28,7 +28,7 @@
use \OCA\Files_External\Service\BackendService;
-OC_Util::checkAdminUser();
+\OCP\User::checkAdminUser();
// we must use the same container
$appContainer = \OC_Mount_Config::$app->getContainer();
diff --git a/apps/files_external/templates/list.php b/apps/files_external/templates/list.php
index 750bf1dae18..c2f68b9c5ba 100644
--- a/apps/files_external/templates/list.php
+++ b/apps/files_external/templates/list.php
@@ -1,4 +1,4 @@
-<?php /** @var $l OC_L10N */ ?>
+<?php /** @var $l \OCP\IL10N */ ?>
<div id="controls">
<div id="file_action_panel"></div>
</div>
diff --git a/apps/files_external/tests/service/userstoragesservicetest.php b/apps/files_external/tests/service/userstoragesservicetest.php
index 0d5b82e2f8c..8bbfbe5a050 100644
--- a/apps/files_external/tests/service/userstoragesservicetest.php
+++ b/apps/files_external/tests/service/userstoragesservicetest.php
@@ -31,9 +31,14 @@ class UserStoragesServiceTest extends StoragesServiceTest {
public function setUp() {
parent::setUp();
+ $userManager = \OC::$server->getUserManager();
+
$this->userId = $this->getUniqueID('user_');
+ $this->user = $userManager->createUser(
+ $this->userId,
+ $this->userId
+ );
- $this->user = new \OC\User\User($this->userId, null);
$userSession = $this->getMock('\OCP\IUserSession');
$userSession
->expects($this->any())
@@ -48,6 +53,7 @@ class UserStoragesServiceTest extends StoragesServiceTest {
public function tearDown() {
@unlink($this->dataDir . '/' . $this->userId . '/mount.json');
+ $this->user->delete();
parent::tearDown();
}
diff --git a/apps/files_sharing/ajax/testremote.php b/apps/files_sharing/ajax/testremote.php
deleted file mode 100644
index 0a0548dbbd2..00000000000
--- a/apps/files_sharing/ajax/testremote.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <icewind@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/>
- *
- */
-
-OCP\JSON::callCheck();
-OCP\JSON::checkAppEnabled('files_sharing');
-
-$remote = $_GET['remote'];
-
-function testUrl($url) {
- try {
- $result = file_get_contents($url);
- $data = json_decode($result);
- // public link mount is only supported in ownCloud 7+
- return is_object($data) and !empty($data->version) and version_compare($data->version, '7.0.0', '>=');
- } catch (Exception $e) {
- return false;
- }
-}
-
-if (testUrl('https://' . $remote . '/status.php')) {
- echo 'https';
-} elseif (testUrl('http://' . $remote . '/status.php')) {
- echo 'http';
-} else {
- echo 'false';
-}
diff --git a/apps/files_sharing/api/server2server.php b/apps/files_sharing/api/server2server.php
index 211dc52c333..4328e3830ba 100644
--- a/apps/files_sharing/api/server2server.php
+++ b/apps/files_sharing/api/server2server.php
@@ -111,9 +111,14 @@ class Server2Server {
if ($share) {
list($file, $link) = self::getFile($share['uid_owner'], $share['file_source']);
- \OC::$server->getActivityManager()->publishActivity(
- Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, array($share['share_with'], basename($file)), '', array(),
- $file, $link, $share['uid_owner'], Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_LOW);
+ $event = \OC::$server->getActivityManager()->generateEvent();
+ $event->setApp(Activity::FILES_SHARING_APP)
+ ->setType(Activity::TYPE_REMOTE_SHARE)
+ ->setAffectedUser($share['uid_owner'])
+ ->setSubject(Activity::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share['share_with'], basename($file)])
+ ->setObject('files', $share['file_source'], $file)
+ ->setLink($link);
+ \OC::$server->getActivityManager()->publish($event);
}
return new \OC_OCS_Result();
@@ -142,9 +147,14 @@ class Server2Server {
list($file, $link) = $this->getFile($share['uid_owner'], $share['file_source']);
- \OC::$server->getActivityManager()->publishActivity(
- Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_DECLINED, array($share['share_with'], basename($file)), '', array(),
- $file, $link, $share['uid_owner'], Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_LOW);
+ $event = \OC::$server->getActivityManager()->generateEvent();
+ $event->setApp(Activity::FILES_SHARING_APP)
+ ->setType(Activity::TYPE_REMOTE_SHARE)
+ ->setAffectedUser($share['uid_owner'])
+ ->setSubject(Activity::SUBJECT_REMOTE_SHARE_DECLINED, [$share['share_with'], basename($file)])
+ ->setObject('files', $share['file_source'], $file)
+ ->setLink($link);
+ \OC::$server->getActivityManager()->publish($event);
}
return new \OC_OCS_Result();
diff --git a/apps/files_sharing/appinfo/application.php b/apps/files_sharing/appinfo/application.php
index 2fe9019d54e..530195c65fa 100644
--- a/apps/files_sharing/appinfo/application.php
+++ b/apps/files_sharing/appinfo/application.php
@@ -62,7 +62,8 @@ class Application extends App {
$c->query('AppName'),
$c->query('Request'),
$c->query('IsIncomingShareEnabled'),
- $c->query('ExternalManager')
+ $c->query('ExternalManager'),
+ $c->query('HttpClientService')
);
});
@@ -78,6 +79,9 @@ class Application extends App {
$container->registerService('UserManager', function (SimpleContainer $c) use ($server) {
return $server->getUserManager();
});
+ $container->registerService('HttpClientService', function (SimpleContainer $c) use ($server) {
+ return $server->getHTTPClientService();
+ });
$container->registerService('IsIncomingShareEnabled', function (SimpleContainer $c) {
return Helper::isIncomingServer2serverShareEnabled();
});
diff --git a/apps/files_sharing/appinfo/routes.php b/apps/files_sharing/appinfo/routes.php
index 1e99267a43a..184ad29bba4 100644
--- a/apps/files_sharing/appinfo/routes.php
+++ b/apps/files_sharing/appinfo/routes.php
@@ -33,7 +33,14 @@ $application = new Application();
$application->registerRoutes($this, [
'resources' => [
'ExternalShares' => ['url' => '/api/externalShares'],
- ]
+ ],
+ 'routes' => [
+ [
+ 'name' => 'externalShares#testRemote',
+ 'url' => '/testremote',
+ 'verb' => 'GET'
+ ],
+ ],
]);
/** @var $this \OCP\Route\IRouter */
@@ -50,8 +57,6 @@ $this->create('sharing_external_shareinfo', '/shareinfo')
->actionInclude('files_sharing/ajax/shareinfo.php');
$this->create('sharing_external_add', '/external')
->actionInclude('files_sharing/ajax/external.php');
-$this->create('sharing_external_test_remote', '/testremote')
- ->actionInclude('files_sharing/ajax/testremote.php');
// OCS API
diff --git a/apps/files_sharing/css/settings-personal.css b/apps/files_sharing/css/settings-personal.css
index c9af6c08c40..f53365c9371 100644
--- a/apps/files_sharing/css/settings-personal.css
+++ b/apps/files_sharing/css/settings-personal.css
@@ -4,6 +4,7 @@
#fileSharingSettings xmp {
margin-top: 0;
+ white-space: pre-wrap;
}
[class^="social-"], [class*=" social-"] {
diff --git a/apps/files_sharing/lib/controllers/externalsharescontroller.php b/apps/files_sharing/lib/controllers/externalsharescontroller.php
index 494a544b2b8..6eb9d3c13d9 100644
--- a/apps/files_sharing/lib/controllers/externalsharescontroller.php
+++ b/apps/files_sharing/lib/controllers/externalsharescontroller.php
@@ -23,11 +23,11 @@
namespace OCA\Files_Sharing\Controllers;
-use OC;
-use OCP;
use OCP\AppFramework\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\JSONResponse;
+use OCP\Http\Client\IClientService;
+use OCP\AppFramework\Http\DataResponse;
/**
* Class ExternalSharesController
@@ -40,20 +40,25 @@ class ExternalSharesController extends Controller {
private $incomingShareEnabled;
/** @var \OCA\Files_Sharing\External\Manager */
private $externalManager;
+ /** @var IClientService */
+ private $clientService;
/**
* @param string $appName
* @param IRequest $request
* @param bool $incomingShareEnabled
* @param \OCA\Files_Sharing\External\Manager $externalManager
+ * @param IClientService $clientService
*/
public function __construct($appName,
IRequest $request,
$incomingShareEnabled,
- \OCA\Files_Sharing\External\Manager $externalManager) {
+ \OCA\Files_Sharing\External\Manager $externalManager,
+ IClientService $clientService) {
parent::__construct($appName, $request);
$this->incomingShareEnabled = $incomingShareEnabled;
$this->externalManager = $externalManager;
+ $this->clientService = $clientService;
}
/**
@@ -97,4 +102,43 @@ class ExternalSharesController extends Controller {
return new JSONResponse();
}
+ /**
+ * Test whether the specified remote is accessible
+ *
+ * @param string $remote
+ * @return bool
+ */
+ protected function testUrl($remote) {
+ try {
+ $client = $this->clientService->newClient();
+ $response = json_decode($client->get(
+ $remote,
+ [
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ )->getBody());
+
+ return !empty($response->version) && version_compare($response->version, '7.0.0', '>=');
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * @PublicPage
+ *
+ * @param string $remote
+ * @return DataResponse
+ */
+ public function testRemote($remote) {
+ if ($this->testUrl('https://' . $remote . '/status.php')) {
+ return new DataResponse('https');
+ } elseif ($this->testUrl('http://' . $remote . '/status.php')) {
+ return new DataResponse('http');
+ } else {
+ return new DataResponse(false);
+ }
+ }
+
}
diff --git a/apps/files_sharing/lib/external/storage.php b/apps/files_sharing/lib/external/storage.php
index dc8d1738b05..270d8b6d1b8 100644
--- a/apps/files_sharing/lib/external/storage.php
+++ b/apps/files_sharing/lib/external/storage.php
@@ -88,6 +88,8 @@ class Storage extends DAV implements ISharedStorage {
'user' => $options['token'],
'password' => (string)$options['password']
));
+
+ $this->getWatcher()->setPolicy(\OC\Files\Cache\Watcher::CHECK_ONCE);
}
public function getRemoteUser() {
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php
index 66803db1425..c7529df0617 100644
--- a/apps/files_sharing/lib/sharedstorage.php
+++ b/apps/files_sharing/lib/sharedstorage.php
@@ -662,4 +662,22 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage {
list($targetStorage, $targetInternalPath) = $this->resolvePath($path);
$targetStorage->changeLock($targetInternalPath, $type, $provider);
}
+
+ /**
+ * @return array [ available, last_checked ]
+ */
+ public function getAvailability() {
+ // shares do not participate in availability logic
+ return [
+ 'available' => true,
+ 'last_checked' => 0
+ ];
+ }
+
+ /**
+ * @param bool $available
+ */
+ public function setAvailability($available) {
+ // shares do not participate in availability logic
+ }
}
diff --git a/apps/files_sharing/tests/controller/externalsharecontroller.php b/apps/files_sharing/tests/controller/externalsharecontroller.php
new file mode 100644
index 00000000000..3dc34bca7a4
--- /dev/null
+++ b/apps/files_sharing/tests/controller/externalsharecontroller.php
@@ -0,0 +1,187 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@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_Sharing\Controllers;
+
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\Http\Client\IClientService;
+use OCP\IRequest;
+
+/**
+ * Class ExternalShareControllerTest
+ *
+ * @package OCA\Files_Sharing\Controllers
+ */
+class ExternalShareControllerTest extends \Test\TestCase {
+ /** @var bool */
+ private $incomingShareEnabled;
+ /** @var IRequest */
+ private $request;
+ /** @var \OCA\Files_Sharing\External\Manager */
+ private $externalManager;
+ /** @var IClientService */
+ private $clientService;
+
+ public function setUp() {
+ $this->request = $this->getMockBuilder('\\OCP\\IRequest')
+ ->disableOriginalConstructor()->getMock();
+ $this->externalManager = $this->getMockBuilder('\\OCA\\Files_Sharing\\External\\Manager')
+ ->disableOriginalConstructor()->getMock();
+ $this->clientService = $this->getMockBuilder('\\OCP\Http\\Client\\IClientService')
+ ->disableOriginalConstructor()->getMock();
+ }
+
+ /**
+ * @return ExternalSharesController
+ */
+ public function getExternalShareController() {
+ return new ExternalSharesController(
+ 'files_sharing',
+ $this->request,
+ $this->incomingShareEnabled,
+ $this->externalManager,
+ $this->clientService
+ );
+ }
+
+ public function testIndexDisabled() {
+ $this->externalManager
+ ->expects($this->never())
+ ->method('getOpenShares');
+
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->index());
+ }
+
+ public function testIndexEnabled() {
+ $this->incomingShareEnabled = true;
+ $this->externalManager
+ ->expects($this->once())
+ ->method('getOpenShares')
+ ->will($this->returnValue(['MyDummyArray']));
+
+ $this->assertEquals(new JSONResponse(['MyDummyArray']), $this->getExternalShareController()->index());
+ }
+
+ public function testCreateDisabled() {
+ $this->externalManager
+ ->expects($this->never())
+ ->method('acceptShare');
+
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create(4));
+ }
+
+ public function testCreateEnabled() {
+ $this->incomingShareEnabled = true;
+ $this->externalManager
+ ->expects($this->once())
+ ->method('acceptShare')
+ ->with(4);
+
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->create(4));
+ }
+
+ public function testDestroyDisabled() {
+ $this->externalManager
+ ->expects($this->never())
+ ->method('destroy');
+
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy(4));
+ }
+
+ public function testDestroyEnabled() {
+ $this->incomingShareEnabled = true;
+ $this->externalManager
+ ->expects($this->once())
+ ->method('declineShare')
+ ->with(4);
+
+ $this->assertEquals(new JSONResponse(), $this->getExternalShareController()->destroy(4));
+ }
+
+ public function testRemoteWithValidHttps() {
+ $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse')
+ ->disableOriginalConstructor()->getMock();
+ $client
+ ->expects($this->once())
+ ->method('get')
+ ->with(
+ 'https://owncloud.org/status.php',
+ [
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ )->will($this->returnValue($response));
+ $response
+ ->expects($this->once())
+ ->method('getBody')
+ ->will($this->returnValue('{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}'));
+
+ $this->clientService
+ ->expects($this->once())
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertEquals(new DataResponse('https'), $this->getExternalShareController()->testRemote('owncloud.org'));
+ }
+
+ public function testRemoteWithWorkingHttp() {
+ $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse')
+ ->disableOriginalConstructor()->getMock();
+ $client
+ ->method('get')
+ ->will($this->onConsecutiveCalls($response, $response));
+ $response
+ ->expects($this->exactly(2))
+ ->method('getBody')
+ ->will($this->onConsecutiveCalls('Certainly not a JSON string', '{"installed":true,"maintenance":false,"version":"8.1.0.8","versionstring":"8.1.0","edition":""}'));
+ $this->clientService
+ ->expects($this->exactly(2))
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertEquals(new DataResponse('http'), $this->getExternalShareController()->testRemote('owncloud.org'));
+ }
+
+ public function testRemoteWithInvalidRemote() {
+ $client = $this->getMockBuilder('\\OCP\\Http\\Client\\IClient')
+ ->disableOriginalConstructor()->getMock();
+ $response = $this->getMockBuilder('\\OCP\\Http\\Client\\IResponse')
+ ->disableOriginalConstructor()->getMock();
+ $client
+ ->method('get')
+ ->will($this->onConsecutiveCalls($response, $response));
+ $response
+ ->expects($this->exactly(2))
+ ->method('getBody')
+ ->will($this->returnValue('Certainly not a JSON string'));
+ $this->clientService
+ ->expects($this->exactly(2))
+ ->method('newClient')
+ ->will($this->returnValue($client));
+
+ $this->assertEquals(new DataResponse(false), $this->getExternalShareController()->testRemote('owncloud.org'));
+ }
+}
diff --git a/apps/user_ldap/ajax/setConfiguration.php b/apps/user_ldap/ajax/setConfiguration.php
index 8e6994d8f94..9311d72d21f 100644
--- a/apps/user_ldap/ajax/setConfiguration.php
+++ b/apps/user_ldap/ajax/setConfiguration.php
@@ -33,7 +33,7 @@ $prefix = (string)$_POST['ldap_serverconfig_chooser'];
// only legacy checkboxes (Advanced and Expert tab) need to be handled here,
// the Wizard-like tabs handle it on their own
$chkboxes = array('ldap_configuration_active', 'ldap_override_main_server',
- 'ldap_nocase', 'ldap_turn_off_cert_check');
+ 'ldap_turn_off_cert_check');
foreach($chkboxes as $boxid) {
if(!isset($_POST[$boxid])) {
$_POST[$boxid] = 0;
diff --git a/apps/user_ldap/appinfo/update.php b/apps/user_ldap/appinfo/update.php
index b904bce072e..4907db0cdae 100644
--- a/apps/user_ldap/appinfo/update.php
+++ b/apps/user_ldap/appinfo/update.php
@@ -24,3 +24,13 @@ $installedVersion = \OC::$server->getConfig()->getAppValue('user_ldap', 'install
if (version_compare($installedVersion, '0.6.1', '<')) {
\OC::$server->getConfig()->setAppValue('user_ldap', 'enforce_home_folder_naming_rule', false);
}
+
+if(version_compare($installedVersion, '0.6.2', '<')) {
+ // Remove LDAP case insensitive setting from DB as it is no longer beeing used.
+ $helper = new \OCA\user_ldap\lib\Helper();
+ $prefixes = $helper->getServerConfigurationPrefixes();
+
+ foreach($prefixes as $prefix) {
+ \OC::$server->getConfig()->deleteAppValue('user_ldap', $prefix . "ldap_nocase");
+ }
+}
diff --git a/apps/user_ldap/appinfo/version b/apps/user_ldap/appinfo/version
index ee6cdce3c29..b6160487433 100644
--- a/apps/user_ldap/appinfo/version
+++ b/apps/user_ldap/appinfo/version
@@ -1 +1 @@
-0.6.1
+0.6.2
diff --git a/apps/user_ldap/js/wizard/wizardTabAdvanced.js b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
index a27ec87b7c4..7367bfe87ae 100644
--- a/apps/user_ldap/js/wizard/wizardTabAdvanced.js
+++ b/apps/user_ldap/js/wizard/wizardTabAdvanced.js
@@ -41,10 +41,6 @@ OCA = OCA || {};
$element: $('#ldap_override_main_server'),
setMethod: 'setOverrideMainServerState'
},
- ldap_nocase: {
- $element: $('#ldap_nocase'),
- setMethod: 'setNoCase'
- },
ldap_turn_off_cert_check: {
$element: $('#ldap_turn_off_cert_check'),
setMethod: 'setCertCheckDisabled'
@@ -166,16 +162,6 @@ OCA = OCA || {};
},
/**
- * whether the server is case insensitive. This setting does not play
- * a role anymore (probably never had).
- *
- * @param {string} noCase contains an int
- */
- setNoCase: function(noCase) {
- this.setElementValue(this.managedItems.ldap_nocase.$element, noCase);
- },
-
- /**
* sets whether the SSL/TLS certification check shout be disabled
*
* @param {string} doCertCheck contains an int
diff --git a/apps/user_ldap/lib/configuration.php b/apps/user_ldap/lib/configuration.php
index 0af819ff66f..1cbe45a82c2 100644
--- a/apps/user_ldap/lib/configuration.php
+++ b/apps/user_ldap/lib/configuration.php
@@ -43,7 +43,6 @@ class Configuration {
'ldapAgentName' => null,
'ldapAgentPassword' => null,
'ldapTLS' => null,
- 'ldapNoCase' => null,
'turnOffCertCheck' => null,
'ldapIgnoreNamingRules' => null,
'ldapUserDisplayName' => null,
@@ -379,7 +378,6 @@ class Configuration {
'ldap_display_name' => 'displayName',
'ldap_group_display_name' => 'cn',
'ldap_tls' => 0,
- 'ldap_nocase' => 0,
'ldap_quota_def' => '',
'ldap_quota_attr' => '',
'ldap_email_attr' => '',
@@ -436,7 +434,6 @@ class Configuration {
'ldap_display_name' => 'ldapUserDisplayName',
'ldap_group_display_name' => 'ldapGroupDisplayName',
'ldap_tls' => 'ldapTLS',
- 'ldap_nocase' => 'ldapNoCase',
'ldap_quota_def' => 'ldapQuotaDefault',
'ldap_quota_attr' => 'ldapQuotaAttribute',
'ldap_email_attr' => 'ldapEmailAttribute',
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index f40eba005d8..88900e22bf7 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -78,7 +78,6 @@ style('user_ldap', 'settings');
<p><label for="ldap_backup_host"><?php p($l->t('Backup (Replica) Host'));?></label><input type="text" id="ldap_backup_host" name="ldap_backup_host" data-default="<?php p($_['ldap_backup_host_default']); ?>" title="<?php p($l->t('Give an optional backup host. It must be a replica of the main LDAP/AD server.'));?>"></p>
<p><label for="ldap_backup_port"><?php p($l->t('Backup (Replica) Port'));?></label><input type="number" id="ldap_backup_port" name="ldap_backup_port" data-default="<?php p($_['ldap_backup_port_default']); ?>" /></p>
<p><label for="ldap_override_main_server"><?php p($l->t('Disable Main Server'));?></label><input type="checkbox" id="ldap_override_main_server" name="ldap_override_main_server" value="1" data-default="<?php p($_['ldap_override_main_server_default']); ?>" title="<?php p($l->t('Only connect to the replica server.'));?>" /></p>
- <p><label for="ldap_nocase"><?php p($l->t('Case insensitive LDAP server (Windows)'));?></label><input type="checkbox" id="ldap_nocase" name="ldap_nocase" data-default="<?php p($_['ldap_nocase_default']); ?>" value="1"<?php if (isset($_['ldap_nocase']) && ($_['ldap_nocase'])) p(' checked'); ?>></p>
<p><label for="ldap_turn_off_cert_check"><?php p($l->t('Turn off SSL certificate validation.'));?></label><input type="checkbox" id="ldap_turn_off_cert_check" name="ldap_turn_off_cert_check" title="<?php p($l->t('Not recommended, use it for testing only! If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', $theme->getName() ));?>" data-default="<?php p($_['ldap_turn_off_cert_check_default']); ?>" value="1"><br/></p>
<p><label for="ldap_cache_ttl"><?php p($l->t('Cache Time-To-Live'));?></label><input type="number" id="ldap_cache_ttl" name="ldap_cache_ttl" title="<?php p($l->t('in seconds. A change empties the cache.'));?>" data-default="<?php p($_['ldap_cache_ttl_default']); ?>" /></p>
</div>
diff --git a/config/config.sample.php b/config/config.sample.php
index 2b4873d5310..234bf8e0fa3 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -20,12 +20,6 @@
* * use RST syntax
*/
-/**
- * Only enable this for local development and not in production environments
- * This will disable the minifier and outputs some additional debug informations
- */
-define('DEBUG', true);
-
$CONFIG = array(
@@ -494,9 +488,10 @@ $CONFIG = array(
'log_type' => 'owncloud',
/**
- * Change the ownCloud logfile name from ``owncloud.log`` to something else.
+ * Log file path for the ownCloud logging type.
+ * Defaults to ``[datadirectory]/owncloud.log``
*/
-'logfile' => 'owncloud.log',
+'logfile' => '/var/log/owncloud.log',
/**
* Loglevel to start logging at. Valid values are: 0 = Debug, 1 = Info, 2 =
@@ -562,8 +557,8 @@ $CONFIG = array(
* Enables log rotation and limits the total size of logfiles. The default is 0,
* or no rotation. Specify a size in bytes, for example 104857600 (100 megabytes
* = 100 * 1024 * 1024 bytes). A new logfile is created with a new name when the
- * old logfile reaches your limit. The total size of all logfiles is double the
- * ``log_rotate_sizerotation`` value.
+ * old logfile reaches your limit. If a rotated log file is already present, it
+ * will be overwritten.
*/
'log_rotate_size' => false,
@@ -1079,6 +1074,14 @@ $CONFIG = array(
'memcache.locking' => '\\OC\\Memcache\\Redis',
/**
+ * Set this ownCloud instance to debugging mode
+ *
+ * Only enable this for local development and not in production environments
+ * This will disable the minifier and outputs some additional debug information
+ */
+'debug' => false,
+
+/**
* This entry is just here to show a warning in case somebody copied the sample
* configuration. DO NOT ADD THIS SWITCH TO YOUR CONFIGURATION!
*
diff --git a/core/application.php b/core/application.php
index 373965e7fd7..12ec6b63fd4 100644
--- a/core/application.php
+++ b/core/application.php
@@ -27,6 +27,7 @@
namespace OC\Core;
use OC\AppFramework\Utility\SimpleContainer;
+use OC\AppFramework\Utility\TimeFactory;
use \OCP\AppFramework\App;
use OC\Core\LostPassword\Controller\LostController;
use OC\Core\User\UserController;
@@ -63,7 +64,8 @@ class Application extends App {
$c->query('SecureRandom'),
$c->query('DefaultEmailAddress'),
$c->query('IsEncryptionEnabled'),
- $c->query('Mailer')
+ $c->query('Mailer'),
+ $c->query('TimeFactory')
);
});
$container->registerService('UserController', function(SimpleContainer $c) {
@@ -120,15 +122,15 @@ class Application extends App {
$container->registerService('UserFolder', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getUserFolder();
});
-
-
-
$container->registerService('Defaults', function() {
return new \OC_Defaults;
});
$container->registerService('Mailer', function(SimpleContainer $c) {
return $c->query('ServerContainer')->getMailer();
});
+ $container->registerService('TimeFactory', function(SimpleContainer $c) {
+ return new TimeFactory();
+ });
$container->registerService('DefaultEmailAddress', function() {
return Util::getDefaultEmailAddress('lostpassword-noreply');
});
diff --git a/core/avatar/avatarcontroller.php b/core/avatar/avatarcontroller.php
index a0c9ebbd785..945e022600a 100644
--- a/core/avatar/avatarcontroller.php
+++ b/core/avatar/avatarcontroller.php
@@ -91,6 +91,7 @@ class AvatarController extends Controller {
/**
* @NoAdminRequired
+ * @NoCSRFRequired
*
* @param string $userId
* @param int $size
diff --git a/core/command/log/manage.php b/core/command/log/manage.php
new file mode 100644
index 00000000000..f3d18cffca0
--- /dev/null
+++ b/core/command/log/manage.php
@@ -0,0 +1,171 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@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\Core\Command\Log;
+
+use \OCP\IConfig;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Manage extends Command {
+
+ const DEFAULT_BACKEND = 'owncloud';
+ const DEFAULT_LOG_LEVEL = 2;
+ const DEFAULT_TIMEZONE = 'UTC';
+
+ /** @var IConfig */
+ protected $config;
+
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('log:manage')
+ ->setDescription('manage logging configuration')
+ ->addOption(
+ 'backend',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'set the logging backend [owncloud, syslog, errorlog]'
+ )
+ ->addOption(
+ 'level',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'set the log level [debug, info, warning, error]'
+ )
+ ->addOption(
+ 'timezone',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'set the logging timezone'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ // collate config setting to the end, to avoid partial configuration
+ $toBeSet = [];
+
+ if ($backend = $input->getOption('backend')) {
+ $this->validateBackend($backend);
+ $toBeSet['log_type'] = $backend;
+ }
+
+ if ($level = $input->getOption('level')) {
+ if (is_numeric($level)) {
+ $levelNum = $level;
+ // sanity check
+ $this->convertLevelNumber($levelNum);
+ } else {
+ $levelNum = $this->convertLevelString($level);
+ }
+ $toBeSet['loglevel'] = $levelNum;
+ }
+
+ if ($timezone = $input->getOption('timezone')) {
+ $this->validateTimezone($timezone);
+ $toBeSet['logtimezone'] = $timezone;
+ }
+
+ // set config
+ foreach ($toBeSet as $option => $value) {
+ $this->config->setSystemValue($option, $value);
+ }
+
+ // display configuration
+ $backend = $this->config->getSystemValue('log_type', self::DEFAULT_BACKEND);
+ $output->writeln('Enabled logging backend: '.$backend);
+
+ $levelNum = $this->config->getSystemValue('loglevel', self::DEFAULT_LOG_LEVEL);
+ $level = $this->convertLevelNumber($levelNum);
+ $output->writeln('Log level: '.$level.' ('.$levelNum.')');
+
+ $timezone = $this->config->getSystemValue('logtimezone', self::DEFAULT_TIMEZONE);
+ $output->writeln('Log timezone: '.$timezone);
+ }
+
+ /**
+ * @param string $backend
+ * @throws \InvalidArgumentException
+ */
+ protected function validateBackend($backend) {
+ if (!class_exists('OC_Log_'.$backend)) {
+ throw new \InvalidArgumentException('Invalid backend');
+ }
+ }
+
+ /**
+ * @param string $timezone
+ * @throws \Exception
+ */
+ protected function validateTimezone($timezone) {
+ new \DateTimeZone($timezone);
+ }
+
+ /**
+ * @param string $level
+ * @return int
+ * @throws \InvalidArgumentException
+ */
+ protected function convertLevelString($level) {
+ $level = strtolower($level);
+ switch ($level) {
+ case 'debug':
+ return 0;
+ case 'info':
+ return 1;
+ case 'warning':
+ case 'warn':
+ return 2;
+ case 'error':
+ case 'err':
+ return 3;
+ }
+ throw new \InvalidArgumentException('Invalid log level string');
+ }
+
+ /**
+ * @param int $levelNum
+ * @return string
+ * @throws \InvalidArgumentException
+ */
+ protected function convertLevelNumber($levelNum) {
+ switch ($levelNum) {
+ case 0:
+ return 'Debug';
+ case 1:
+ return 'Info';
+ case 2:
+ return 'Warning';
+ case 3:
+ return 'Error';
+ }
+ throw new \InvalidArgumentException('Invalid log level number');
+ }
+}
diff --git a/core/command/log/owncloud.php b/core/command/log/owncloud.php
new file mode 100644
index 00000000000..a2d9e4bc7c8
--- /dev/null
+++ b/core/command/log/owncloud.php
@@ -0,0 +1,124 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@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\Core\Command\Log;
+
+use \OCP\IConfig;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class OwnCloud extends Command {
+
+ /** @var IConfig */
+ protected $config;
+
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('log:owncloud')
+ ->setDescription('manipulate ownCloud logging backend')
+ ->addOption(
+ 'enable',
+ null,
+ InputOption::VALUE_NONE,
+ 'enable this logging backend'
+ )
+ ->addOption(
+ 'file',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'set the log file path'
+ )
+ ->addOption(
+ 'rotate-size',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'set the file size for log rotation, 0 = disabled'
+ )
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output) {
+ $toBeSet = [];
+
+ if ($input->getOption('enable')) {
+ $toBeSet['log_type'] = 'owncloud';
+ }
+
+ if ($file = $input->getOption('file')) {
+ $toBeSet['logfile'] = $file;
+ }
+
+ if (($rotateSize = $input->getOption('rotate-size')) !== null) {
+ $rotateSize = \OCP\Util::computerFileSize($rotateSize);
+ $this->validateRotateSize($rotateSize);
+ $toBeSet['log_rotate_size'] = $rotateSize;
+ }
+
+ // set config
+ foreach ($toBeSet as $option => $value) {
+ $this->config->setSystemValue($option, $value);
+ }
+
+ // display config
+ if ($this->config->getSystemValue('log_type', 'owncloud') === 'owncloud') {
+ $enabledText = 'enabled';
+ } else {
+ $enabledText = 'disabled';
+ }
+ $output->writeln('Log backend ownCloud: '.$enabledText);
+
+ $dataDir = $this->config->getSystemValue('datadirectory', \OC::$SERVERROOT.'/data');
+ $defaultLogFile = rtrim($dataDir, '/').'/owncloud.log';
+ $output->writeln('Log file: '.$this->config->getSystemValue('logfile', $defaultLogFile));
+
+ $rotateSize = $this->config->getSystemValue('log_rotate_size', 0);
+ if ($rotateSize) {
+ $rotateString = \OCP\Util::humanFileSize($rotateSize);
+ } else {
+ $rotateString = 'disabled';
+ }
+ $output->writeln('Rotate at: '.$rotateString);
+ }
+
+ /**
+ * @param mixed $rotateSize
+ * @throws \InvalidArgumentException
+ */
+ protected function validateRotateSize(&$rotateSize) {
+ if ($rotateSize === false) {
+ throw new \InvalidArgumentException('Error parsing log rotation file size');
+ }
+ $rotateSize = (int) $rotateSize;
+ if ($rotateSize < 0) {
+ throw new \InvalidArgumentException('Log rotation file size must be non-negative');
+ }
+ }
+
+}
diff --git a/core/css/apps.css b/core/css/apps.css
index 300b186bba2..b3d7eaf6599 100644
--- a/core/css/apps.css
+++ b/core/css/apps.css
@@ -440,8 +440,10 @@
left: auto;
bottom: 0;
width: 27%;
+ min-width: 250px;
display: block;
- background: #eee;
+ background: #fff;
+ border-left: 1px solid #eee;
-webkit-transition: margin-right 300ms;
-moz-transition: margin-right 300ms;
-o-transition: margin-right 300ms;
@@ -600,47 +602,31 @@ em {
/* generic tab styles */
.tabHeaders {
margin: 15px;
- background-color: #1D2D44;
}
-
.tabHeaders .tabHeader {
float: left;
- border: 1px solid #ddd;
padding: 5px;
cursor: pointer;
- background-color: #f8f8f8;
- font-weight: bold;
}
.tabHeaders .tabHeader, .tabHeaders .tabHeader a {
color: #888;
}
-
-.tabHeaders .tabHeader:first-child {
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-
-.tabHeaders .tabHeader:last-child {
- border-top-right-radius: 4px;
- border-bottom-right-radius: 4px;
+.tabHeaders .tabHeader.selected {
+ font-weight: 600;
}
-
.tabHeaders .tabHeader.selected,
.tabHeaders .tabHeader:hover {
- background-color: #e8e8e8;
+ border-bottom: 1px solid #333;
}
-
.tabHeaders .tabHeader.selected,
.tabHeaders .tabHeader.selected a,
.tabHeaders .tabHeader:hover,
.tabHeaders .tabHeader:hover a {
color: #000;
}
-
.tabsContainer {
clear: left;
}
-
.tabsContainer .tab {
padding: 15px;
}
diff --git a/core/css/mobile.css b/core/css/mobile.css
index 2256d821d73..9008e39b89c 100644
--- a/core/css/mobile.css
+++ b/core/css/mobile.css
@@ -31,7 +31,6 @@
width: 0;
cursor: pointer;
background-color: transparent;
- background-image: url('../img/actions/search-white.svg');
-webkit-transition: all 100ms;
-moz-transition: all 100ms;
-o-transition: all 100ms;
@@ -44,8 +43,7 @@
width: 155px;
max-width: 50%;
cursor: text;
- background-color: #fff;
- background-image: url('../img/actions/search.svg');
+ background-color: #112;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
opacity: 1;
}
diff --git a/core/css/styles.css b/core/css/styles.css
index db81f850303..619a9df7433 100644
--- a/core/css/styles.css
+++ b/core/css/styles.css
@@ -258,7 +258,8 @@ input:disabled+label, input:disabled:hover+label, input:disabled:focus+label {
font-size: 1.2em;
padding: 3px;
padding-left: 25px;
- background: #fff url('../img/actions/search.svg') no-repeat 6px center;
+ background: #112 url('../img/actions/search-white.svg') no-repeat 6px center;
+ color: #fff;
border: 0;
border-radius: 3px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
@@ -271,6 +272,7 @@ input:disabled+label, input:disabled:hover+label, input:disabled:focus+label {
.searchbox input[type="search"]:active {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
opacity: .7;
+ color: #fff;
}
input[type="submit"].enabled {
@@ -680,6 +682,13 @@ label.infield {
color: #ccc;
}
+#body-login .update .appList {
+ list-style: disc;
+ text-align: left;
+ margin-left: 25px;
+ margin-right: 25px;
+}
+
#body-login .v-align {
width: inherit;
}
diff --git a/core/js/config.php b/core/js/config.php
index cecbf27e4b2..5da610698df 100644
--- a/core/js/config.php
+++ b/core/js/config.php
@@ -62,7 +62,7 @@ if ($defaultExpireDateEnabled) {
$outgoingServer2serverShareEnabled = $config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes') === 'yes';
$array = array(
- "oc_debug" => (defined('DEBUG') && DEBUG) ? 'true' : 'false',
+ "oc_debug" => $config->getSystemValue('debug', false) ? 'true' : 'false',
"oc_isadmin" => OC_User::isAdminUser(OC_User::getUser()) ? 'true' : 'false',
"oc_webroot" => "\"".OC::$WEBROOT."\"",
"oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
@@ -78,6 +78,28 @@ $array = array(
(string)$l->t('Saturday')
)
),
+ "dayNamesShort" => json_encode(
+ array(
+ (string)$l->t('Sun.'),
+ (string)$l->t('Mon.'),
+ (string)$l->t('Tue.'),
+ (string)$l->t('Wed.'),
+ (string)$l->t('Thu.'),
+ (string)$l->t('Fri.'),
+ (string)$l->t('Sat.')
+ )
+ ),
+ "dayNamesMin" => json_encode(
+ array(
+ (string)$l->t('Su'),
+ (string)$l->t('Mo'),
+ (string)$l->t('Tu'),
+ (string)$l->t('We'),
+ (string)$l->t('Th'),
+ (string)$l->t('Fr'),
+ (string)$l->t('Sa')
+ )
+ ),
"monthNames" => json_encode(
array(
(string)$l->t('January'),
@@ -94,6 +116,22 @@ $array = array(
(string)$l->t('December')
)
),
+ "monthNamesShort" => json_encode(
+ array(
+ (string)$l->t('Jan.'),
+ (string)$l->t('Feb.'),
+ (string)$l->t('Mar.'),
+ (string)$l->t('Apr.'),
+ (string)$l->t('May.'),
+ (string)$l->t('Jun.'),
+ (string)$l->t('Jul.'),
+ (string)$l->t('Aug.'),
+ (string)$l->t('Sep.'),
+ (string)$l->t('Oct.'),
+ (string)$l->t('Nov.'),
+ (string)$l->t('Dec.')
+ )
+ ),
"firstDay" => json_encode($l->getFirstWeekDay()) ,
"oc_config" => json_encode(
array(
diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js
index 74acaac7927..b0d1ca7d88f 100644
--- a/core/js/jquery.avatar.js
+++ b/core/js/jquery.avatar.js
@@ -76,8 +76,8 @@
var $div = this;
var url = OC.generateUrl(
- '/avatar/{user}/{size}?requesttoken={requesttoken}',
- {user: user, size: size * window.devicePixelRatio, requesttoken: oc_requesttoken});
+ '/avatar/{user}/{size}',
+ {user: user, size: size * window.devicePixelRatio});
$.get(url, function(result) {
if (typeof(result) === 'object') {
diff --git a/core/js/share.js b/core/js/share.js
index 57dd0dd6553..bf9250b3c3a 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -905,10 +905,10 @@ $(document).ready(function() {
minDate.setDate(minDate.getDate()+1);
$.datepicker.setDefaults({
monthNames: monthNames,
- monthNamesShort: $.map(monthNames, function(v) { return v.slice(0,3)+'.'; }),
+ monthNamesShort: monthNamesShort,
dayNames: dayNames,
- dayNamesMin: $.map(dayNames, function(v) { return v.slice(0,2); }),
- dayNamesShort: $.map(dayNames, function(v) { return v.slice(0,3)+'.'; }),
+ dayNamesMin: dayNamesMin,
+ dayNamesShort: dayNamesShort,
firstDay: firstDay,
minDate : minDate
});
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index dbe005ba2e9..cd387d76ce8 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -35,6 +35,24 @@ window.dayNames = [
'Friday',
'Saturday'
];
+window.dayNamesShort = [
+ 'Sun.',
+ 'Mon.',
+ 'Tue.',
+ 'Wed.',
+ 'Thu.',
+ 'Fri.',
+ 'Sat.'
+];
+window.dayNamesMin = [
+ 'Su',
+ 'Mo',
+ 'Tu',
+ 'We',
+ 'Th',
+ 'Fr',
+ 'Sa'
+];
window.monthNames = [
'January',
'February',
@@ -49,6 +67,20 @@ window.monthNames = [
'November',
'December'
];
+window.monthNamesShort = [
+ 'Jan.',
+ 'Feb.',
+ 'Mar.',
+ 'Apr.',
+ 'May.',
+ 'Jun.',
+ 'Jul.',
+ 'Aug.',
+ 'Sep.',
+ 'Oct.',
+ 'Nov.',
+ 'Dec.'
+];
window.firstDay = 0;
// setup dummy webroots
diff --git a/core/lostpassword/controller/lostcontroller.php b/core/lostpassword/controller/lostcontroller.php
index 4c5e58c7b60..7d983bd7e30 100644
--- a/core/lostpassword/controller/lostcontroller.php
+++ b/core/lostpassword/controller/lostcontroller.php
@@ -28,6 +28,7 @@ namespace OC\Core\LostPassword\Controller;
use \OCP\AppFramework\Controller;
use \OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Utility\ITimeFactory;
use \OCP\IURLGenerator;
use \OCP\IRequest;
use \OCP\IL10N;
@@ -66,6 +67,8 @@ class LostController extends Controller {
protected $secureRandom;
/** @var IMailer */
protected $mailer;
+ /** @var ITimeFactory */
+ protected $timeFactory;
/**
* @param string $appName
@@ -79,6 +82,7 @@ class LostController extends Controller {
* @param string $from
* @param string $isDataEncrypted
* @param IMailer $mailer
+ * @param ITimeFactory $timeFactory
*/
public function __construct($appName,
IRequest $request,
@@ -90,7 +94,8 @@ class LostController extends Controller {
ISecureRandom $secureRandom,
$from,
$isDataEncrypted,
- IMailer $mailer) {
+ IMailer $mailer,
+ ITimeFactory $timeFactory) {
parent::__construct($appName, $request);
$this->urlGenerator = $urlGenerator;
$this->userManager = $userManager;
@@ -101,6 +106,7 @@ class LostController extends Controller {
$this->isDataEncrypted = $isDataEncrypted;
$this->config = $config;
$this->mailer = $mailer;
+ $this->timeFactory = $timeFactory;
}
/**
@@ -173,7 +179,17 @@ class LostController extends Controller {
try {
$user = $this->userManager->get($userId);
- if (!StringUtils::equals($this->config->getUserValue($userId, 'owncloud', 'lostpassword', null), $token)) {
+ $splittedToken = explode(':', $this->config->getUserValue($userId, 'owncloud', 'lostpassword', null));
+ if(count($splittedToken) !== 2) {
+ throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
+ }
+
+ if ($splittedToken[0] < ($this->timeFactory->getTime() - 60*60*12) ||
+ $user->getLastLogin() > $splittedToken[0]) {
+ throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is expired'));
+ }
+
+ if (!StringUtils::equals($splittedToken[1], $token)) {
throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
}
@@ -216,12 +232,12 @@ class LostController extends Controller {
ISecureRandom::CHAR_DIGITS.
ISecureRandom::CHAR_LOWER.
ISecureRandom::CHAR_UPPER);
- $this->config->setUserValue($user, 'owncloud', 'lostpassword', $token);
+ $this->config->setUserValue($user, 'owncloud', 'lostpassword', $this->timeFactory->getTime() .':'. $token);
$link = $this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', array('userId' => $user, 'token' => $token));
$tmpl = new \OC_Template('core/lostpassword', 'email');
- $tmpl->assign('link', $link, false);
+ $tmpl->assign('link', $link);
$msg = $tmpl->fetchPage();
try {
diff --git a/core/register_command.php b/core/register_command.php
index 6cd81b4c3b7..9c13c0967f8 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -58,6 +58,9 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$application->add(new OC\Core\Command\Encryption\SetDefaultModule(\OC::$server->getEncryptionManager()));
$application->add(new OC\Core\Command\Encryption\Status(\OC::$server->getEncryptionManager()));
+ $application->add(new OC\Core\Command\Log\Manage(\OC::$server->getConfig()));
+ $application->add(new OC\Core\Command\Log\OwnCloud(\OC::$server->getConfig()));
+
$application->add(new OC\Core\Command\Maintenance\MimeTypesJS());
$application->add(new OC\Core\Command\Maintenance\Mode(\OC::$server->getConfig()));
$application->add(new OC\Core\Command\Maintenance\Repair(new \OC\Repair(\OC\Repair::getRepairSteps()), \OC::$server->getConfig()));
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index 2f93a30ba6a..59fced353d1 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -100,7 +100,7 @@
<?php p($l->t('Search'));?>
</label>
<input id="searchbox" class="svg" type="search" name="query"
- value="<?php if(isset($_POST['query'])) {p($_POST['query']);};?>"
+ value=""
autocomplete="off" tabindex="5">
</form>
</div></header>
diff --git a/core/templates/update.admin.php b/core/templates/update.admin.php
index ccd5d236828..fbd3025f2e0 100644
--- a/core/templates/update.admin.php
+++ b/core/templates/update.admin.php
@@ -1,12 +1,26 @@
<div class="update" data-productname="<?php p($_['productName']) ?>" data-version="<?php p($_['version']) ?>">
<div class="updateOverview">
- <h2 class="title bold"><?php p($l->t('%s will be updated to version %s.',
+ <?php if ($_['isAppsOnlyUpgrade']) { ?>
+ <h2 class="title bold"><?php p($l->t('App update required')); ?></h2>
+ <?php } else { ?>
+ <h2 class="title bold"><?php p($l->t('%s will be updated to version %s',
array($_['productName'], $_['version']))); ?></h2>
- <?php if (!empty($_['appList'])) { ?>
+ <?php } ?>
+ <?php if (!empty($_['appsToUpgrade'])) { ?>
+ <div class="infogroup">
+ <span class="bold"><?php p($l->t('These apps will be updated:')); ?></span>
+ <ul class="content appList">
+ <?php foreach ($_['appsToUpgrade'] as $appInfo) { ?>
+ <li><?php p($appInfo['name']) ?> (<?php p($appInfo['id']) ?>)</li>
+ <?php } ?>
+ </ul>
+ </div>
+ <?php } ?>
+ <?php if (!empty($_['incompatibleAppsList'])) { ?>
<div class="infogroup">
- <span class="bold"><?php p($l->t('The following apps will be disabled:')) ?></span>
+ <span class="bold"><?php p($l->t('These incompatible apps will be disabled:')) ?></span>
<ul class="content appList">
- <?php foreach ($_['appList'] as $appInfo) { ?>
+ <?php foreach ($_['incompatibleAppsList'] as $appInfo) { ?>
<li><?php p($appInfo['name']) ?> (<?php p($appInfo['id']) ?>)</li>
<?php } ?>
</ul>
diff --git a/cron.php b/cron.php
index 987c7dbca7f..ed2a20a1e1f 100644
--- a/cron.php
+++ b/cron.php
@@ -52,7 +52,10 @@ try {
\OC::$server->getSession()->close();
// initialize a dummy memory session
- \OC::$server->setSession(new \OC\Session\Memory(''));
+ $session = new \OC\Session\Memory('');
+ $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
+ $session = $cryptoWrapper->wrapSession($session);
+ \OC::$server->setSession($session);
$logger = \OC::$server->getLogger();
diff --git a/lib/base.php b/lib/base.php
index c0f3e50142e..aceac2e53c3 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -134,18 +134,7 @@ class OC {
OC_Config::$object = new \OC\Config(self::$configDir);
OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
- /**
- * FIXME: The following line is required because of a cyclic dependency
- * on IRequest.
- */
- $params = [
- 'server' => [
- 'SCRIPT_NAME' => $_SERVER['SCRIPT_NAME'],
- 'SCRIPT_FILENAME' => $_SERVER['SCRIPT_FILENAME'],
- ],
- ];
- $fakeRequest = new \OC\AppFramework\Http\Request($params, null, new \OC\AllConfig(new \OC\SystemConfig()));
- $scriptName = $fakeRequest->getScriptName();
+ $scriptName = $_SERVER['SCRIPT_NAME'];
if (substr($scriptName, -1) == '/') {
$scriptName .= 'index.php';
//make sure suburi follows the same rules as scriptName
@@ -346,27 +335,7 @@ class OC {
if (\OCP\Util::needUpgrade()) {
$systemConfig = \OC::$server->getSystemConfig();
if ($showTemplate && !$systemConfig->getValue('maintenance', false)) {
- $version = OC_Util::getVersion();
- $oldTheme = $systemConfig->getValue('theme');
- $systemConfig->setValue('theme', '');
- OC_Util::addScript('config'); // needed for web root
- OC_Util::addScript('update');
- $tmpl = new OC_Template('', 'update.admin', 'guest');
- $tmpl->assign('version', OC_Util::getVersionString());
-
- // get third party apps
- $apps = OC_App::getEnabledApps();
- $incompatibleApps = array();
- foreach ($apps as $appId) {
- $info = OC_App::getAppInfo($appId);
- if(!OC_App::isAppCompatible($version, $info)) {
- $incompatibleApps[] = $info;
- }
- }
- $tmpl->assign('appList', $incompatibleApps);
- $tmpl->assign('productName', 'ownCloud'); // for now
- $tmpl->assign('oldTheme', $oldTheme);
- $tmpl->printPage();
+ self::printUpgradePage();
exit();
} else {
return true;
@@ -375,6 +344,41 @@ class OC {
return false;
}
+ /**
+ * Prints the upgrade page
+ */
+ private static function printUpgradePage() {
+ $systemConfig = \OC::$server->getSystemConfig();
+ $oldTheme = $systemConfig->getValue('theme');
+ $systemConfig->setValue('theme', '');
+ \OCP\Util::addScript('config'); // needed for web root
+ \OCP\Util::addScript('update');
+
+ // check whether this is a core update or apps update
+ $installedVersion = $systemConfig->getValue('version', '0.0.0');
+ $currentVersion = implode('.', OC_Util::getVersion());
+
+ $appManager = \OC::$server->getAppManager();
+
+ $tmpl = new OC_Template('', 'update.admin', 'guest');
+ $tmpl->assign('version', OC_Util::getVersionString());
+
+ // if not a core upgrade, then it's apps upgrade
+ if (version_compare($currentVersion, $installedVersion, '=')) {
+ $tmpl->assign('isAppsOnlyUpgrade', true);
+ } else {
+ $tmpl->assign('isAppsOnlyUpgrade', false);
+ }
+
+ // get third party apps
+ $ocVersion = OC_Util::getVersion();
+ $tmpl->assign('appsToUpgrade', $appManager->getAppsNeedingUpgrade($ocVersion));
+ $tmpl->assign('incompatibleAppsList', $appManager->getIncompatibleApps($ocVersion));
+ $tmpl->assign('productName', 'ownCloud'); // for now
+ $tmpl->assign('oldTheme', $oldTheme);
+ $tmpl->printPage();
+ }
+
public static function initTemplateEngine() {
// Add the stuff we need always
// following logic will import all vendor libraries that are
@@ -448,13 +452,15 @@ class OC {
$useCustomSession = false;
$session = self::$server->getSession();
OC_Hook::emit('OC', 'initSession', array('session' => &$session, 'sessionName' => &$sessionName, 'useCustomSession' => &$useCustomSession));
- if($useCustomSession) {
- // use the session reference as the new Session
- self::$server->setSession($session);
- } else {
+ if (!$useCustomSession) {
// set the session name to the instance id - which is unique
- self::$server->setSession(new \OC\Session\Internal($sessionName));
+ $session = new \OC\Session\Internal($sessionName);
}
+
+ $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
+ $session = $cryptoWrapper->wrapSession($session);
+ self::$server->setSession($session);
+
// if session cant be started break with http 500 error
} catch (Exception $e) {
\OCP\Util::logException('base', $e);
@@ -576,7 +582,7 @@ class OC {
if (!defined('PHPUNIT_RUN')) {
$logger = \OC::$server->getLogger();
OC\Log\ErrorHandler::setLogger($logger);
- if (defined('DEBUG') and DEBUG) {
+ if (\OC::$server->getConfig()->getSystemValue('debug', false)) {
OC\Log\ErrorHandler::register(true);
set_exception_handler(array('OC_Template', 'printExceptionErrorPage'));
} else {
@@ -1034,7 +1040,7 @@ class OC {
return false;
}
- if (defined("DEBUG") && DEBUG) {
+ if (\OC::$server->getConfig()->getSystemValue('debug', false)) {
\OCP\Util::writeLog('core', 'Trying to login from cookie', \OCP\Util::DEBUG);
}
@@ -1087,11 +1093,12 @@ class OC {
self::cleanupLoginTokens($userId);
if (!empty($_POST["remember_login"])) {
- if (defined("DEBUG") && DEBUG) {
+ $config = self::$server->getConfig();
+ if ($config->getSystemValue('debug', false)) {
self::$server->getLogger()->debug('Setting remember login to cookie', array('app' => 'core'));
}
$token = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(32);
- self::$server->getConfig()->setUserValue($userId, 'login_token', $token, time());
+ $config->setUserValue($userId, 'login_token', $token, time());
OC_User::setMagicInCookie($userId, $token);
} else {
OC_User::unsetMagicInCookie();
diff --git a/lib/private/activity/event.php b/lib/private/activity/event.php
new file mode 100644
index 00000000000..fe6fc485b7b
--- /dev/null
+++ b/lib/private/activity/event.php
@@ -0,0 +1,250 @@
+<?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\Activity;
+
+use OCP\Activity\IEvent;
+
+class Event implements IEvent {
+ /** @var array */
+ protected $data = [
+ 'app' => null,
+ 'type' => null,
+ 'affected_user' => null,
+ 'author' => null,
+ 'timestamp' => null,
+ 'subject' => null,
+ 'subject_parameters' => null,
+ 'message' => '',
+ 'message_parameters' => [],
+ 'object_type' => '',
+ 'object_id' => 0,
+ 'object_name' => '',
+ 'link' => '',
+ ];
+
+ /**
+ * Set the app of the activity
+ *
+ * @param string $app
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setApp($app) {
+ $this->data['app'] = (string) $app;
+ return $this;
+ }
+
+ /**
+ * Set the type of the activity
+ *
+ * @param string $type
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setType($type) {
+ $this->data['type'] = (string) $type;
+ return $this;
+ }
+
+ /**
+ * Set the affected user of the activity
+ *
+ * @param string $affectedUser
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setAffectedUser($affectedUser) {
+ $this->data['affected_user'] = (string) $affectedUser;
+ return $this;
+ }
+
+ /**
+ * Set the author of the activity
+ *
+ * @param string $author
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setAuthor($author) {
+ $this->data['author'] = (string) $author;
+ return $this;
+ }
+
+ /**
+ * Set the author of the activity
+ *
+ * @param int $timestamp
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setTimestamp($timestamp) {
+ $this->data['timestamp'] = (int) $timestamp;
+ return $this;
+ }
+
+ /**
+ * Set the subject of the activity
+ *
+ * @param string $subject
+ * @param array $parameters
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setSubject($subject, array $parameters = []) {
+ $this->data['subject'] = (string) $subject;
+ $this->data['subject_parameters'] = $parameters;
+ return $this;
+ }
+
+ /**
+ * Set the message of the activity
+ *
+ * @param string $message
+ * @param array $parameters
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setMessage($message, array $parameters = []) {
+ $this->data['message'] = (string) $message;
+ $this->data['message_parameters'] = $parameters;
+ return $this;
+ }
+
+ /**
+ * Set the object of the activity
+ *
+ * @param string $objectType
+ * @param int $objectId
+ * @param string $objectName
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setObject($objectType, $objectId, $objectName = '') {
+ $this->data['object_type'] = (string) $objectType;
+ $this->data['object_id'] = (int) $objectId;
+ $this->data['object_name'] = (string) $objectName;
+ return $this;
+ }
+
+ /**
+ * Set the link of the activity
+ *
+ * @param string $link
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setLink($link) {
+ $this->data['link'] = (string) $link;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getApp() {
+ return $this->data['app'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getType() {
+ return $this->data['type'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getAffectedUser() {
+ return $this->data['affected_user'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getAuthor() {
+ return $this->data['author'];
+ }
+
+ /**
+ * @return int
+ */
+ public function getTimestamp() {
+ return $this->data['timestamp'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getSubject() {
+ return $this->data['subject'];
+ }
+
+ /**
+ * @return array
+ */
+ public function getSubjectParameters() {
+ return $this->data['subject_parameters'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getMessage() {
+ return $this->data['message'];
+ }
+
+ /**
+ * @return array
+ */
+ public function getMessageParameters() {
+ return $this->data['message_parameters'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getObjectType() {
+ return $this->data['object_type'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getObjectId() {
+ return $this->data['object_id'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getObjectName() {
+ return $this->data['object_name'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getLink() {
+ return $this->data['link'];
+ }
+}
diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php
index 938335a87e1..a973db7206f 100644
--- a/lib/private/activitymanager.php
+++ b/lib/private/activitymanager.php
@@ -24,11 +24,14 @@
namespace OC;
+use OC\Activity\Event;
use OCP\Activity\IConsumer;
+use OCP\Activity\IEvent;
use OCP\Activity\IExtension;
use OCP\Activity\IManager;
use OCP\IConfig;
use OCP\IRequest;
+use OCP\IUser;
use OCP\IUserSession;
class ActivityManager implements IManager {
@@ -124,36 +127,87 @@ class ActivityManager implements IManager {
}
/**
- * @param $app
- * @param $subject
- * @param $subjectParams
- * @param $message
- * @param $messageParams
- * @param $file
- * @param $link
- * @param $affectedUser
- * @param $type
- * @param $priority
- * @return mixed
+ * Generates a new IEvent object
+ *
+ * Make sure to call at least the following methods before sending it to the
+ * app with via the publish() method:
+ * - setApp()
+ * - setType()
+ * - setAffectedUser()
+ * - setSubject()
+ *
+ * @return IEvent
*/
- function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority) {
- foreach($this->getConsumers() as $c) {
- try {
- $c->receive(
- $app,
- $subject,
- $subjectParams,
- $message,
- $messageParams,
- $file,
- $link,
- $affectedUser,
- $type,
- $priority);
- } catch (\Exception $ex) {
- // TODO: log the exception
+ public function generateEvent() {
+ return new Event();
+ }
+
+ /**
+ * Publish an event to the activity consumers
+ *
+ * Make sure to call at least the following methods before sending an Event:
+ * - setApp()
+ * - setType()
+ * - setAffectedUser()
+ * - setSubject()
+ *
+ * @param IEvent $event
+ * @return null
+ * @throws \BadMethodCallException if required values have not been set
+ */
+ public function publish(IEvent $event) {
+ if (!$event->getApp()) {
+ throw new \BadMethodCallException('App not set', 10);
+ }
+ if (!$event->getType()) {
+ throw new \BadMethodCallException('Type not set', 11);
+ }
+ if ($event->getAffectedUser() === null) {
+ throw new \BadMethodCallException('Affected user not set', 12);
+ }
+ if ($event->getSubject() === null || $event->getSubjectParameters() === null) {
+ throw new \BadMethodCallException('Subject not set', 13);
+ }
+
+ if ($event->getAuthor() === null) {
+ if ($this->session->getUser() instanceof IUser) {
+ $event->setAuthor($this->session->getUser()->getUID());
}
}
+
+ if (!$event->getTimestamp()) {
+ $event->setTimestamp(time());
+ }
+
+ foreach ($this->getConsumers() as $c) {
+ $c->receive($event);
+ }
+ }
+
+ /**
+ * @param string $app The app where this event is associated with
+ * @param string $subject A short description of the event
+ * @param array $subjectParams Array with parameters that are filled in the subject
+ * @param string $message A longer description of the event
+ * @param array $messageParams Array with parameters that are filled in the message
+ * @param string $file The file including path where this event is associated with
+ * @param string $link A link where this event is associated with
+ * @param string $affectedUser Recipient of the activity
+ * @param string $type Type of the notification
+ * @param int $priority Priority of the notification
+ * @return null
+ */
+ public function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority) {
+ $event = $this->generateEvent();
+ $event->setApp($app)
+ ->setType($type)
+ ->setAffectedUser($affectedUser)
+ ->setSubject($subject, $subjectParams)
+ ->setMessage($message, $messageParams)
+ ->setObject('', 0, $file)
+ ->setLink($link);
+
+ $this->publish($event);
}
/**
@@ -164,7 +218,7 @@ class ActivityManager implements IManager {
*
* @param \Closure $callable
*/
- function registerConsumer(\Closure $callable) {
+ public function registerConsumer(\Closure $callable) {
array_push($this->consumersClosures, $callable);
$this->consumers = [];
}
@@ -178,7 +232,7 @@ class ActivityManager implements IManager {
* @param \Closure $callable
* @return void
*/
- function registerExtension(\Closure $callable) {
+ public function registerExtension(\Closure $callable) {
array_push($this->extensionsClosures, $callable);
$this->extensions = [];
}
@@ -189,7 +243,7 @@ class ActivityManager implements IManager {
* @param string $languageCode
* @return array
*/
- function getNotificationTypes($languageCode) {
+ public function getNotificationTypes($languageCode) {
$notificationTypes = array();
foreach ($this->getExtensions() as $c) {
$result = $c->getNotificationTypes($languageCode);
@@ -205,7 +259,7 @@ class ActivityManager implements IManager {
* @param string $method
* @return array
*/
- function getDefaultTypes($method) {
+ public function getDefaultTypes($method) {
$defaultTypes = array();
foreach ($this->getExtensions() as $c) {
$types = $c->getDefaultTypes($method);
@@ -220,7 +274,7 @@ class ActivityManager implements IManager {
* @param string $type
* @return string
*/
- function getTypeIcon($type) {
+ public function getTypeIcon($type) {
if (isset($this->typeIcons[$type])) {
return $this->typeIcons[$type];
}
@@ -246,7 +300,7 @@ class ActivityManager implements IManager {
* @param string $languageCode
* @return string|false
*/
- function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
+ public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode) {
foreach ($this->getExtensions() as $c) {
$translation = $c->translate($app, $text, $params, $stripPath, $highlightParams, $languageCode);
if (is_string($translation)) {
@@ -262,7 +316,7 @@ class ActivityManager implements IManager {
* @param string $text
* @return array|false
*/
- function getSpecialParameterList($app, $text) {
+ public function getSpecialParameterList($app, $text) {
if (isset($this->specialParameters[$app][$text])) {
return $this->specialParameters[$app][$text];
}
@@ -287,7 +341,7 @@ class ActivityManager implements IManager {
* @param array $activity
* @return integer|false
*/
- function getGroupParameter($activity) {
+ public function getGroupParameter($activity) {
foreach ($this->getExtensions() as $c) {
$parameter = $c->getGroupParameter($activity);
if ($parameter !== false) {
@@ -301,7 +355,7 @@ class ActivityManager implements IManager {
/**
* @return array
*/
- function getNavigation() {
+ public function getNavigation() {
$entries = array(
'apps' => array(),
'top' => array(),
@@ -321,7 +375,7 @@ class ActivityManager implements IManager {
* @param string $filterValue
* @return boolean
*/
- function isFilterValid($filterValue) {
+ public function isFilterValid($filterValue) {
if (isset($this->validFilters[$filterValue])) {
return $this->validFilters[$filterValue];
}
@@ -342,7 +396,7 @@ class ActivityManager implements IManager {
* @param string $filter
* @return array
*/
- function filterNotificationTypes($types, $filter) {
+ public function filterNotificationTypes($types, $filter) {
if (!$this->isFilterValid($filter)) {
return $types;
}
@@ -360,7 +414,7 @@ class ActivityManager implements IManager {
* @param string $filter
* @return array
*/
- function getQueryForFilter($filter) {
+ public function getQueryForFilter($filter) {
if (!$this->isFilterValid($filter)) {
return [null, null];
}
diff --git a/lib/private/app.php b/lib/private/app.php
index 9de1c66ee55..f1a1d27ae66 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -1139,7 +1139,7 @@ class OC_App {
// check for required dependencies
$dependencyAnalyzer = new DependencyAnalyzer(new Platform($config), $l);
- $missing = $dependencyAnalyzer->analyze($app);
+ $missing = $dependencyAnalyzer->analyze($info);
if (!empty($missing)) {
$missingMsg = join(PHP_EOL, $missing);
throw new \Exception(
diff --git a/lib/private/app/appmanager.php b/lib/private/app/appmanager.php
index 7a61cd53c59..75b1c0a7865 100644
--- a/lib/private/app/appmanager.php
+++ b/lib/private/app/appmanager.php
@@ -209,4 +209,73 @@ class AppManager implements IAppManager {
$settingsMemCache = $this->memCacheFactory->create('settings');
$settingsMemCache->clear('listApps');
}
+
+ /**
+ * Returns a list of apps that need upgrade
+ *
+ * @param array $version ownCloud version as array of version components
+ * @return array list of app info from apps that need an upgrade
+ *
+ * @internal
+ */
+ public function getAppsNeedingUpgrade($ocVersion) {
+ $appsToUpgrade = [];
+ $apps = $this->getInstalledApps();
+ foreach ($apps as $appId) {
+ $appInfo = $this->getAppInfo($appId);
+ $appDbVersion = $this->appConfig->getValue($appId, 'installed_version');
+ if ($appDbVersion
+ && isset($appInfo['version'])
+ && version_compare($appInfo['version'], $appDbVersion, '>')
+ && \OC_App::isAppCompatible($ocVersion, $appInfo)
+ ) {
+ $appsToUpgrade[] = $appInfo;
+ }
+ }
+
+ return $appsToUpgrade;
+ }
+
+ /**
+ * Returns the app information from "appinfo/info.xml".
+ *
+ * If no version was present in "appinfo/info.xml", reads it
+ * from the external "appinfo/version" file instead.
+ *
+ * @param string $appId app id
+ *
+ * @return array app iinfo
+ *
+ * @internal
+ */
+ public function getAppInfo($appId) {
+ $appInfo = \OC_App::getAppInfo($appId);
+ if (!isset($appInfo['version'])) {
+ // read version from separate file
+ $appInfo['version'] = \OC_App::getAppVersion($appId);
+ }
+ return $appInfo;
+ }
+
+ /**
+ * Returns a list of apps incompatible with the given version
+ *
+ * @param array $version ownCloud version as array of version components
+ *
+ * @return array list of app info from incompatible apps
+ *
+ * @internal
+ */
+ public function getIncompatibleApps($version) {
+ $apps = $this->getInstalledApps();
+ $incompatibleApps = array();
+ foreach ($apps as $appId) {
+ $info = $this->getAppInfo($appId);
+ if (!\OC_App::isAppCompatible($version, $info)) {
+ $incompatibleApps[] = $info;
+ }
+ }
+ return $incompatibleApps;
+ }
+
}
diff --git a/lib/private/appframework/http/request.php b/lib/private/appframework/http/request.php
index aaad286e843..a2109439177 100644
--- a/lib/private/appframework/http/request.php
+++ b/lib/private/appframework/http/request.php
@@ -32,6 +32,7 @@ namespace OC\AppFramework\Http;
use OC\Security\TrustedDomainHelper;
use OCP\IConfig;
use OCP\IRequest;
+use OCP\Security\ICrypto;
use OCP\Security\ISecureRandom;
/**
@@ -67,6 +68,8 @@ class Request implements \ArrayAccess, \Countable, IRequest {
protected $config;
/** @var string */
protected $requestId = '';
+ /** @var ICrypto */
+ protected $crypto;
/**
* @param array $vars An associative array with the following optional values:
@@ -80,17 +83,20 @@ class Request implements \ArrayAccess, \Countable, IRequest {
* - string 'method' the request method (GET, POST etc)
* - string|false 'requesttoken' the requesttoken or false when not available
* @param ISecureRandom $secureRandom
+ * @param ICrypto $crypto
* @param IConfig $config
* @param string $stream
* @see http://www.php.net/manual/en/reserved.variables.php
*/
public function __construct(array $vars=array(),
ISecureRandom $secureRandom = null,
+ ICrypto $crypto,
IConfig $config,
$stream='php://input') {
$this->inputStream = $stream;
$this->items['params'] = array();
$this->secureRandom = $secureRandom;
+ $this->crypto = $crypto;
$this->config = $config;
if(!array_key_exists('method', $vars)) {
@@ -415,8 +421,22 @@ class Request implements \ArrayAccess, \Countable, IRequest {
return false;
}
+ // Decrypt token to prevent BREACH like attacks
+ $token = explode(':', $token);
+ if (count($token) !== 2) {
+ return false;
+ }
+
+ $encryptedToken = $token[0];
+ $secret = $token[1];
+ try {
+ $decryptedToken = $this->crypto->decrypt($encryptedToken, $secret);
+ } catch (\Exception $e) {
+ return false;
+ }
+
// Check if the token is valid
- if(\OCP\Security\StringUtils::equals($token, $this->items['requesttoken'])) {
+ if(\OCP\Security\StringUtils::equals($decryptedToken, $this->items['requesttoken'])) {
return true;
} else {
return false;
diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php
index e8915b47f24..f297bccbc7d 100644
--- a/lib/private/backgroundjob/joblist.php
+++ b/lib/private/backgroundjob/joblist.php
@@ -87,6 +87,11 @@ class JobList implements IJobList {
}
}
+ protected function removeById($id) {
+ $query = $this->conn->prepare('DELETE FROM `*PREFIX*jobs` WHERE `id` = ?');
+ $query->execute([$id]);
+ }
+
/**
* check if a job is in the list
*
@@ -134,17 +139,25 @@ class JobList implements IJobList {
$query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` > ? ORDER BY `id` ASC', 1);
$query->execute(array($lastId));
if ($row = $query->fetch()) {
- return $this->buildJob($row);
+ $jobId = $row['id'];
+ $job = $this->buildJob($row);
} else {
//begin at the start of the queue
$query = $this->conn->prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` ORDER BY `id` ASC', 1);
$query->execute();
if ($row = $query->fetch()) {
- return $this->buildJob($row);
+ $jobId = $row['id'];
+ $job = $this->buildJob($row);
} else {
return null; //empty job list
}
}
+ if (is_null($job)) {
+ $this->removeById($jobId);
+ return $this->getNext();
+ } else {
+ return $job;
+ }
}
/**
diff --git a/lib/private/config.php b/lib/private/config.php
index 20ff02c1abf..3ad800a00be 100644
--- a/lib/private/config.php
+++ b/lib/private/config.php
@@ -47,8 +47,6 @@ class Config {
protected $configFilePath;
/** @var string */
protected $configFileName;
- /** @var bool */
- protected $debugMode;
/**
* @param string $configDir Path to the config dir, needs to end with '/'
@@ -59,7 +57,6 @@ class Config {
$this->configFilePath = $this->configDir.$fileName;
$this->configFileName = $fileName;
$this->readData();
- $this->debugMode = (defined('DEBUG') && DEBUG);
}
/**
@@ -225,9 +222,6 @@ class Config {
private function writeData() {
// Create a php file ...
$content = "<?php\n";
- if ($this->debugMode) {
- $content .= "define('DEBUG',true);\n";
- }
$content .= '$CONFIG = ';
$content .= var_export($this->cache, true);
$content .= ";\n";
diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php
index 82c8f3de690..b333844f8c8 100644
--- a/lib/private/files/fileinfo.php
+++ b/lib/private/files/fileinfo.php
@@ -252,7 +252,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
$sid = $this->getStorage()->getId();
if (!is_null($sid)) {
$sid = explode(':', $sid);
- return ($sid[0] !== 'local' and $sid[0] !== 'home' and $sid[0] !== 'shared');
+ return ($sid[0] !== 'home' and $sid[0] !== 'shared');
}
return false;
diff --git a/lib/private/http/client/client.php b/lib/private/http/client/client.php
index fb3e06f3c46..323fc0d324f 100644
--- a/lib/private/http/client/client.php
+++ b/lib/private/http/client/client.php
@@ -144,6 +144,7 @@ class Client implements IClient {
* 'debug' => true,
* 'timeout' => 5,
* @return Response
+ * @throws \Exception If the request could not get completed
*/
public function head($uri, $options = []) {
$response = $this->client->head($uri, $options);
@@ -176,6 +177,7 @@ class Client implements IClient {
* 'debug' => true,
* 'timeout' => 5,
* @return Response
+ * @throws \Exception If the request could not get completed
*/
public function post($uri, array $options = []) {
$response = $this->client->post($uri, $options);
@@ -208,6 +210,7 @@ class Client implements IClient {
* 'debug' => true,
* 'timeout' => 5,
* @return Response
+ * @throws \Exception If the request could not get completed
*/
public function put($uri, array $options = []) {
$response = $this->client->put($uri, $options);
@@ -240,6 +243,7 @@ class Client implements IClient {
* 'debug' => true,
* 'timeout' => 5,
* @return Response
+ * @throws \Exception If the request could not get completed
*/
public function delete($uri, array $options = []) {
$response = $this->client->delete($uri, $options);
@@ -273,6 +277,7 @@ class Client implements IClient {
* 'debug' => true,
* 'timeout' => 5,
* @return Response
+ * @throws \Exception If the request could not get completed
*/
public function options($uri, array $options = []) {
$response = $this->client->options($uri, $options);
diff --git a/lib/private/server.php b/lib/private/server.php
index 89001567219..5a3a6328fae 100644
--- a/lib/private/server.php
+++ b/lib/private/server.php
@@ -40,6 +40,7 @@ use bantu\IniGetWrapper\IniGetWrapper;
use OC\AppFramework\Http\Request;
use OC\AppFramework\Db\Db;
use OC\AppFramework\Utility\SimpleContainer;
+use OC\AppFramework\Utility\TimeFactory;
use OC\Command\AsyncBus;
use OC\Diagnostics\EventLogger;
use OC\Diagnostics\NullEventLogger;
@@ -56,6 +57,7 @@ use OC\Security\Crypto;
use OC\Security\Hasher;
use OC\Security\SecureRandom;
use OC\Security\TrustedDomainHelper;
+use OC\Session\CryptoWrapper;
use OC\Tagging\TagMapper;
use OCP\IServerContainer;
use Symfony\Component\EventDispatcher\EventDispatcher;
@@ -159,7 +161,12 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('UserSession', function (Server $c) {
$manager = $c->getUserManager();
- $userSession = new \OC\User\Session($manager, new \OC\Session\Memory(''));
+
+ $session = new \OC\Session\Memory('');
+ $cryptoWrapper = $c->getSessionCryptoWrapper();
+ $session = $cryptoWrapper->wrapSession($session);
+
+ $userSession = new \OC\User\Session($manager, $session);
$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
\OC_Hook::emit('OC_User', 'pre_createUser', array('run' => true, 'uid' => $uid, 'password' => $password));
});
@@ -322,14 +329,14 @@ class Server extends SimpleContainer implements IServerContainer {
);
});
$this->registerService('EventLogger', function (Server $c) {
- if (defined('DEBUG') and DEBUG) {
+ if ($c->getSystemConfig()->getValue('debug', false)) {
return new EventLogger();
} else {
return new NullEventLogger();
}
});
- $this->registerService('QueryLogger', function ($c) {
- if (defined('DEBUG') and DEBUG) {
+ $this->registerService('QueryLogger', function (Server $c) {
+ if ($c->getSystemConfig()->getValue('debug', false)) {
return new QueryLogger();
} else {
return new NullQueryLogger();
@@ -410,6 +417,7 @@ class Server extends SimpleContainer implements IServerContainer {
'requesttoken' => $requestToken,
],
$this->getSecureRandom(),
+ $this->getCrypto(),
$this->getConfig(),
$stream
);
@@ -461,6 +469,32 @@ class Server extends SimpleContainer implements IServerContainer {
$this->registerService('EventDispatcher', function() {
return new EventDispatcher();
});
+ $this->registerService('CryptoWrapper', function (Server $c) {
+ // FIXME: Instantiiated here due to cyclic dependency
+ $request = new Request(
+ [
+ 'get' => $_GET,
+ 'post' => $_POST,
+ 'files' => $_FILES,
+ 'server' => $_SERVER,
+ 'env' => $_ENV,
+ 'cookies' => $_COOKIE,
+ 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
+ ? $_SERVER['REQUEST_METHOD']
+ : null,
+ ],
+ new SecureRandom(),
+ $c->getCrypto(),
+ $c->getConfig()
+ );
+
+ return new CryptoWrapper(
+ $c->getConfig(),
+ $c->getCrypto(),
+ $c->getSecureRandom(),
+ $request
+ );
+ });
}
/**
@@ -976,4 +1010,11 @@ class Server extends SimpleContainer implements IServerContainer {
public function getEventDispatcher() {
return $this->query('EventDispatcher');
}
+
+ /**
+ * @return \OC\Session\CryptoWrapper
+ */
+ public function getSessionCryptoWrapper() {
+ return $this->query('CryptoWrapper');
+ }
}
diff --git a/lib/private/session/cryptosessiondata.php b/lib/private/session/cryptosessiondata.php
new file mode 100644
index 00000000000..60d22b25e97
--- /dev/null
+++ b/lib/private/session/cryptosessiondata.php
@@ -0,0 +1,147 @@
+<?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\Session;
+
+use OCP\ISession;
+use OCP\Security\ICrypto;
+
+/**
+ * Class CryptoSessionData
+ *
+ * @package OC\Session
+ */
+class CryptoSessionData implements \ArrayAccess, ISession {
+ /** @var ISession */
+ protected $session;
+
+ /** @var \OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var string */
+ protected $passphrase;
+
+ /**
+ * @param ISession $session
+ * @param ICrypto $crypto
+ * @param string $passphrase
+ */
+ public function __construct(ISession $session, ICrypto $crypto, $passphrase) {
+ $this->crypto = $crypto;
+ $this->session = $session;
+ $this->passphrase = $passphrase;
+ }
+
+ /**
+ * Set a value in the session
+ *
+ * @param string $key
+ * @param mixed $value
+ */
+ public function set($key, $value) {
+ $encryptedValue = $this->crypto->encrypt(json_encode($value), $this->passphrase);
+ $this->session->set($key, $encryptedValue);
+ }
+
+ /**
+ * Get a value from the session
+ *
+ * @param string $key
+ * @return string|null Either the value or null
+ */
+ public function get($key) {
+ $encryptedValue = $this->session->get($key);
+ if ($encryptedValue === null) {
+ return null;
+ }
+
+ try {
+ $value = $this->crypto->decrypt($encryptedValue, $this->passphrase);
+ return json_decode($value);
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * Check if a named key exists in the session
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function exists($key) {
+ return $this->session->exists($key);
+ }
+
+ /**
+ * Remove a $key/$value pair from the session
+ *
+ * @param string $key
+ */
+ public function remove($key) {
+ $this->session->remove($key);
+ }
+
+ /**
+ * Reset and recreate the session
+ */
+ public function clear() {
+ $this->session->clear();
+ }
+
+ /**
+ * Close the session and release the lock
+ */
+ public function close() {
+ $this->session->close();
+ }
+
+ /**
+ * @param mixed $offset
+ * @return bool
+ */
+ public function offsetExists($offset) {
+ return $this->exists($offset);
+ }
+
+ /**
+ * @param mixed $offset
+ * @return mixed
+ */
+ public function offsetGet($offset) {
+ return $this->get($offset);
+ }
+
+ /**
+ * @param mixed $offset
+ * @param mixed $value
+ */
+ public function offsetSet($offset, $value) {
+ $this->set($offset, $value);
+ }
+
+ /**
+ * @param mixed $offset
+ */
+ public function offsetUnset($offset) {
+ $this->remove($offset);
+ }
+}
diff --git a/lib/private/session/cryptowrapper.php b/lib/private/session/cryptowrapper.php
new file mode 100644
index 00000000000..62bdcbfb719
--- /dev/null
+++ b/lib/private/session/cryptowrapper.php
@@ -0,0 +1,96 @@
+<?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\Session;
+
+use OCP\AppFramework\Utility\ITimeFactory;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\ISession;
+use OCP\Security\ICrypto;
+use OCP\Security\ISecureRandom;
+
+/**
+ * Class CryptoWrapper provides some rough basic level of additional security by
+ * storing the session data in an encrypted form.
+ *
+ * The content of the session is encrypted using another cookie sent by the browser.
+ * One should note that an adversary with access to the source code or the system
+ * memory is still able to read the original session ID from the users' request.
+ * This thus can not be considered a strong security measure one should consider
+ * it as an additional small security obfuscation layer to comply with compliance
+ * guidelines.
+ *
+ * TODO: Remove this in a future relase with an approach such as
+ * https://github.com/owncloud/core/pull/17866
+ *
+ * @package OC\Session
+ */
+class CryptoWrapper {
+ const COOKIE_NAME = 'oc_sessionPassphrase';
+
+ /** @var ISession */
+ protected $session;
+
+ /** @var \OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var ISecureRandom */
+ protected $random;
+
+ /**
+ * @param IConfig $config
+ * @param ICrypto $crypto
+ * @param ISecureRandom $random
+ * @param IRequest $request
+ */
+ public function __construct(IConfig $config,
+ ICrypto $crypto,
+ ISecureRandom $random,
+ IRequest $request) {
+ $this->crypto = $crypto;
+ $this->config = $config;
+ $this->random = $random;
+
+ if (!is_null($request->getCookie(self::COOKIE_NAME))) {
+ $this->passphrase = $request->getCookie(self::COOKIE_NAME);
+ } else {
+ $this->passphrase = $this->random->getMediumStrengthGenerator()->generate(128);
+ $secureCookie = $request->getServerProtocol() === 'https';
+ // FIXME: Required for CI
+ if (!defined('PHPUNIT_RUN')) {
+ setcookie(self::COOKIE_NAME, $this->passphrase, 0, \OC::$WEBROOT, '', $secureCookie, true);
+ }
+ }
+ }
+
+ /**
+ * @param ISession $session
+ * @return ISession
+ */
+ public function wrapSession(ISession $session) {
+ if (!($session instanceof CryptoSessionData)) {
+ return new CryptoSessionData($session, $this->crypto, $this->passphrase);
+ }
+
+ return $session;
+ }
+}
diff --git a/lib/private/template.php b/lib/private/template.php
index e7acc778de3..920be71abbf 100644
--- a/lib/private/template.php
+++ b/lib/private/template.php
@@ -233,7 +233,7 @@ class OC_Template extends \OC\Template\Base {
$content->assign('file', $exception->getFile());
$content->assign('line', $exception->getLine());
$content->assign('trace', $exception->getTraceAsString());
- $content->assign('debugMode', defined('DEBUG') && DEBUG === true);
+ $content->assign('debugMode', \OC::$server->getSystemConfig()->getValue('debug', false));
$content->assign('remoteAddr', $request->getRemoteAddress());
$content->assign('requestID', $request->getId());
$content->printPage();
diff --git a/lib/private/util.php b/lib/private/util.php
index 501dbf5c4c5..edd375b5c36 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -1057,7 +1057,8 @@ class OC_Util {
/**
* Register an get/post call. Important to prevent CSRF attacks.
*
- * @return string Generated token.
+ * @return string The encrypted CSRF token, the shared secret is appended after the `:`.
+ *
* @description
* Creates a 'request token' (random) and stores it inside the session.
* Ever subsequent (ajax) request must use such a valid token to succeed,
@@ -1074,7 +1075,10 @@ class OC_Util {
// Valid token already exists, send it
$requestToken = \OC::$server->getSession()->get('requesttoken');
}
- return ($requestToken);
+
+ // Encrypt the token to mitigate breach-like attacks
+ $sharedSecret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(10);
+ return \OC::$server->getCrypto()->encrypt($requestToken, $sharedSecret) . ':' . $sharedSecret;
}
/**
diff --git a/lib/public/activity/iconsumer.php b/lib/public/activity/iconsumer.php
index a55110ababc..e74884d76c5 100644
--- a/lib/public/activity/iconsumer.php
+++ b/lib/public/activity/iconsumer.php
@@ -37,19 +37,11 @@ namespace OCP\Activity;
*/
interface IConsumer {
/**
- * @param $app
- * @param $subject
- * @param $subjectParams
- * @param $message
- * @param $messageParams
- * @param $file
- * @param $link
- * @param $affectedUser
- * @param $type
- * @param $priority
- * @return mixed
+ * @param IEvent $event
+ * @return null
* @since 6.0.0
+ * @since 8.2.0 Replaced the parameters with an IEvent object
*/
- function receive($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority );
+ public function receive(IEvent $event);
}
diff --git a/lib/public/activity/ievent.php b/lib/public/activity/ievent.php
new file mode 100644
index 00000000000..184c7ae503f
--- /dev/null
+++ b/lib/public/activity/ievent.php
@@ -0,0 +1,200 @@
+<?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/>
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Activity/IEvent interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Activity;
+
+/**
+ * Interface IEvent
+ *
+ * @package OCP\Activity
+ * @since 8.2.0
+ */
+interface IEvent {
+ /**
+ * Set the app of the activity
+ *
+ * @param string $app
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setApp($app);
+
+ /**
+ * Set the type of the activity
+ *
+ * @param string $type
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setType($type);
+
+ /**
+ * Set the affected user of the activity
+ *
+ * @param string $user
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setAffectedUser($user);
+
+ /**
+ * Set the author of the activity
+ *
+ * @param string $author
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setAuthor($author);
+
+ /**
+ * Set the author of the activity
+ *
+ * @param int $timestamp
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setTimestamp($timestamp);
+
+ /**
+ * Set the subject of the activity
+ *
+ * @param string $subject
+ * @param array $parameters
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setSubject($subject, array $parameters = []);
+
+ /**
+ * Set the message of the activity
+ *
+ * @param string $message
+ * @param array $parameters
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setMessage($message, array $parameters = []);
+
+ /**
+ * Set the object of the activity
+ *
+ * @param string $objectType
+ * @param int $objectId
+ * @param string $objectName
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setObject($objectType, $objectId, $objectName = '');
+
+ /**
+ * Set the link of the activity
+ *
+ * @param string $link
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function setLink($link);
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getApp();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getType();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getAffectedUser();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getAuthor();
+
+ /**
+ * @return int
+ * @since 8.2.0
+ */
+ public function getTimestamp();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getSubject();
+
+ /**
+ * @return array
+ * @since 8.2.0
+ */
+ public function getSubjectParameters();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getMessage();
+
+ /**
+ * @return array
+ * @since 8.2.0
+ */
+ public function getMessageParameters();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getObjectType();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getObjectId();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getObjectName();
+
+ /**
+ * @return string
+ * @since 8.2.0
+ */
+ public function getLink();
+}
diff --git a/lib/public/activity/imanager.php b/lib/public/activity/imanager.php
index 0f5dccd8ba1..b3a4969fb06 100644
--- a/lib/public/activity/imanager.php
+++ b/lib/public/activity/imanager.php
@@ -38,22 +38,52 @@ namespace OCP\Activity;
* @since 6.0.0
*/
interface IManager {
+ /**
+ * Generates a new IEvent object
+ *
+ * Make sure to call at least the following methods before sending it to the
+ * app with via the publish() method:
+ * - setApp()
+ * - setType()
+ * - setAffectedUser()
+ * - setSubject()
+ *
+ * @return IEvent
+ * @since 8.2.0
+ */
+ public function generateEvent();
+
+ /**
+ * Publish an event to the activity consumers
+ *
+ * Make sure to call at least the following methods before sending an Event:
+ * - setApp()
+ * - setType()
+ * - setAffectedUser()
+ * - setSubject()
+ *
+ * @param IEvent $event
+ * @return null
+ * @since 8.2.0
+ */
+ public function publish(IEvent $event);
/**
- * @param $app
- * @param $subject
- * @param $subjectParams
- * @param $message
- * @param $messageParams
- * @param $file
- * @param $link
- * @param $affectedUser
- * @param $type
- * @param $priority
- * @return mixed
+ * @param string $app The app where this event is associated with
+ * @param string $subject A short description of the event
+ * @param array $subjectParams Array with parameters that are filled in the subject
+ * @param string $message A longer description of the event
+ * @param array $messageParams Array with parameters that are filled in the message
+ * @param string $file The file including path where this event is associated with
+ * @param string $link A link where this event is associated with
+ * @param string $affectedUser Recipient of the activity
+ * @param string $type Type of the notification
+ * @param int $priority Priority of the notification
+ * @return null
* @since 6.0.0
+ * @deprecated 8.2.0 Grab an IEvent from generateEvent() instead and use the publish() method
*/
- function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority);
+ public function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority);
/**
* In order to improve lazy loading a closure can be registered which will be called in case
@@ -65,7 +95,7 @@ interface IManager {
* @return void
* @since 6.0.0
*/
- function registerConsumer(\Closure $callable);
+ public function registerConsumer(\Closure $callable);
/**
* In order to improve lazy loading a closure can be registered which will be called in case
@@ -77,7 +107,7 @@ interface IManager {
* @return void
* @since 8.0.0
*/
- function registerExtension(\Closure $callable);
+ public function registerExtension(\Closure $callable);
/**
* Will return additional notification types as specified by other apps
@@ -91,21 +121,21 @@ interface IManager {
* @since 8.0.0
* @changed 8.2.0 - Added support to allow limiting notifications to certain methods
*/
- function getNotificationTypes($languageCode);
+ public function getNotificationTypes($languageCode);
/**
* @param string $method
* @return array
* @since 8.0.0
*/
- function getDefaultTypes($method);
+ public function getDefaultTypes($method);
/**
* @param string $type
* @return string
* @since 8.0.0
*/
- function getTypeIcon($type);
+ public function getTypeIcon($type);
/**
* @param string $app
@@ -117,7 +147,7 @@ interface IManager {
* @return string|false
* @since 8.0.0
*/
- function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode);
+ public function translate($app, $text, $params, $stripPath, $highlightParams, $languageCode);
/**
* @param string $app
@@ -125,27 +155,27 @@ interface IManager {
* @return array|false
* @since 8.0.0
*/
- function getSpecialParameterList($app, $text);
+ public function getSpecialParameterList($app, $text);
/**
* @param array $activity
* @return integer|false
* @since 8.0.0
*/
- function getGroupParameter($activity);
+ public function getGroupParameter($activity);
/**
* @return array
* @since 8.0.0
*/
- function getNavigation();
+ public function getNavigation();
/**
* @param string $filterValue
* @return boolean
* @since 8.0.0
*/
- function isFilterValid($filterValue);
+ public function isFilterValid($filterValue);
/**
* @param array $types
@@ -153,14 +183,14 @@ interface IManager {
* @return array
* @since 8.0.0
*/
- function filterNotificationTypes($types, $filter);
+ public function filterNotificationTypes($types, $filter);
/**
* @param string $filter
* @return array
* @since 8.0.0
*/
- function getQueryForFilter($filter);
+ public function getQueryForFilter($filter);
/**
* Get the user we need to use
diff --git a/lib/public/http/client/iclient.php b/lib/public/http/client/iclient.php
index aadb9efd1bb..494ca7d419e 100644
--- a/lib/public/http/client/iclient.php
+++ b/lib/public/http/client/iclient.php
@@ -80,6 +80,7 @@ interface IClient {
* 'verify' => true, // bool or string to CA file
* 'debug' => true,
* @return IResponse
+ * @throws \Exception If the request could not get completed
* @since 8.1.0
*/
public function head($uri, $options = []);
@@ -109,6 +110,7 @@ interface IClient {
* 'verify' => true, // bool or string to CA file
* 'debug' => true,
* @return IResponse
+ * @throws \Exception If the request could not get completed
* @since 8.1.0
*/
public function post($uri, array $options = []);
@@ -138,6 +140,7 @@ interface IClient {
* 'verify' => true, // bool or string to CA file
* 'debug' => true,
* @return IResponse
+ * @throws \Exception If the request could not get completed
* @since 8.1.0
*/
public function put($uri, array $options = []);
@@ -167,6 +170,7 @@ interface IClient {
* 'verify' => true, // bool or string to CA file
* 'debug' => true,
* @return IResponse
+ * @throws \Exception If the request could not get completed
* @since 8.1.0
*/
public function delete($uri, array $options = []);
@@ -196,6 +200,7 @@ interface IClient {
* 'verify' => true, // bool or string to CA file
* 'debug' => true,
* @return IResponse
+ * @throws \Exception If the request could not get completed
* @since 8.1.0
*/
public function options($uri, array $options = []);
diff --git a/settings/ajax/togglegroups.php b/settings/ajax/togglegroups.php
index 87b60e485bf..4d248408db0 100644
--- a/settings/ajax/togglegroups.php
+++ b/settings/ajax/togglegroups.php
@@ -60,9 +60,6 @@ if( OC_Group::inGroup( $username, $group )) {
$error = $l->t("Unable to remove user from group %s", $group);
$success = OC_Group::removeFromGroup( $username, $group );
$usersInGroup=OC_Group::usersInGroup($group);
- if(count($usersInGroup) === 0) {
- OC_Group::deleteGroup($group);
- }
}
else{
$success = OC_Group::addToGroup( $username, $group );
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 9bd342ca6f2..0f1f432e4e2 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -361,6 +361,11 @@ table.grid td.date{
list-style: initial;
margin: 10px 0;
}
+#security-warning-state span {
+ padding-left: 25px;
+ background-position: 5px center;
+ margin-left: -5px;
+}
#shareAPI p { padding-bottom: 0.8em; }
#shareAPI input#shareapiExpireAfterNDays {width: 25px;}
diff --git a/settings/js/admin.js b/settings/js/admin.js
index aa228e76be7..7117c7b46cf 100644
--- a/settings/js/admin.js
+++ b/settings/js/admin.js
@@ -46,6 +46,8 @@ $(document).ready(function(){
var mode = $(this).val();
if (mode === 'ajax' || mode === 'webcron' || mode === 'cron') {
OC.AppConfig.setValue('core', 'backgroundjobs_mode', mode);
+ // clear cron errors on background job mode change
+ OC.AppConfig.deleteKey('core', 'cronErrors');
}
}
});
@@ -177,6 +179,10 @@ $(document).ready(function(){
var $el = $('#postsetupchecks');
$el.find('.loading').addClass('hidden');
if (messages.length === 0) {
+ var securityWarning = $('#security-warning');
+ if (securityWarning.children('ul').children().length === 0) {
+ $('#security-warning-state').find('span').removeClass('hidden');
+ }
} else {
var $errorsEl = $el.find('.errors');
var $warningsEl = $el.find('.warnings');
diff --git a/settings/js/personal.js b/settings/js/personal.js
index 9e4dd54090d..33746d22aca 100644
--- a/settings/js/personal.js
+++ b/settings/js/personal.js
@@ -321,7 +321,7 @@ $(document).ready(function () {
var url = OC.generateUrl(
'/avatar/{user}/{size}',
{user: OC.currentUser, size: 1}
- ) + '?requesttoken=' + encodeURIComponent(oc_requesttoken);
+ );
$.get(url, function (result) {
if (typeof(result) === 'object') {
$('#removeavatar').hide();
diff --git a/settings/js/users/users.js b/settings/js/users/users.js
index 4e686a6db8f..5b12366ad40 100644
--- a/settings/js/users/users.js
+++ b/settings/js/users/users.js
@@ -470,17 +470,6 @@ var UserList = {
UserList.availableGroups.push(groupName);
}
- // in case this was the last user in that group the group has to be removed
- var groupElement = GroupList.getGroupLI(groupName);
- var userCount = GroupList.getUserCount(groupElement);
- if (response.data.action === 'remove' && userCount === 1) {
- _.without(UserList.availableGroups, groupName);
- GroupList.remove(groupName);
- $('.groupsselect option').filterAttr('value', groupName).remove();
- $('.subadminsselect option').filterAttr('value', groupName).remove();
- }
-
-
}
if (response.data.message) {
OC.Notification.show(response.data.message);
diff --git a/settings/templates/admin.php b/settings/templates/admin.php
index 888ed823793..9c161281846 100644
--- a/settings/templates/admin.php
+++ b/settings/templates/admin.php
@@ -177,6 +177,9 @@ if ($_['cronErrors']) {
<?php print_unescaped($l->t('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>.', link_to_docs('admin-install'))); ?>
</p>
</div>
+<div id="security-warning-state">
+ <span class="hidden icon-checkmark"><?php p($l->t('All checks passed.'));?></span>
+</div>
</div>
<div class="section" id="shareAPI">
diff --git a/settings/templates/users/part.grouplist.php b/settings/templates/users/part.grouplist.php
index 51638c7bcce..cd6ac4a1e89 100644
--- a/settings/templates/users/part.grouplist.php
+++ b/settings/templates/users/part.grouplist.php
@@ -43,9 +43,11 @@
</a>
<span class="utils">
<span class="usercount"><?php if($group['usercount'] > 0) { p($group['usercount']); } ?></span>
+ <?php if($_['isAdmin']): ?>
<a href="#" class="action delete" original-title="<?php p($l->t('Delete'))?>">
<img src="<?php print_unescaped(image_path('core', 'actions/delete.svg')) ?>" class="svg" />
</a>
+ <?php endif; ?>
</span>
</li>
<?php endforeach; ?>
diff --git a/status.php b/status.php
index 6e7bcea5266..90250ff2615 100644
--- a/status.php
+++ b/status.php
@@ -41,6 +41,7 @@ try {
if (OC::$CLI) {
print_r($values);
} else {
+ header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
echo json_encode($values);
}
diff --git a/tests/core/command/log/managetest.php b/tests/core/command/log/managetest.php
new file mode 100644
index 00000000000..6fb83347f23
--- /dev/null
+++ b/tests/core/command/log/managetest.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@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 Tests\Core\Command\Log;
+
+
+use OC\Core\Command\Log\Manage;
+use Test\TestCase;
+
+class ManageTest extends TestCase {
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $consoleInput;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $consoleOutput;
+
+ /** @var \Symfony\Component\Console\Command\Command */
+ protected $command;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $config = $this->config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $this->command = new Manage($config);
+ }
+
+ public function testChangeBackend() {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['backend', 'syslog']
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('log_type', 'syslog');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ public function testChangeLevel() {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['level', 'debug']
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('loglevel', 0);
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ public function testChangeTimezone() {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['timezone', 'UTC']
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('logtimezone', 'UTC');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidateBackend() {
+ self::invokePrivate($this->command, 'validateBackend', ['notabackend']);
+ }
+
+ /**
+ * @expectedException \Exception
+ */
+ public function testValidateTimezone() {
+ // this might need to be changed when humanity colonises Mars
+ self::invokePrivate($this->command, 'validateTimezone', ['Mars/OlympusMons']);
+ }
+
+ public function convertLevelStringProvider() {
+ return [
+ ['dEbug', 0],
+ ['inFO', 1],
+ ['Warning', 2],
+ ['wArn', 2],
+ ['error', 3],
+ ['eRr', 3],
+ ];
+ }
+
+ /**
+ * @dataProvider convertLevelStringProvider
+ */
+ public function testConvertLevelString($levelString, $expectedInt) {
+ $this->assertEquals($expectedInt,
+ self::invokePrivate($this->command, 'convertLevelString', [$levelString])
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConvertLevelStringInvalid() {
+ self::invokePrivate($this->command, 'convertLevelString', ['abc']);
+ }
+
+ public function convertLevelNumberProvider() {
+ return [
+ [0, 'Debug'],
+ [1, 'Info'],
+ [2, 'Warning'],
+ [3, 'Error'],
+ ];
+ }
+
+ /**
+ * @dataProvider convertLevelNumberProvider
+ */
+ public function testConvertLevelNumber($levelNum, $expectedString) {
+ $this->assertEquals($expectedString,
+ self::invokePrivate($this->command, 'convertLevelNumber', [$levelNum])
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConvertLevelNumberInvalid() {
+ self::invokePrivate($this->command, 'convertLevelNumber', [11]);
+ }
+
+ public function testGetConfiguration() {
+ $this->config->expects($this->at(0))
+ ->method('getSystemValue')
+ ->with('log_type', 'owncloud')
+ ->willReturn('log_type_value');
+ $this->config->expects($this->at(1))
+ ->method('getSystemValue')
+ ->with('loglevel', 2)
+ ->willReturn(0);
+ $this->config->expects($this->at(2))
+ ->method('getSystemValue')
+ ->with('logtimezone', 'UTC')
+ ->willReturn('logtimezone_value');
+
+ $this->consoleOutput->expects($this->at(0))
+ ->method('writeln')
+ ->with('Enabled logging backend: log_type_value');
+ $this->consoleOutput->expects($this->at(1))
+ ->method('writeln')
+ ->with('Log level: Debug (0)');
+ $this->consoleOutput->expects($this->at(2))
+ ->method('writeln')
+ ->with('Log timezone: logtimezone_value');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+}
diff --git a/tests/core/command/log/owncloudtest.php b/tests/core/command/log/owncloudtest.php
new file mode 100644
index 00000000000..3cb05221c37
--- /dev/null
+++ b/tests/core/command/log/owncloudtest.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * @author Robin McCorkell <rmccorkell@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 Tests\Core\Command\Log;
+
+
+use OC\Core\Command\Log\OwnCloud;
+use Test\TestCase;
+
+class OwnCloudTest extends TestCase {
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $consoleInput;
+ /** @var \PHPUnit_Framework_MockObject_MockObject */
+ protected $consoleOutput;
+
+ /** @var \Symfony\Component\Console\Command\Command */
+ protected $command;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $config = $this->config = $this->getMockBuilder('OCP\IConfig')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->consoleInput = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $this->consoleOutput = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $this->command = new OwnCloud($config);
+ }
+
+ public function testEnable() {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['enable', 'true']
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('log_type', 'owncloud');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ public function testChangeFile() {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['file', '/foo/bar/file.log']
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('logfile', '/foo/bar/file.log');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ public function changeRotateSizeProvider() {
+ return [
+ ['42', 42],
+ ['0', 0],
+ ['1 kB', 1024],
+ ['5MB', 5 * 1024 * 1024],
+ ];
+ }
+
+ /**
+ * @dataProvider changeRotateSizeProvider
+ */
+ public function testChangeRotateSize($optionValue, $configValue) {
+ $this->consoleInput->method('getOption')
+ ->will($this->returnValueMap([
+ ['rotate-size', $optionValue]
+ ]));
+ $this->config->expects($this->once())
+ ->method('setSystemValue')
+ ->with('log_rotate_size', $configValue);
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+ public function testGetConfiguration() {
+ $this->config->method('getSystemValue')
+ ->will($this->returnValueMap([
+ ['log_type', 'owncloud', 'log_type_value'],
+ ['datadirectory', \OC::$SERVERROOT.'/data', '/data/directory/'],
+ ['logfile', '/data/directory/owncloud.log', '/var/log/owncloud.log'],
+ ['log_rotate_size', 0, 5 * 1024 * 1024],
+ ]));
+
+ $this->consoleOutput->expects($this->at(0))
+ ->method('writeln')
+ ->with('Log backend ownCloud: disabled');
+ $this->consoleOutput->expects($this->at(1))
+ ->method('writeln')
+ ->with('Log file: /var/log/owncloud.log');
+ $this->consoleOutput->expects($this->at(2))
+ ->method('writeln')
+ ->with('Rotate at: 5 MB');
+
+ self::invokePrivate($this->command, 'execute', [$this->consoleInput, $this->consoleOutput]);
+ }
+
+}
diff --git a/tests/core/lostpassword/controller/lostcontrollertest.php b/tests/core/lostpassword/controller/lostcontrollertest.php
index f82fc1ba3ff..0f8cb4fc5c8 100644
--- a/tests/core/lostpassword/controller/lostcontrollertest.php
+++ b/tests/core/lostpassword/controller/lostcontrollertest.php
@@ -1,9 +1,22 @@
<?php
/**
- * Copyright (c) 2014-2015 Lukas Reschke <lukas@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
+ * @author Lukas Reschke <lukas@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\Core\LostPassword\Controller;
@@ -47,6 +60,8 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
->disableOriginalConstructor()->getMock();
$this->container['SecureRandom'] = $this->getMockBuilder('\OCP\Security\ISecureRandom')
->disableOriginalConstructor()->getMock();
+ $this->container['TimeFactory'] = $this->getMockBuilder('\OCP\AppFramework\Utility\ITimeFactory')
+ ->disableOriginalConstructor()->getMock();
$this->container['IsEncryptionEnabled'] = true;
$this->lostController = $this->container['LostController'];
}
@@ -116,6 +131,10 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
->method('userExists')
->with('ExistingUser')
->will($this->returnValue(true));
+ $this->container['TimeFactory']
+ ->expects($this->once())
+ ->method('getTime')
+ ->will($this->returnValue(12348));
$this->container['Config']
->expects($this->once())
->method('getUserValue')
@@ -128,7 +147,7 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
$this->container['Config']
->expects($this->once())
->method('setUserValue')
- ->with('ExistingUser', 'owncloud', 'lostpassword', 'ThisIsMaybeANotSoSecretToken!');
+ ->with('ExistingUser', 'owncloud', 'lostpassword', '12348:ThisIsMaybeANotSoSecretToken!');
$this->container['URLGenerator']
->expects($this->once())
->method('linkToRouteAbsolute')
@@ -190,7 +209,11 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
$this->container['Config']
->expects($this->once())
->method('setUserValue')
- ->with('ExistingUser', 'owncloud', 'lostpassword', 'ThisIsMaybeANotSoSecretToken!');
+ ->with('ExistingUser', 'owncloud', 'lostpassword', '12348:ThisIsMaybeANotSoSecretToken!');
+ $this->container['TimeFactory']
+ ->expects($this->once())
+ ->method('getTime')
+ ->will($this->returnValue(12348));
$this->container['URLGenerator']
->expects($this->once())
->method('linkToRouteAbsolute')
@@ -256,9 +279,13 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
->expects($this->once())
->method('getUserValue')
->with('ValidTokenUser', 'owncloud', 'lostpassword', null)
- ->will($this->returnValue('TheOnlyAndOnlyOneTokenToResetThePassword'));
+ ->will($this->returnValue('12345:TheOnlyAndOnlyOneTokenToResetThePassword'));
$user = $this->getMockBuilder('\OCP\IUser')
->disableOriginalConstructor()->getMock();
+ $user
+ ->expects($this->once())
+ ->method('getLastLogin')
+ ->will($this->returnValue(12344));
$user->expects($this->once())
->method('setPassword')
->with('NewPassword')
@@ -272,12 +299,94 @@ class LostControllerTest extends \PHPUnit_Framework_TestCase {
->expects($this->once())
->method('deleteUserValue')
->with('ValidTokenUser', 'owncloud', 'lostpassword');
+ $this->container['TimeFactory']
+ ->expects($this->once())
+ ->method('getTime')
+ ->will($this->returnValue(12348));
$response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
$expectedResponse = array('status' => 'success');
$this->assertSame($expectedResponse, $response);
}
+ public function testSetPasswordExpiredToken() {
+ $this->container['Config']
+ ->expects($this->once())
+ ->method('getUserValue')
+ ->with('ValidTokenUser', 'owncloud', 'lostpassword', null)
+ ->will($this->returnValue('12345:TheOnlyAndOnlyOneTokenToResetThePassword'));
+ $user = $this->getMockBuilder('\OCP\IUser')
+ ->disableOriginalConstructor()->getMock();
+ $this->container['UserManager']
+ ->expects($this->once())
+ ->method('get')
+ ->with('ValidTokenUser')
+ ->will($this->returnValue($user));
+ $this->container['TimeFactory']
+ ->expects($this->once())
+ ->method('getTime')
+ ->will($this->returnValue(55546));
+
+ $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
+ $expectedResponse = [
+ 'status' => 'error',
+ 'msg' => 'Couldn\'t reset password because the token is expired',
+ ];
+ $this->assertSame($expectedResponse, $response);
+ }
+
+ public function testSetPasswordInvalidDataInDb() {
+ $this->container['Config']
+ ->expects($this->once())
+ ->method('getUserValue')
+ ->with('ValidTokenUser', 'owncloud', 'lostpassword', null)
+ ->will($this->returnValue('TheOnlyAndOnlyOneTokenToResetThePassword'));
+ $user = $this->getMockBuilder('\OCP\IUser')
+ ->disableOriginalConstructor()->getMock();
+ $this->container['UserManager']
+ ->expects($this->once())
+ ->method('get')
+ ->with('ValidTokenUser')
+ ->will($this->returnValue($user));
+
+ $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
+ $expectedResponse = [
+ 'status' => 'error',
+ 'msg' => 'Couldn\'t reset password because the token is invalid',
+ ];
+ $this->assertSame($expectedResponse, $response);
+ }
+
+ public function testSetPasswordExpiredTokenDueToLogin() {
+ $this->container['Config']
+ ->expects($this->once())
+ ->method('getUserValue')
+ ->with('ValidTokenUser', 'owncloud', 'lostpassword', null)
+ ->will($this->returnValue('12345:TheOnlyAndOnlyOneTokenToResetThePassword'));
+ $user = $this->getMockBuilder('\OCP\IUser')
+ ->disableOriginalConstructor()->getMock();
+ $user
+ ->expects($this->once())
+ ->method('getLastLogin')
+ ->will($this->returnValue(12346));
+ $this->container['UserManager']
+ ->expects($this->once())
+ ->method('get')
+ ->with('ValidTokenUser')
+ ->will($this->returnValue($user));
+ $this->container['TimeFactory']
+ ->expects($this->once())
+ ->method('getTime')
+ ->will($this->returnValue(12345));
+
+ $response = $this->lostController->setPassword('TheOnlyAndOnlyOneTokenToResetThePassword', 'ValidTokenUser', 'NewPassword', true);
+ $expectedResponse = [
+ 'status' => 'error',
+ 'msg' => 'Couldn\'t reset password because the token is expired',
+ ];
+ $this->assertSame($expectedResponse, $response);
+ }
+
public function testIsSetPasswordWithoutTokenFailing() {
$this->container['Config']
->expects($this->once())
diff --git a/tests/lib/activitymanager.php b/tests/lib/activitymanager.php
index 28caf575948..26759d46270 100644
--- a/tests/lib/activitymanager.php
+++ b/tests/lib/activitymanager.php
@@ -41,6 +41,9 @@ class Test_ActivityManager extends \Test\TestCase {
$this->config
);
+ $this->assertSame([], $this->invokePrivate($this->activityManager, 'getConsumers'));
+ $this->assertSame([], $this->invokePrivate($this->activityManager, 'getExtensions'));
+
$this->activityManager->registerConsumer(function() {
return new NoOpConsumer();
});
@@ -50,6 +53,11 @@ class Test_ActivityManager extends \Test\TestCase {
$this->activityManager->registerExtension(function() {
return new SimpleExtension();
});
+
+ $this->assertNotEmpty($this->invokePrivate($this->activityManager, 'getConsumers'));
+ $this->assertNotEmpty($this->invokePrivate($this->activityManager, 'getConsumers'));
+ $this->assertNotEmpty($this->invokePrivate($this->activityManager, 'getExtensions'));
+ $this->assertNotEmpty($this->invokePrivate($this->activityManager, 'getExtensions'));
}
public function testGetConsumers() {
@@ -249,6 +257,192 @@ class Test_ActivityManager extends \Test\TestCase {
->method('getUser')
->willReturn($mockUser);
}
+
+ /**
+ * @expectedException BadMethodCallException
+ * @expectedExceptionMessage App not set
+ * @expectedExceptionCode 10
+ */
+ public function testPublishExceptionNoApp() {
+ $event = new \OC\Activity\Event();
+ $this->activityManager->publish($event);
+ }
+
+ /**
+ * @expectedException BadMethodCallException
+ * @expectedExceptionMessage Type not set
+ * @expectedExceptionCode 11
+ */
+ public function testPublishExceptionNoType() {
+ $event = new \OC\Activity\Event();
+ $event->setApp('test');
+ $this->activityManager->publish($event);
+ }
+
+ /**
+ * @expectedException BadMethodCallException
+ * @expectedExceptionMessage Affected user not set
+ * @expectedExceptionCode 12
+ */
+ public function testPublishExceptionNoAffectedUser() {
+ $event = new \OC\Activity\Event();
+ $event->setApp('test')
+ ->setType('test_type');
+ $this->activityManager->publish($event);
+ }
+
+ /**
+ * @expectedException BadMethodCallException
+ * @expectedExceptionMessage Subject not set
+ * @expectedExceptionCode 13
+ */
+ public function testPublishExceptionNoSubject() {
+ $event = new \OC\Activity\Event();
+ $event->setApp('test')
+ ->setType('test_type')
+ ->setAffectedUser('test_affected');
+ $this->activityManager->publish($event);
+ }
+
+ public function dataPublish() {
+ return [
+ [null],
+ ['test_author'],
+ ];
+ }
+
+ /**
+ * @dataProvider dataPublish
+ * @param string $author
+ */
+ public function testPublish($author) {
+ if ($author !== null) {
+ $authorObject = $this->getMockBuilder('OCP\IUser')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $authorObject->expects($this->once())
+ ->method('getUID')
+ ->willReturn($author);
+ $this->session->expects($this->atLeastOnce())
+ ->method('getUser')
+ ->willReturn($authorObject);
+ }
+
+ $event = new \OC\Activity\Event();
+ $event->setApp('test')
+ ->setType('test_type')
+ ->setSubject('test_subject', [])
+ ->setAffectedUser('test_affected');
+
+ $consumer = $this->getMockBuilder('OCP\Activity\IConsumer')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $consumer->expects($this->once())
+ ->method('receive')
+ ->with($event)
+ ->willReturnCallback(function(\OCP\Activity\IEvent $event) use ($author) {
+ $this->assertLessThanOrEqual(time() + 2, $event->getTimestamp(), 'Timestamp not set correctly');
+ $this->assertGreaterThanOrEqual(time() - 2, $event->getTimestamp(), 'Timestamp not set correctly');
+ $this->assertSame($author, $event->getAuthor(), 'Author name not set correctly');
+ });
+ $this->activityManager->registerConsumer(function () use ($consumer) {
+ return $consumer;
+ });
+
+ $this->activityManager->publish($event);
+ }
+
+ public function testPublishAllManually() {
+ $event = new \OC\Activity\Event();
+ $event->setApp('test_app')
+ ->setType('test_type')
+ ->setAffectedUser('test_affected')
+ ->setAuthor('test_author')
+ ->setTimestamp(1337)
+ ->setSubject('test_subject', ['test_subject_param'])
+ ->setMessage('test_message', ['test_message_param'])
+ ->setObject('test_object_type', 42, 'test_object_name')
+ ->setLink('test_link')
+ ;
+
+ $consumer = $this->getMockBuilder('OCP\Activity\IConsumer')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $consumer->expects($this->once())
+ ->method('receive')
+ ->willReturnCallback(function(\OCP\Activity\IEvent $event) {
+ $this->assertSame('test_app', $event->getApp(), 'App not set correctly');
+ $this->assertSame('test_type', $event->getType(), 'Type not set correctly');
+ $this->assertSame('test_affected', $event->getAffectedUser(), 'Affected user not set correctly');
+ $this->assertSame('test_author', $event->getAuthor(), 'Author not set correctly');
+ $this->assertSame(1337, $event->getTimestamp(), 'Timestamp not set correctly');
+ $this->assertSame('test_subject', $event->getSubject(), 'Subject not set correctly');
+ $this->assertSame(['test_subject_param'], $event->getSubjectParameters(), 'Subject parameter not set correctly');
+ $this->assertSame('test_message', $event->getMessage(), 'Message not set correctly');
+ $this->assertSame(['test_message_param'], $event->getMessageParameters(), 'Message parameter not set correctly');
+ $this->assertSame('test_object_type', $event->getObjectType(), 'Object type not set correctly');
+ $this->assertSame(42, $event->getObjectId(), 'Object ID not set correctly');
+ $this->assertSame('test_object_name', $event->getObjectName(), 'Object name not set correctly');
+ $this->assertSame('test_link', $event->getLink(), 'Link not set correctly');
+ });
+ $this->activityManager->registerConsumer(function () use ($consumer) {
+ return $consumer;
+ });
+
+ $this->activityManager->publish($event);
+ }
+
+ public function testDeprecatedPublishActivity() {
+ $event = new \OC\Activity\Event();
+ $event->setApp('test_app')
+ ->setType('test_type')
+ ->setAffectedUser('test_affected')
+ ->setAuthor('test_author')
+ ->setTimestamp(1337)
+ ->setSubject('test_subject', ['test_subject_param'])
+ ->setMessage('test_message', ['test_message_param'])
+ ->setObject('test_object_type', 42, 'test_object_name')
+ ->setLink('test_link')
+ ;
+
+ $consumer = $this->getMockBuilder('OCP\Activity\IConsumer')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $consumer->expects($this->once())
+ ->method('receive')
+ ->willReturnCallback(function(\OCP\Activity\IEvent $event) {
+ $this->assertSame('test_app', $event->getApp(), 'App not set correctly');
+ $this->assertSame('test_type', $event->getType(), 'Type not set correctly');
+ $this->assertSame('test_affected', $event->getAffectedUser(), 'Affected user not set correctly');
+ $this->assertSame('test_subject', $event->getSubject(), 'Subject not set correctly');
+ $this->assertSame(['test_subject_param'], $event->getSubjectParameters(), 'Subject parameter not set correctly');
+ $this->assertSame('test_message', $event->getMessage(), 'Message not set correctly');
+ $this->assertSame(['test_message_param'], $event->getMessageParameters(), 'Message parameter not set correctly');
+ $this->assertSame('test_object_name', $event->getObjectName(), 'Object name not set correctly');
+ $this->assertSame('test_link', $event->getLink(), 'Link not set correctly');
+
+ // The following values can not be used via publishActivity()
+ $this->assertLessThanOrEqual(time() + 2, $event->getTimestamp(), 'Timestamp not set correctly');
+ $this->assertGreaterThanOrEqual(time() - 2, $event->getTimestamp(), 'Timestamp not set correctly');
+ $this->assertSame(null, $event->getAuthor(), 'Author not set correctly');
+ $this->assertSame('', $event->getObjectType(), 'Object type should not be set');
+ $this->assertSame(0, $event->getObjectId(), 'Object ID should not be set');
+ });
+ $this->activityManager->registerConsumer(function () use ($consumer) {
+ return $consumer;
+ });
+
+ $this->activityManager->publishActivity(
+ $event->getApp(),
+ $event->getSubject(), $event->getSubjectParameters(),
+ $event->getMessage(), $event->getMessageParameters(),
+ $event->getObjectName(),
+ $event->getLink(),
+ $event->getAffectedUser(),
+ $event->getType(),
+ \OCP\Activity\IExtension::PRIORITY_MEDIUM
+ );
+ }
}
class SimpleExtension implements \OCP\Activity\IExtension {
@@ -368,6 +562,7 @@ class NoOpExtension implements \OCP\Activity\IExtension {
class NoOpConsumer implements \OCP\Activity\IConsumer {
- public function receive($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority) {
+ public function receive(\OCP\Activity\IEvent $event) {
+
}
}
diff --git a/tests/lib/app/manager.php b/tests/lib/app/manager.php
index 6cf7eb3bb6c..7333d7601b1 100644
--- a/tests/lib/app/manager.php
+++ b/tests/lib/app/manager.php
@@ -204,4 +204,74 @@ class Manager extends \PHPUnit_Framework_TestCase {
$this->appConfig->setValue('test4', 'enabled', '["asd"]');
$this->assertEquals(['test1', 'test3'], $this->manager->getEnabledAppsForUser($user));
}
+
+ public function testGetAppsNeedingUpgrade() {
+ $this->manager = $this->getMockBuilder('\OC\App\AppManager')
+ ->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory])
+ ->setMethods(['getAppInfo'])
+ ->getMock();
+
+ $appInfos = [
+ 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '9.0.0'],
+ 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
+ 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
+ 'test4' => ['id' => 'test4', 'version' => '3.0.0', 'requiremin' => '8.1.0'],
+ 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
+ ];
+
+ $this->manager->expects($this->any())
+ ->method('getAppInfo')
+ ->will($this->returnCallback(
+ function($appId) use ($appInfos) {
+ return $appInfos[$appId];
+ }
+ ));
+
+ $this->appConfig->setValue('test1', 'enabled', 'yes');
+ $this->appConfig->setValue('test1', 'installed_version', '1.0.0');
+ $this->appConfig->setValue('test2', 'enabled', 'yes');
+ $this->appConfig->setValue('test2', 'installed_version', '1.0.0');
+ $this->appConfig->setValue('test3', 'enabled', 'yes');
+ $this->appConfig->setValue('test3', 'installed_version', '1.0.0');
+ $this->appConfig->setValue('test4', 'enabled', 'yes');
+ $this->appConfig->setValue('test4', 'installed_version', '2.4.0');
+
+ $apps = $this->manager->getAppsNeedingUpgrade('8.2.0');
+
+ $this->assertCount(2, $apps);
+ $this->assertEquals('test1', $apps[0]['id']);
+ $this->assertEquals('test4', $apps[1]['id']);
+ }
+
+ public function testGetIncompatibleApps() {
+ $this->manager = $this->getMockBuilder('\OC\App\AppManager')
+ ->setConstructorArgs([$this->userSession, $this->appConfig, $this->groupManager, $this->cacheFactory])
+ ->setMethods(['getAppInfo'])
+ ->getMock();
+
+ $appInfos = [
+ 'test1' => ['id' => 'test1', 'version' => '1.0.1', 'requiremax' => '8.0.0'],
+ 'test2' => ['id' => 'test2', 'version' => '1.0.0', 'requiremin' => '8.2.0'],
+ 'test3' => ['id' => 'test3', 'version' => '1.2.4', 'requiremin' => '9.0.0'],
+ 'testnoversion' => ['id' => 'testnoversion', 'requiremin' => '8.2.0'],
+ ];
+
+ $this->manager->expects($this->any())
+ ->method('getAppInfo')
+ ->will($this->returnCallback(
+ function($appId) use ($appInfos) {
+ return $appInfos[$appId];
+ }
+ ));
+
+ $this->appConfig->setValue('test1', 'enabled', 'yes');
+ $this->appConfig->setValue('test2', 'enabled', 'yes');
+ $this->appConfig->setValue('test3', 'enabled', 'yes');
+
+ $apps = $this->manager->getIncompatibleApps('8.2.0');
+
+ $this->assertCount(2, $apps);
+ $this->assertEquals('test1', $apps[0]['id']);
+ $this->assertEquals('test3', $apps[1]['id']);
+ }
}
diff --git a/tests/lib/appframework/controller/ApiControllerTest.php b/tests/lib/appframework/controller/ApiControllerTest.php
index 137e5950f67..573fe7f3bad 100644
--- a/tests/lib/appframework/controller/ApiControllerTest.php
+++ b/tests/lib/appframework/controller/ApiControllerTest.php
@@ -38,6 +38,7 @@ class ApiControllerTest extends \Test\TestCase {
$request = new Request(
['server' => ['HTTP_ORIGIN' => 'test']],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->controller = new ChildApiController('app', $request, 'verbs',
diff --git a/tests/lib/appframework/controller/ControllerTest.php b/tests/lib/appframework/controller/ControllerTest.php
index 0d7716da411..243014a91a7 100644
--- a/tests/lib/appframework/controller/ControllerTest.php
+++ b/tests/lib/appframework/controller/ControllerTest.php
@@ -76,6 +76,7 @@ class ControllerTest extends \Test\TestCase {
'method' => 'hi',
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
diff --git a/tests/lib/appframework/controller/OCSControllerTest.php b/tests/lib/appframework/controller/OCSControllerTest.php
index 92b092cf0e9..292a56e3caa 100644
--- a/tests/lib/appframework/controller/OCSControllerTest.php
+++ b/tests/lib/appframework/controller/OCSControllerTest.php
@@ -43,6 +43,7 @@ class OCSControllerTest extends \Test\TestCase {
],
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$controller = new ChildOCSController('app', $request, 'verbs',
@@ -64,6 +65,7 @@ class OCSControllerTest extends \Test\TestCase {
$controller = new ChildOCSController('app', new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
));
$expected = "<?xml version=\"1.0\"?>\n" .
@@ -96,6 +98,7 @@ class OCSControllerTest extends \Test\TestCase {
$controller = new ChildOCSController('app', new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
));
$expected = "<?xml version=\"1.0\"?>\n" .
@@ -128,6 +131,7 @@ class OCSControllerTest extends \Test\TestCase {
$controller = new ChildOCSController('app', new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
));
$expected = '{"ocs":{"meta":{"status":"failure","statuscode":400,"message":"OK",' .
diff --git a/tests/lib/appframework/dependencyinjection/DIContainerTest.php b/tests/lib/appframework/dependencyinjection/DIContainerTest.php
index 0cbdddbb205..598e70beffc 100644
--- a/tests/lib/appframework/dependencyinjection/DIContainerTest.php
+++ b/tests/lib/appframework/dependencyinjection/DIContainerTest.php
@@ -74,6 +74,7 @@ class DIContainerTest extends \Test\TestCase {
$this->container['Request'] = new Request(
['method' => 'GET'],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$security = $this->container['SecurityMiddleware'];
diff --git a/tests/lib/appframework/http/DispatcherTest.php b/tests/lib/appframework/http/DispatcherTest.php
index 02c86df8e72..c25fd7b6f85 100644
--- a/tests/lib/appframework/http/DispatcherTest.php
+++ b/tests/lib/appframework/http/DispatcherTest.php
@@ -295,6 +295,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'POST'
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
@@ -322,6 +323,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'POST',
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
@@ -352,6 +354,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'GET'
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
@@ -381,6 +384,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'GET'
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
@@ -411,6 +415,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'PUT'
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
@@ -443,6 +448,7 @@ class DispatcherTest extends \Test\TestCase {
'method' => 'POST'
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->dispatcher = new Dispatcher(
diff --git a/tests/lib/appframework/http/RequestTest.php b/tests/lib/appframework/http/RequestTest.php
index 10a9e486c97..deb28909869 100644
--- a/tests/lib/appframework/http/RequestTest.php
+++ b/tests/lib/appframework/http/RequestTest.php
@@ -10,6 +10,7 @@
namespace OC\AppFramework\Http;
+use OC\Security\Crypto;
use OCP\Security\ISecureRandom;
use OCP\IConfig;
@@ -53,6 +54,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -85,6 +87,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -96,8 +99,8 @@ class RequestTest extends \Test\TestCase {
/**
- * @expectedException \RuntimeException
- */
+ * @expectedException \RuntimeException
+ */
public function testImmutableArrayAccess() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
@@ -107,6 +110,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -115,8 +119,8 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @expectedException \RuntimeException
- */
+ * @expectedException \RuntimeException
+ */
public function testImmutableMagicAccess() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
@@ -126,6 +130,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -134,8 +139,8 @@ class RequestTest extends \Test\TestCase {
}
/**
- * @expectedException \LogicException
- */
+ * @expectedException \LogicException
+ */
public function testGetTheMethodRight() {
$vars = array(
'get' => array('name' => 'John Q. Public', 'nickname' => 'Joey'),
@@ -145,6 +150,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -161,6 +167,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -182,6 +189,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -206,6 +214,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -230,6 +239,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -250,6 +260,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -274,6 +285,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -303,6 +315,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -324,6 +337,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
$vars,
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -347,6 +361,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -358,6 +373,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
\OC::$server->getSecureRandom(),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -382,6 +398,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -410,6 +427,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -438,6 +456,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -470,6 +489,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -497,6 +517,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -506,10 +527,10 @@ class RequestTest extends \Test\TestCase {
public function testGetServerProtocolWithProtoValid() {
$this->config
- ->expects($this->exactly(2))
- ->method('getSystemValue')
- ->with('overwriteprotocol')
- ->will($this->returnValue(''));
+ ->expects($this->exactly(2))
+ ->method('getSystemValue')
+ ->with('overwriteprotocol')
+ ->will($this->returnValue(''));
$requestHttps = new Request(
[
@@ -518,6 +539,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -528,6 +550,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -551,6 +574,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -571,6 +595,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -587,6 +612,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -607,6 +633,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -628,6 +655,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -716,6 +744,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -732,6 +761,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -749,6 +779,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -766,6 +797,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -793,6 +825,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -814,6 +847,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -840,6 +874,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -866,6 +901,7 @@ class RequestTest extends \Test\TestCase {
],
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -882,6 +918,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -909,6 +946,7 @@ class RequestTest extends \Test\TestCase {
$request = new Request(
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -924,6 +962,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -944,6 +983,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -964,6 +1004,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -986,6 +1027,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -1008,6 +1050,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -1030,6 +1073,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -1052,6 +1096,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -1105,6 +1150,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
);
@@ -1144,6 +1190,7 @@ class RequestTest extends \Test\TestCase {
]
],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
])
@@ -1157,17 +1204,25 @@ class RequestTest extends \Test\TestCase {
}
public function testPassesCSRFCheckWithGet() {
+ $crypto = $this->getMock('\OCP\Security\ICrypto');
+ $crypto
+ ->expects($this->once())
+ ->method('decrypt')
+ ->with('1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4', 'secret')
+ ->will($this->returnValue('MyStoredRequestToken'));
+
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'get' => [
- 'requesttoken' => 'MyStoredRequestToken',
+ 'requesttoken' => '1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4:secret',
],
'requesttoken' => 'MyStoredRequestToken',
],
$this->secureRandom,
+ $crypto,
$this->config,
$this->stream
])
@@ -1177,17 +1232,25 @@ class RequestTest extends \Test\TestCase {
}
public function testPassesCSRFCheckWithPost() {
+ $crypto = $this->getMock('\OCP\Security\ICrypto');
+ $crypto
+ ->expects($this->once())
+ ->method('decrypt')
+ ->with('1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4', 'secret')
+ ->will($this->returnValue('MyStoredRequestToken'));
+
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'post' => [
- 'requesttoken' => 'MyStoredRequestToken',
+ 'requesttoken' => '1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4:secret',
],
'requesttoken' => 'MyStoredRequestToken',
],
$this->secureRandom,
+ $crypto,
$this->config,
$this->stream
])
@@ -1197,17 +1260,24 @@ class RequestTest extends \Test\TestCase {
}
public function testPassesCSRFCheckWithHeader() {
+ $crypto = $this->getMock('\OCP\Security\ICrypto');
+ $crypto
+ ->expects($this->once())
+ ->method('decrypt')
+ ->with('1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4', 'secret')
+ ->will($this->returnValue('MyStoredRequestToken'));
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
- 'HTTP_REQUESTTOKEN' => 'MyStoredRequestToken',
+ 'HTTP_REQUESTTOKEN' => '1c637c4147e40a8a8f09428ec2059cebea3480c27b402b4e793c69710a731513|wlXxNUaFqHuQnZr5|e6ab49c9e0e20c8d3607e02f1d8e6ec17ad6020ae10b7d64ab4b0a6318c0875940943a6aa303dc090fea0b4cd5b9fb8bcbecac4308a2bd15d9f369cdc22121a4:secret',
],
'requesttoken' => 'MyStoredRequestToken',
],
$this->secureRandom,
+ $crypto,
$this->config,
$this->stream
])
@@ -1216,18 +1286,34 @@ class RequestTest extends \Test\TestCase {
$this->assertTrue($request->passesCSRFCheck());
}
- public function testPassesCSRFCheckWithInvalidToken() {
+ public function invalidTokenDataProvider() {
+ return [
+ ['InvalidSentToken'],
+ ['InvalidSentToken:InvalidSecret'],
+ [null],
+ [''],
+ ];
+ }
+
+ /**
+ * @dataProvider invalidTokenDataProvider
+ * @param string $invalidToken
+ */
+ public function testPassesCSRFCheckWithInvalidToken($invalidToken) {
+ $crypto = new Crypto($this->config, $this->secureRandom);
+
/** @var Request $request */
$request = $this->getMockBuilder('\OC\AppFramework\Http\Request')
->setMethods(['getScriptName'])
->setConstructorArgs([
[
'server' => [
- 'HTTP_REQUESTTOKEN' => 'MyInvalidSentToken',
+ 'HTTP_REQUESTTOKEN' => $invalidToken,
],
'requesttoken' => 'MyStoredRequestToken',
],
$this->secureRandom,
+ $crypto,
$this->config,
$this->stream
])
@@ -1243,6 +1329,7 @@ class RequestTest extends \Test\TestCase {
->setConstructorArgs([
[],
$this->secureRandom,
+ $this->getMock('\OCP\Security\ICrypto'),
$this->config,
$this->stream
])
diff --git a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php
index a8731525798..eab45b03c98 100644
--- a/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php
+++ b/tests/lib/appframework/middleware/MiddlewareDispatcherTest.php
@@ -133,6 +133,7 @@ class MiddlewareDispatcherTest extends \Test\TestCase {
new Request(
['method' => 'GET'],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
)
]
diff --git a/tests/lib/appframework/middleware/MiddlewareTest.php b/tests/lib/appframework/middleware/MiddlewareTest.php
index 33f04e1383d..8e077b37e2f 100644
--- a/tests/lib/appframework/middleware/MiddlewareTest.php
+++ b/tests/lib/appframework/middleware/MiddlewareTest.php
@@ -61,6 +61,7 @@ class MiddlewareTest extends \Test\TestCase {
new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
)
]
diff --git a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
index ca526fb859c..f5e6106dc3a 100644
--- a/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
+++ b/tests/lib/appframework/middleware/security/CORSMiddlewareTest.php
@@ -42,6 +42,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
]
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->reflector->reflect($this, __FUNCTION__);
@@ -61,6 +62,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
]
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
@@ -78,6 +80,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$request = new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->reflector->reflect($this, __FUNCTION__);
@@ -101,6 +104,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
]
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->reflector->reflect($this, __FUNCTION__);
@@ -119,6 +123,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
$request = new Request(
[],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->reflector->reflect($this, __FUNCTION__);
@@ -144,6 +149,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
'PHP_AUTH_PW' => 'pass'
]],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->session->expects($this->once())
@@ -169,6 +175,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
'PHP_AUTH_PW' => 'pass'
]],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->session->expects($this->once())
@@ -190,6 +197,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
'PHP_AUTH_PW' => 'pass'
]],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
@@ -206,6 +214,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
'PHP_AUTH_PW' => 'pass'
]],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
@@ -226,6 +235,7 @@ class CORSMiddlewareTest extends \Test\TestCase {
'PHP_AUTH_PW' => 'pass'
]],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$middleware = new CORSMiddleware($request, $this->reflector, $this->session);
diff --git a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
index 347a0423ea6..3b4d7987e94 100644
--- a/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
+++ b/tests/lib/appframework/middleware/security/SecurityMiddlewareTest.php
@@ -322,6 +322,7 @@ class SecurityMiddlewareTest extends \Test\TestCase {
]
],
$this->getMock('\OCP\Security\ISecureRandom'),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->middleware = $this->getMiddleware(true, true);
diff --git a/tests/lib/appframework/middleware/sessionmiddlewaretest.php b/tests/lib/appframework/middleware/sessionmiddlewaretest.php
index 11c1600f515..06390e96d4c 100644
--- a/tests/lib/appframework/middleware/sessionmiddlewaretest.php
+++ b/tests/lib/appframework/middleware/sessionmiddlewaretest.php
@@ -36,6 +36,7 @@ class SessionMiddlewareTest extends \Test\TestCase {
$this->request = new Request(
[],
$this->getMockBuilder('\OCP\Security\ISecureRandom')->getMock(),
+ $this->getMock('\OCP\Security\ICrypto'),
$this->getMock('\OCP\IConfig')
);
$this->reflector = new ControllerMethodReflector();
diff --git a/tests/lib/backgroundjob/joblist.php b/tests/lib/backgroundjob/joblist.php
index 13bee12479e..d5136676a47 100644
--- a/tests/lib/backgroundjob/joblist.php
+++ b/tests/lib/backgroundjob/joblist.php
@@ -202,4 +202,30 @@ class JobList extends \Test\TestCase {
$this->instance->remove($job);
}
+
+ public function testGetNextNonExisting() {
+ $job = new TestJob();
+ $this->instance->add($job, 1);
+ $this->instance->add('\OC\Non\Existing\Class');
+ $this->instance->add($job, 2);
+
+ $jobs = $this->instance->getAll();
+
+ $savedJob1 = $jobs[count($jobs) - 2];
+ $savedJob2 = $jobs[count($jobs) - 1];
+
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->with('backgroundjob', 'lastjob', 0)
+ ->will($this->returnValue($savedJob1->getId()));
+
+ $this->instance->getNext();
+
+ $nextJob = $this->instance->getNext();
+
+ $this->assertEquals($savedJob2, $nextJob);
+
+ $this->instance->remove($job, 1);
+ $this->instance->remove($job, 2);
+ }
}
diff --git a/tests/lib/connector/sabre/requesttest/requesttest.php b/tests/lib/connector/sabre/requesttest/requesttest.php
index c7739aefcd7..7f33dcf817b 100644
--- a/tests/lib/connector/sabre/requesttest/requesttest.php
+++ b/tests/lib/connector/sabre/requesttest/requesttest.php
@@ -11,22 +11,18 @@ namespace Test\Connector\Sabre\RequestTest;
use OC\Connector\Sabre\Server;
use OC\Connector\Sabre\ServerFactory;
use OC\Files\Mount\MountPoint;
+use OC\Files\Storage\StorageFactory;
use OC\Files\Storage\Temporary;
use OC\Files\View;
use OCP\IUser;
use Sabre\HTTP\Request;
use Test\TestCase;
+use Test\Traits\MountProviderTrait;
+use Test\Traits\UserTrait;
abstract class RequestTest extends TestCase {
- /**
- * @var \OC_User_Dummy
- */
- protected $userBackend;
-
- /**
- * @var \OCP\Files\Config\IMountProvider[]
- */
- protected $mountProviders;
+ use UserTrait;
+ use MountProviderTrait;
/**
* @var \OC\Connector\Sabre\ServerFactory
@@ -40,33 +36,8 @@ abstract class RequestTest extends TestCase {
return $stream;
}
- /**
- * @param $userId
- * @param $storages
- * @return \OCP\Files\Config\IMountProvider
- */
- protected function getMountProvider($userId, $storages) {
- $mounts = [];
- foreach ($storages as $mountPoint => $storage) {
- $mounts[] = new MountPoint($storage, $mountPoint);
- }
- $provider = $this->getMock('\OCP\Files\Config\IMountProvider');
- $provider->expects($this->any())
- ->method('getMountsForUser')
- ->will($this->returnCallback(function (IUser $user) use ($userId, $mounts) {
- if ($user->getUID() === $userId) {
- return $mounts;
- } else {
- return [];
- }
- }));
- return $provider;
- }
-
protected function setUp() {
parent::setUp();
- $this->userBackend = new \OC_User_Dummy();
- \OC::$server->getUserManager()->registerBackend($this->userBackend);
$this->serverFactory = new ServerFactory(
\OC::$server->getConfig(),
@@ -78,16 +49,9 @@ abstract class RequestTest extends TestCase {
);
}
- protected function tearDown() {
- parent::tearDown();
- \OC::$server->getUserManager()->removeBackend($this->userBackend);
- }
-
protected function setupUser($name, $password) {
- $this->userBackend->createUser($name, $password);
- \OC::$server->getMountProviderCollection()->registerProvider($this->getMountProvider($name, [
- '/' . $name => new Temporary()
- ]));
+ $this->createUser($name, $password);
+ $this->registerMount($name, '\OC\Files\Storage\Temporary', '/' . $name);
$this->loginAsUser($name);
return new View('/' . $name . '/files');
}
diff --git a/tests/lib/server.php b/tests/lib/server.php
index 9c5c83ceb5c..bc44c50a22a 100644
--- a/tests/lib/server.php
+++ b/tests/lib/server.php
@@ -56,6 +56,7 @@ class Server extends \Test\TestCase {
['ContactsManager', '\OCP\Contacts\IManager'],
['Crypto', '\OC\Security\Crypto'],
['Crypto', '\OCP\Security\ICrypto'],
+ ['CryptoWrapper', '\OC\Session\CryptoWrapper'],
['DatabaseConnection', '\OC\DB\Connection'],
['DatabaseConnection', '\OCP\IDBConnection'],
diff --git a/tests/lib/session/cryptosessiondatatest.php b/tests/lib/session/cryptosessiondatatest.php
new file mode 100644
index 00000000000..ee6bcbf11c1
--- /dev/null
+++ b/tests/lib/session/cryptosessiondatatest.php
@@ -0,0 +1,53 @@
+<?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 Test\Session;
+
+use OC\Session\CryptoSessionData;
+
+class CryptoSessionDataTest extends Session {
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var \OCP\ISession */
+ protected $wrappedSession;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->wrappedSession = new \OC\Session\Memory($this->getUniqueID());
+ $this->crypto = $this->getMockBuilder('OCP\Security\ICrypto')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->crypto->expects($this->any())
+ ->method('encrypt')
+ ->willReturnCallback(function ($input) {
+ return '#' . $input . '#';
+ });
+ $this->crypto->expects($this->any())
+ ->method('decrypt')
+ ->willReturnCallback(function ($input) {
+ return substr($input, 1, -1);
+ });
+
+ $this->instance = new CryptoSessionData($this->wrappedSession, $this->crypto, 'PASS');
+ }
+}
diff --git a/tests/lib/session/cryptowrappingtest.php b/tests/lib/session/cryptowrappingtest.php
new file mode 100644
index 00000000000..12b3c905b7f
--- /dev/null
+++ b/tests/lib/session/cryptowrappingtest.php
@@ -0,0 +1,82 @@
+<?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 Test\Session;
+
+use OC\Session\CryptoSessionData;
+use Test\TestCase;
+
+class CryptoWrappingTest extends TestCase {
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCP\Security\ICrypto */
+ protected $crypto;
+
+ /** @var \PHPUnit_Framework_MockObject_MockObject|\OCP\ISession */
+ protected $wrappedSession;
+
+ /** @var \OC\Session\CryptoSessionData */
+ protected $instance;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->wrappedSession = $this->getMockBuilder('OCP\ISession')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->crypto = $this->getMockBuilder('OCP\Security\ICrypto')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->crypto->expects($this->any())
+ ->method('encrypt')
+ ->willReturnCallback(function ($input) {
+ return $input;
+ });
+ $this->crypto->expects($this->any())
+ ->method('decrypt')
+ ->willReturnCallback(function ($input) {
+ return substr($input, 1, -1);
+ });
+
+ $this->instance = new CryptoSessionData($this->wrappedSession, $this->crypto, 'PASS');
+ }
+
+ public function testWrappingSet() {
+ $unencryptedValue = 'foobar';
+
+ $this->wrappedSession->expects($this->once())
+ ->method('set')
+ ->with('key', $this->crypto->encrypt(json_encode($unencryptedValue)));
+ $this->instance->set('key', $unencryptedValue);
+ }
+
+ public function testUnwrappingGet() {
+ $unencryptedValue = 'foobar';
+ $encryptedValue = $this->crypto->encrypt($unencryptedValue);
+
+ $this->wrappedSession->expects($this->once())
+ ->method('get')
+ ->with('key')
+ ->willReturnCallback(function () use ($encryptedValue) {
+ return $encryptedValue;
+ });
+
+ $this->assertSame($unencryptedValue, $this->wrappedSession->get('key'));
+ }
+}
diff --git a/tests/lib/testcase.php b/tests/lib/testcase.php
index fd0b8d5f2de..854d5f4f65b 100644
--- a/tests/lib/testcase.php
+++ b/tests/lib/testcase.php
@@ -32,21 +32,52 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase {
*/
private $commandBus;
+ protected function getTestTraits() {
+ $traits = [];
+ $class = $this;
+ do {
+ $traits = array_merge(class_uses($class), $traits);
+ } while ($class = get_parent_class($class));
+ foreach ($traits as $trait => $same) {
+ $traits = array_merge(class_uses($trait), $traits);
+ }
+ $traits = array_unique($traits);
+ return array_filter($traits, function ($trait) {
+ return substr($trait, 0, 5) === 'Test\\';
+ });
+ }
+
protected function setUp() {
// overwrite the command bus with one we can run ourselves
$this->commandBus = new QueueBus();
\OC::$server->registerService('AsyncCommandBus', function () {
return $this->commandBus;
});
+
+ $traits = $this->getTestTraits();
+ foreach ($traits as $trait) {
+ $methodName = 'setUp' . basename(str_replace('\\', '/', $trait));
+ if (method_exists($this, $methodName)) {
+ call_user_func([$this, $methodName]);
+ }
+ }
}
protected function tearDown() {
$hookExceptions = \OC_Hook::$thrownExceptions;
\OC_Hook::$thrownExceptions = [];
\OC::$server->getLockingProvider()->releaseAll();
- if(!empty($hookExceptions)) {
+ if (!empty($hookExceptions)) {
throw $hookExceptions[0];
}
+
+ $traits = $this->getTestTraits();
+ foreach ($traits as $trait) {
+ $methodName = 'tearDown' . basename(str_replace('\\', '/', $trait));
+ if (method_exists($this, $methodName)) {
+ call_user_func([$this, $methodName]);
+ }
+ }
}
/**
diff --git a/tests/lib/traits/mountprovidertrait.php b/tests/lib/traits/mountprovidertrait.php
new file mode 100644
index 00000000000..66eca1597c8
--- /dev/null
+++ b/tests/lib/traits/mountprovidertrait.php
@@ -0,0 +1,56 @@
+<?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\Files\Mount\MountPoint;
+use OC\Files\Storage\StorageFactory;
+use OCP\IUser;
+
+/**
+ * Allow setting mounts for users
+ */
+trait MountProviderTrait {
+ /**
+ * @var \OCP\Files\Config\IMountProvider
+ */
+ protected $mountProvider;
+
+ /**
+ * @var \OC\Files\Storage\StorageFactory
+ */
+ protected $storageFactory;
+
+ protected $mounts = [];
+
+ protected function registerMount($userId, $storage, $mountPoint, $arguments = null) {
+ if (!isset($this->mounts[$userId])) {
+ $this->mounts[$userId] = [];
+ }
+ $this->mounts[$userId][] = new MountPoint($storage, $mountPoint, $arguments, $this->storageFactory);
+ }
+
+ protected function registerStorageWrapper($name, $wrapper) {
+ $this->storageFactory->addStorageWrapper($name, $wrapper);
+ }
+
+ protected function setUpMountProviderTrait() {
+ $this->storageFactory = new StorageFactory();
+ $this->mountProvider = $this->getMock('\OCP\Files\Config\IMountProvider');
+ $this->mountProvider->expects($this->any())
+ ->method('getMountsForUser')
+ ->will($this->returnCallback(function (IUser $user) {
+ if (isset($this->mounts[$user->getUID()])) {
+ return $this->mounts[$user->getUID()];
+ } else {
+ return [];
+ }
+ }));
+ \OC::$server->getMountProviderCollection()->registerProvider($this->mountProvider);
+ }
+}
diff --git a/tests/lib/traits/usertrait.php b/tests/lib/traits/usertrait.php
new file mode 100644
index 00000000000..401d8b8a832
--- /dev/null
+++ b/tests/lib/traits/usertrait.php
@@ -0,0 +1,32 @@
+<?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;
+
+/**
+ * Allow creating users in a temporary backend
+ */
+trait UserTrait {
+ /**
+ * @var \OC_User_Dummy|\OCP\UserInterface
+ */
+ protected $userBackend;
+
+ protected function createUser($name, $password) {
+ $this->userBackend->createUser($name, $password);
+ }
+
+ protected function setUpUserTrait() {
+ $this->userBackend = new \OC_User_Dummy();
+ \OC::$server->getUserManager()->registerBackend($this->userBackend);
+ }
+
+ protected function tearDownUserTrait() {
+ \OC::$server->getUserManager()->removeBackend($this->userBackend);
+ }
+}
diff --git a/tests/lib/util.php b/tests/lib/util.php
index e52a9fcc618..b9b8062653e 100644
--- a/tests/lib/util.php
+++ b/tests/lib/util.php
@@ -91,7 +91,7 @@ class Test_Util extends \Test\TestCase {
function testCallRegister() {
$result = strlen(OC_Util::callRegister());
- $this->assertEquals(30, $result);
+ $this->assertEquals(221, $result);
}
function testSanitizeHTML() {