aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.drone.yml18
-rw-r--r--apps/comments/l10n/ru.js2
-rw-r--r--apps/comments/l10n/ru.json2
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesReportPlugin.php12
-rw-r--r--apps/dav/lib/Files/RootCollection.php1
-rw-r--r--apps/dav/lib/Server.php40
-rw-r--r--apps/federatedfilesharing/l10n/de.js1
-rw-r--r--apps/federatedfilesharing/l10n/de.json1
-rw-r--r--apps/federatedfilesharing/l10n/de_DE.js1
-rw-r--r--apps/federatedfilesharing/l10n/de_DE.json1
-rw-r--r--apps/federatedfilesharing/l10n/fr.js1
-rw-r--r--apps/federatedfilesharing/l10n/fr.json1
-rw-r--r--apps/federation/lib/DAV/FedAuth.php8
-rw-r--r--apps/user_ldap/js/wizard/wizardTabLoginFilter.js2
-rw-r--r--apps/user_ldap/l10n/pt_BR.js2
-rw-r--r--apps/user_ldap/l10n/pt_BR.json2
-rwxr-xr-xautotest-external.sh7
-rw-r--r--build/integration/features/bootstrap/WebDav.php24
-rw-r--r--build/integration/features/webdav-related.feature16
-rw-r--r--core/Command/Integrity/SignApp.php11
-rw-r--r--core/Command/Integrity/SignCore.php12
-rw-r--r--lib/private/IntegrityCheck/Checker.php48
-rw-r--r--lib/private/IntegrityCheck/Helpers/FileAccessHelper.php29
-rw-r--r--settings/l10n/de.js2
-rw-r--r--settings/l10n/de.json2
-rw-r--r--settings/l10n/de_DE.js2
-rw-r--r--settings/l10n/de_DE.json2
-rw-r--r--settings/l10n/fr.js2
-rw-r--r--settings/l10n/fr.json2
-rw-r--r--settings/l10n/it.js1
-rw-r--r--settings/l10n/it.json1
-rw-r--r--tests/Core/Command/TwoFactorAuth/DisableTest.php99
-rw-r--r--tests/Core/Command/TwoFactorAuth/EnableTest.php99
-rw-r--r--tests/lib/Command/Integrity/SignAppTest.php62
-rw-r--r--tests/lib/Command/Integrity/SignCoreTest.php60
-rw-r--r--tests/lib/IntegrityCheck/CheckerTest.php97
-rw-r--r--tests/lib/IntegrityCheck/Helpers/FileAccessHelperTest.php25
-rw-r--r--tests/lib/Memcache/APCuTest.php12
38 files changed, 617 insertions, 93 deletions
diff --git a/.drone.yml b/.drone.yml
index cb43c7d8ba8..821062acc96 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -13,14 +13,14 @@ pipeline:
matrix:
TESTS: jsunit
check-autoloader:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- bash ./build/autoloaderchecker.sh
when:
matrix:
TESTS: check-autoloader
app-check-code:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- ./occ app:check-code admin_audit
- ./occ app:check-code comments
@@ -33,14 +33,14 @@ pipeline:
matrix:
TESTS: app-check-code
signed-off-check:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- php ./build/signed-off-checker.php
when:
matrix:
TESTS: signed-off-check
htaccess-checker:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- php ./build/htaccess-checker.php
when:
@@ -55,7 +55,7 @@ pipeline:
matrix:
TESTS: syntax-php5.6
syntax-php7.0:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- composer install
- ./lib/composer/bin/parallel-lint --exclude lib/composer/jakub-onderka/ --exclude 3rdparty/symfony/polyfill-php70/Resources/stubs/ --exclude 3rdparty/patchwork/utf8/src/Patchwork/Utf8/Bootup/ --exclude 3rdparty/paragonie/random_compat/lib/ --exclude lib/composer/composer/autoload_static.php --exclude 3rdparty/composer/autoload_static.php .
@@ -139,7 +139,7 @@ pipeline:
DB: NODB
PHP: 5.6
nodb-php7.0:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- NOCOVERAGE=true TEST_SELECTION=NODB ./autotest.sh sqlite
when:
@@ -163,7 +163,7 @@ pipeline:
DB: sqlite
PHP: 5.6
sqlite-php7.0:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- NOCOVERAGE=true TEST_SELECTION=DB ./autotest.sh sqlite
when:
@@ -383,7 +383,7 @@ pipeline:
matrix:
TESTS: integration-transfer-ownership-features
nodb-codecov:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- TEST_SELECTION=NODB ./autotest.sh sqlite
- wget https://codecov.io/bash -O codecov.sh
@@ -393,7 +393,7 @@ pipeline:
matrix:
TESTS: nodb-codecov
db-codecov:
- image: nextcloudci/php7.0:php7.0-6
+ image: nextcloudci/php7.0:php7.0-7
commands:
- TEST_SELECTION=QUICKDB ./autotest.sh sqlite
- wget https://codecov.io/bash -O codecov.sh
diff --git a/apps/comments/l10n/ru.js b/apps/comments/l10n/ru.js
index 92ccc845075..650ff5c7d3d 100644
--- a/apps/comments/l10n/ru.js
+++ b/apps/comments/l10n/ru.js
@@ -2,7 +2,7 @@ OC.L10N.register(
"comments",
{
"Comments" : "Комментарии",
- "Unknown user" : "Пользователь неизвестен",
+ "Unknown user" : "Неизвестный пользователь",
"New comment …" : "Новый комментарий...",
"Delete comment" : "Удалить комментарий",
"Post" : "Опубликовать",
diff --git a/apps/comments/l10n/ru.json b/apps/comments/l10n/ru.json
index 18a0e76bb1b..91974f9cdad 100644
--- a/apps/comments/l10n/ru.json
+++ b/apps/comments/l10n/ru.json
@@ -1,6 +1,6 @@
{ "translations": {
"Comments" : "Комментарии",
- "Unknown user" : "Пользователь неизвестен",
+ "Unknown user" : "Неизвестный пользователь",
"New comment …" : "Новый комментарий...",
"Delete comment" : "Удалить комментарий",
"Post" : "Опубликовать",
diff --git a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
index bc0c1c2f603..81c082b9105 100644
--- a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
@@ -24,9 +24,7 @@
namespace OCA\DAV\Connector\Sabre;
use OC\Files\View;
-use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\Exception\PreconditionFailed;
-use Sabre\DAV\Exception\ReportNotSupported;
use Sabre\DAV\Exception\BadRequest;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\Tree;
@@ -105,7 +103,7 @@ class FilesReportPlugin extends ServerPlugin {
* @param ITagManager $fileTagger manager for private tags
* @param IUserSession $userSession
* @param IGroupManager $groupManager
- * @param Folder $userfolder
+ * @param Folder $userFolder
*/
public function __construct(Tree $tree,
View $view,
@@ -161,11 +159,12 @@ class FilesReportPlugin extends ServerPlugin {
* REPORT operations to look for files
*
* @param string $reportName
- * @param [] $report
+ * @param $report
* @param string $uri
* @return bool
- * @throws NotFound
- * @throws ReportNotSupported
+ * @throws BadRequest
+ * @throws PreconditionFailed
+ * @internal param $ [] $report
*/
public function onReport($reportName, $report, $uri) {
$reportTargetNode = $this->server->tree->getNodeForPath($uri);
@@ -232,7 +231,6 @@ class FilesReportPlugin extends ServerPlugin {
private function getFilesBaseUri($uri, $subPath) {
$uri = trim($uri, '/');
$subPath = trim($subPath, '/');
- $filesUri = '';
if (empty($subPath)) {
$filesUri = $uri;
} else {
diff --git a/apps/dav/lib/Files/RootCollection.php b/apps/dav/lib/Files/RootCollection.php
index 345015530e2..c73d7c175ce 100644
--- a/apps/dav/lib/Files/RootCollection.php
+++ b/apps/dav/lib/Files/RootCollection.php
@@ -21,6 +21,7 @@
*/
namespace OCA\DAV\Files;
+use Sabre\DAV\INode;
use Sabre\DAVACL\AbstractPrincipalCollection;
use Sabre\HTTP\URLUtil;
use Sabre\DAV\SimpleCollection;
diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php
index 1205d018241..79c4301a8d8 100644
--- a/apps/dav/lib/Server.php
+++ b/apps/dav/lib/Server.php
@@ -33,11 +33,14 @@ use OCA\DAV\CardDAV\ImageExportPlugin;
use OCA\DAV\Comments\CommentsPlugin;
use OCA\DAV\Connector\Sabre\Auth;
use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
+use OCA\DAV\Connector\Sabre\CommentPropertiesPlugin;
use OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin;
use OCA\DAV\Connector\Sabre\DavAclPlugin;
use OCA\DAV\Connector\Sabre\DummyGetResponsePlugin;
use OCA\DAV\Connector\Sabre\FakeLockerPlugin;
use OCA\DAV\Connector\Sabre\FilesPlugin;
+use OCA\DAV\Connector\Sabre\FilesReportPlugin;
+use OCA\DAV\Connector\Sabre\SharesPlugin;
use OCA\DAV\DAV\PublicAuth;
use OCA\DAV\Connector\Sabre\QuotaPlugin;
use OCA\DAV\Files\BrowserErrorPagePlugin;
@@ -85,7 +88,6 @@ class Server {
$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
$authPlugin = new Plugin();
- $authPlugin->addBackend($authBackend);
$authPlugin->addBackend(new PublicAuth());
$this->server->addPlugin($authPlugin);
@@ -166,7 +168,7 @@ class Server {
// custom properties plugin must be the last one
$userSession = \OC::$server->getUserSession();
$user = $userSession->getUser();
- if (!is_null($user)) {
+ if ($user !== null) {
$view = \OC\Files\Filesystem::getView();
$this->server->addPlugin(
new FilesPlugin(
@@ -188,9 +190,10 @@ class Server {
)
)
);
- $this->server->addPlugin(
- new QuotaPlugin($view)
- );
+ if ($view !== null) {
+ $this->server->addPlugin(
+ new QuotaPlugin($view));
+ }
$this->server->addPlugin(
new TagsPlugin(
$this->server->tree, \OC::$server->getTagManager()
@@ -198,28 +201,29 @@ class Server {
);
// TODO: switch to LazyUserFolder
$userFolder = \OC::$server->getUserFolder();
- $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\SharesPlugin(
+ $this->server->addPlugin(new SharesPlugin(
$this->server->tree,
$userSession,
$userFolder,
\OC::$server->getShareManager()
));
- $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\CommentPropertiesPlugin(
+ $this->server->addPlugin(new CommentPropertiesPlugin(
\OC::$server->getCommentsManager(),
$userSession
));
- $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\FilesReportPlugin(
- $this->server->tree,
- $view,
- \OC::$server->getSystemTagManager(),
- \OC::$server->getSystemTagObjectMapper(),
- \OC::$server->getTagManager(),
- $userSession,
- \OC::$server->getGroupManager(),
- $userFolder
- ));
+ if ($view !== null) {
+ $this->server->addPlugin(new FilesReportPlugin(
+ $this->server->tree,
+ $view,
+ \OC::$server->getSystemTagManager(),
+ \OC::$server->getSystemTagObjectMapper(),
+ \OC::$server->getTagManager(),
+ $userSession,
+ \OC::$server->getGroupManager(),
+ $userFolder
+ ));
+ }
}
- $this->server->addPlugin(new \OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin());
});
}
diff --git a/apps/federatedfilesharing/l10n/de.js b/apps/federatedfilesharing/l10n/de.js
index 335f2c89815..ef4085d222a 100644
--- a/apps/federatedfilesharing/l10n/de.js
+++ b/apps/federatedfilesharing/l10n/de.js
@@ -41,6 +41,7 @@ OC.L10N.register(
"Open documentation" : "Dokumentation öffnen",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Search global and public address book for users" : "Globale Suche und ein öffentliches Adresbuch für Nutzer",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Deine Federated-Cloud-ID:",
"Share it:" : "Zum Teilen:",
diff --git a/apps/federatedfilesharing/l10n/de.json b/apps/federatedfilesharing/l10n/de.json
index e29b867f3b3..4e02478be20 100644
--- a/apps/federatedfilesharing/l10n/de.json
+++ b/apps/federatedfilesharing/l10n/de.json
@@ -39,6 +39,7 @@
"Open documentation" : "Dokumentation öffnen",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Search global and public address book for users" : "Globale Suche und ein öffentliches Adresbuch für Nutzer",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Deine Federated-Cloud-ID:",
"Share it:" : "Zum Teilen:",
diff --git a/apps/federatedfilesharing/l10n/de_DE.js b/apps/federatedfilesharing/l10n/de_DE.js
index 677371b423c..6bb9513d048 100644
--- a/apps/federatedfilesharing/l10n/de_DE.js
+++ b/apps/federatedfilesharing/l10n/de_DE.js
@@ -41,6 +41,7 @@ OC.L10N.register(
"Open documentation" : "Dokumentation öffnen",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Search global and public address book for users" : "Globale Suche und ein öffentliches Adresbuch für Nutzer",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Ihre Federated-Cloud-ID:",
"Share it:" : "Zum Teilen:",
diff --git a/apps/federatedfilesharing/l10n/de_DE.json b/apps/federatedfilesharing/l10n/de_DE.json
index 4451011acaa..6a9be77cda4 100644
--- a/apps/federatedfilesharing/l10n/de_DE.json
+++ b/apps/federatedfilesharing/l10n/de_DE.json
@@ -39,6 +39,7 @@
"Open documentation" : "Dokumentation öffnen",
"Allow users on this server to send shares to other servers" : "Benutzern auf diesem Server das Senden von Freigaben an andere Server erlauben",
"Allow users on this server to receive shares from other servers" : "Benutzern auf diesem Server das Empfangen von Freigaben von anderen Servern erlauben",
+ "Search global and public address book for users" : "Globale Suche und ein öffentliches Adresbuch für Nutzer",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Ihre Federated-Cloud-ID:",
"Share it:" : "Zum Teilen:",
diff --git a/apps/federatedfilesharing/l10n/fr.js b/apps/federatedfilesharing/l10n/fr.js
index 2af16f7274d..4a1d7767965 100644
--- a/apps/federatedfilesharing/l10n/fr.js
+++ b/apps/federatedfilesharing/l10n/fr.js
@@ -41,6 +41,7 @@ OC.L10N.register(
"Open documentation" : "Voir la documentation",
"Allow users on this server to send shares to other servers" : "Autoriser les utilisateurs de ce serveur à envoyer des partages vers d'autres serveurs",
"Allow users on this server to receive shares from other servers" : "Autoriser les utilisateurs de ce serveur à recevoir des partages d'autres serveurs",
+ "Search global and public address book for users" : "Rechercher dans le carnet d'adresse global et public pour les utilisateurs",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Votre identifiant Federated Cloud :",
"Share it:" : "Partager :",
diff --git a/apps/federatedfilesharing/l10n/fr.json b/apps/federatedfilesharing/l10n/fr.json
index cdc9b90113d..670a3bd043c 100644
--- a/apps/federatedfilesharing/l10n/fr.json
+++ b/apps/federatedfilesharing/l10n/fr.json
@@ -39,6 +39,7 @@
"Open documentation" : "Voir la documentation",
"Allow users on this server to send shares to other servers" : "Autoriser les utilisateurs de ce serveur à envoyer des partages vers d'autres serveurs",
"Allow users on this server to receive shares from other servers" : "Autoriser les utilisateurs de ce serveur à recevoir des partages d'autres serveurs",
+ "Search global and public address book for users" : "Rechercher dans le carnet d'adresse global et public pour les utilisateurs",
"Federated Cloud" : "Federated Cloud",
"Your Federated Cloud ID:" : "Votre identifiant Federated Cloud :",
"Share it:" : "Partager :",
diff --git a/apps/federation/lib/DAV/FedAuth.php b/apps/federation/lib/DAV/FedAuth.php
index 705ccbdd3bb..ae78ffeded9 100644
--- a/apps/federation/lib/DAV/FedAuth.php
+++ b/apps/federation/lib/DAV/FedAuth.php
@@ -24,6 +24,8 @@ namespace OCA\Federation\DAV;
use OCA\Federation\DbHandler;
use Sabre\DAV\Auth\Backend\AbstractBasic;
+use Sabre\HTTP\RequestInterface;
+use Sabre\HTTP\ResponseInterface;
class FedAuth extends AbstractBasic {
@@ -57,4 +59,10 @@ class FedAuth extends AbstractBasic {
protected function validateUserPass($username, $password) {
return $this->db->auth($username, $password);
}
+
+ /**
+ * @inheritdoc
+ */
+ function challenge(RequestInterface $request, ResponseInterface $response) {
+ }
}
diff --git a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
index 7b9a408784a..d08a744f9ee 100644
--- a/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
+++ b/apps/user_ldap/js/wizard/wizardTabLoginFilter.js
@@ -148,7 +148,7 @@ OCA = OCA || {};
} else if(usersFound === 1) {
message = t('user_ldap', 'User found and settings verified.');
} else if(usersFound > 1) {
- message = t('user_ldap', 'Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter.');
+ message = t('user_ldap', 'Settings verified, but more than one user found. Only the first will be able to login. Consider a more narrow filter.');
}
} else {
message = t('user_ldap', 'An unspecified error occurred. Please check the settings and the log.');
diff --git a/apps/user_ldap/l10n/pt_BR.js b/apps/user_ldap/l10n/pt_BR.js
index dc4f1b43c71..db1617d02a2 100644
--- a/apps/user_ldap/l10n/pt_BR.js
+++ b/apps/user_ldap/l10n/pt_BR.js
@@ -40,7 +40,7 @@ OC.L10N.register(
"Select attributes" : "Selecione os atributos",
"User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Usuário não encontrado. Por favor verifique os seus atributos de login e nome de usuário. Filtro eficaz (para copiar-e-colar para validação de linha de comando): <br/>",
"User found and settings verified." : "Usuário encontrado e configurações verificadas.",
- "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Configurações verificadas, mas um usuário encontrado. Apenas o primeiro será capaz de fazer login. Considere um filtro mais apurado.",
+ "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Configurações verificadas, mas mais de um usuário foi encontrado. Apenas o primeiro será capaz de fazer login. Considere um filtro mais apurado.",
"An unspecified error occurred. Please check the settings and the log." : "SetAn Ocorreu um erro não especificado. Por favor, verifique as configurações e os log.tings verificadas, mas um usuário encontrado. Apenas o primeiro será capaz de login. Considere um filtro mais apurado.",
"The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "O filtro de pesquisa é inválido, provavelmente devido a questões de sintaxe, como número ímpar de colchetes abertos e fechados. Por favor, revise.",
"A connection error to LDAP / AD occurred, please check host, port and credentials." : "Um erro de conexão para LDAP / AD ocorreu, por favor, verifique host, a porta e as credenciais.",
diff --git a/apps/user_ldap/l10n/pt_BR.json b/apps/user_ldap/l10n/pt_BR.json
index 03ae6313654..94a3f961f4f 100644
--- a/apps/user_ldap/l10n/pt_BR.json
+++ b/apps/user_ldap/l10n/pt_BR.json
@@ -38,7 +38,7 @@
"Select attributes" : "Selecione os atributos",
"User not found. Please check your login attributes and username. Effective filter (to copy-and-paste for command line validation): <br/>" : "Usuário não encontrado. Por favor verifique os seus atributos de login e nome de usuário. Filtro eficaz (para copiar-e-colar para validação de linha de comando): <br/>",
"User found and settings verified." : "Usuário encontrado e configurações verificadas.",
- "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Configurações verificadas, mas um usuário encontrado. Apenas o primeiro será capaz de fazer login. Considere um filtro mais apurado.",
+ "Settings verified, but one user found. Only the first will be able to login. Consider a more narrow filter." : "Configurações verificadas, mas mais de um usuário foi encontrado. Apenas o primeiro será capaz de fazer login. Considere um filtro mais apurado.",
"An unspecified error occurred. Please check the settings and the log." : "SetAn Ocorreu um erro não especificado. Por favor, verifique as configurações e os log.tings verificadas, mas um usuário encontrado. Apenas o primeiro será capaz de login. Considere um filtro mais apurado.",
"The search filter is invalid, probably due to syntax issues like uneven number of opened and closed brackets. Please revise." : "O filtro de pesquisa é inválido, provavelmente devido a questões de sintaxe, como número ímpar de colchetes abertos e fechados. Por favor, revise.",
"A connection error to LDAP / AD occurred, please check host, port and credentials." : "Um erro de conexão para LDAP / AD ocorreu, por favor, verifique host, a porta e as credenciais.",
diff --git a/autotest-external.sh b/autotest-external.sh
index a6ca077ebb0..1f1ca330ac5 100755
--- a/autotest-external.sh
+++ b/autotest-external.sh
@@ -210,16 +210,19 @@ EOF
rm -rf "coverage-external-html-$1-$name"
mkdir "coverage-external-html-$1-$name"
"$PHPUNIT" --configuration phpunit-autotest-external.xml --log-junit "autotest-external-results-$1-$name.xml" --coverage-clover "autotest-external-clover-$1-$name.xml" --coverage-html "coverage-external-html-$1-$name" "$FILES_EXTERNAL_BACKEND_PATH/$testToRun"
- RESULT=$?
else
echo "No coverage"
"$PHPUNIT" --configuration phpunit-autotest-external.xml --log-junit "autotest-external-results-$1-$name.xml" "$FILES_EXTERNAL_BACKEND_PATH/$testToRun"
- RESULT=$?
fi
else
DOEXIT=1
fi
+ if [[ $? -ne 0 ]]; then
+ echo "Error during phpunit execution ... terminating"
+ exit 1
+ fi
+
# calculate stop file
stopFile=`echo "$startFile" | sed 's/start/stop/'`
echo "stop: $stopFile"
diff --git a/build/integration/features/bootstrap/WebDav.php b/build/integration/features/bootstrap/WebDav.php
index c44a6175579..6438a871fb1 100644
--- a/build/integration/features/bootstrap/WebDav.php
+++ b/build/integration/features/bootstrap/WebDav.php
@@ -657,4 +657,28 @@ trait WebDav {
$this->asGetsPropertiesOfFolderWith($user, 'entry', $path, $propertiesTable);
PHPUnit_Framework_Assert::assertNotEquals($this->response['{DAV:}getetag'], $this->storedETAG[$user][$path]);
}
+
+ /**
+ * @When Connecting to dav endpoint
+ */
+ public function connectingToDavEndpoint() {
+ try {
+ $this->response = $this->makeDavRequest(null, 'PROPFIND', '', []);
+ } catch (\GuzzleHttp\Exception\ClientException $e) {
+ $this->response = $e->getResponse();
+ }
+ }
+
+ /**
+ * @Then there are no duplicate headers
+ */
+ public function thereAreNoDuplicateHeaders() {
+ $headers = $this->response->getHeaders();
+ foreach ($headers as $headerName => $headerValues) {
+ // if a header has multiple values, they must be different
+ if (count($headerValues) > 1 && count(array_unique($headerValues)) < count($headerValues)) {
+ throw new \Exception('Duplicate header found: ' . $headerName);
+ }
+ }
+ }
}
diff --git a/build/integration/features/webdav-related.feature b/build/integration/features/webdav-related.feature
index b75fdd35618..c3aa6145527 100644
--- a/build/integration/features/webdav-related.feature
+++ b/build/integration/features/webdav-related.feature
@@ -2,6 +2,22 @@ Feature: webdav-related
Background:
Given using api version "1"
+ Scenario: Unauthenticated call old dav path
+ Given using old dav path
+ When connecting to dav endpoint
+ Then the HTTP status code should be "401"
+ And there are no duplicate headers
+ And The following headers should be set
+ |WWW-Authenticate|Basic realm="Nextcloud"|
+
+ Scenario: Unauthenticated call new dav path
+ Given using new dav path
+ When connecting to dav endpoint
+ Then the HTTP status code should be "401"
+ And there are no duplicate headers
+ And The following headers should be set
+ |WWW-Authenticate|Basic realm="Nextcloud"|
+
Scenario: Moving a file
Given using old dav path
And As an "admin"
diff --git a/core/Command/Integrity/SignApp.php b/core/Command/Integrity/SignApp.php
index 3bc79eb0114..26d2791475b 100644
--- a/core/Command/Integrity/SignApp.php
+++ b/core/Command/Integrity/SignApp.php
@@ -101,8 +101,13 @@ class SignApp extends Command {
$x509 = new X509();
$x509->loadX509($keyBundle);
$x509->setPrivateKey($rsa);
- $this->checker->writeAppSignature($path, $x509, $rsa);
-
- $output->writeln('Successfully signed "'.$path.'"');
+ try {
+ $this->checker->writeAppSignature($path, $x509, $rsa);
+ $output->writeln('Successfully signed "'.$path.'"');
+ } catch (\Exception $e){
+ $output->writeln('Error: ' . $e->getMessage());
+ return 1;
+ }
+ return 0;
}
}
diff --git a/core/Command/Integrity/SignCore.php b/core/Command/Integrity/SignCore.php
index 440c3da3b23..8f951204a58 100644
--- a/core/Command/Integrity/SignCore.php
+++ b/core/Command/Integrity/SignCore.php
@@ -23,12 +23,10 @@
namespace OC\Core\Command\Integrity;
use OC\IntegrityCheck\Checker;
-use OC\IntegrityCheck\Helpers\EnvironmentHelper;
use OC\IntegrityCheck\Helpers\FileAccessHelper;
use phpseclib\Crypt\RSA;
use phpseclib\File\X509;
use Symfony\Component\Console\Command\Command;
-use OCP\IConfig;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@@ -94,8 +92,14 @@ class SignCore extends Command {
$x509 = new X509();
$x509->loadX509($keyBundle);
$x509->setPrivateKey($rsa);
- $this->checker->writeCoreSignature($x509, $rsa, $path);
- $output->writeln('Successfully signed "core"');
+ try {
+ $this->checker->writeCoreSignature($x509, $rsa, $path);
+ $output->writeln('Successfully signed "core"');
+ } catch (\Exception $e){
+ $output->writeln('Error: ' . $e->getMessage());
+ return 1;
+ }
+ return 0;
}
}
diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php
index cba290e6aa7..419f989fa0f 100644
--- a/lib/private/IntegrityCheck/Checker.php
+++ b/lib/private/IntegrityCheck/Checker.php
@@ -267,16 +267,23 @@ class Checker {
public function writeAppSignature($path,
X509 $certificate,
RSA $privateKey) {
- if(!is_dir($path)) {
- throw new \Exception('Directory does not exist.');
- }
- $iterator = $this->getFolderIterator($path);
- $hashes = $this->generateHashes($iterator, $path);
- $signature = $this->createSignatureData($hashes, $certificate, $privateKey);
- $this->fileAccessHelper->file_put_contents(
- $path . '/appinfo/signature.json',
+ $appInfoDir = $path . '/appinfo';
+ try {
+ $this->fileAccessHelper->assertDirectoryExists($appInfoDir);
+
+ $iterator = $this->getFolderIterator($path);
+ $hashes = $this->generateHashes($iterator, $path);
+ $signature = $this->createSignatureData($hashes, $certificate, $privateKey);
+ $this->fileAccessHelper->file_put_contents(
+ $appInfoDir . '/signature.json',
json_encode($signature, JSON_PRETTY_PRINT)
- );
+ );
+ } catch (\Exception $e){
+ if (!$this->fileAccessHelper->is_writable($appInfoDir)) {
+ throw new \Exception($appInfoDir . ' is not writable');
+ }
+ throw $e;
+ }
}
/**
@@ -285,17 +292,28 @@ class Checker {
* @param X509 $certificate
* @param RSA $rsa
* @param string $path
+ * @throws \Exception
*/
public function writeCoreSignature(X509 $certificate,
RSA $rsa,
$path) {
- $iterator = $this->getFolderIterator($path, $path);
- $hashes = $this->generateHashes($iterator, $path);
- $signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
- $this->fileAccessHelper->file_put_contents(
- $path . '/core/signature.json',
+ $coreDir = $path . '/core';
+ try {
+
+ $this->fileAccessHelper->assertDirectoryExists($coreDir);
+ $iterator = $this->getFolderIterator($path, $path);
+ $hashes = $this->generateHashes($iterator, $path);
+ $signatureData = $this->createSignatureData($hashes, $certificate, $rsa);
+ $this->fileAccessHelper->file_put_contents(
+ $coreDir . '/signature.json',
json_encode($signatureData, JSON_PRETTY_PRINT)
- );
+ );
+ } catch (\Exception $e){
+ if (!$this->fileAccessHelper->is_writable($coreDir)) {
+ throw new \Exception($coreDir . ' is not writable');
+ }
+ throw $e;
+ }
}
/**
diff --git a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
index 9e2b76ce11a..a7e378c165e 100644
--- a/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
+++ b/lib/private/IntegrityCheck/Helpers/FileAccessHelper.php
@@ -53,10 +53,33 @@ class FileAccessHelper {
* Wrapper around file_put_contents($filename, $data)
*
* @param string $filename
- * @param $data
- * @return int|false
+ * @param string $data
+ * @return int
+ * @throws \Exception
*/
public function file_put_contents($filename, $data) {
- return file_put_contents($filename, $data);
+ $bytesWritten = @file_put_contents($filename, $data);
+ if ($bytesWritten === false || $bytesWritten !== strlen($data)){
+ throw new \Exception('Failed to write into ' . $filename);
+ }
+ return $bytesWritten;
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function is_writable($path) {
+ return is_writable($path);
+ }
+
+ /**
+ * @param string $path
+ * @throws \Exception
+ */
+ public function assertDirectoryExists($path) {
+ if (!is_dir($path)) {
+ throw new \Exception('Directory ' . $path . ' does not exist.');
+ }
}
}
diff --git a/settings/l10n/de.js b/settings/l10n/de.js
index 95a5eb38343..e99970226ad 100644
--- a/settings/l10n/de.js
+++ b/settings/l10n/de.js
@@ -58,6 +58,7 @@ OC.L10N.register(
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Offizielle Apps werden von und innerhalb der Community entwickelt. Sie stellen die zentralen Funktionen bereit und sind für den produktiven Einsatz geeignet.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Geprüfte Apps werden von vertrauenswürdigen Entwicklern entwickelt und haben eine oberflächliche Sicherheitsprüfung durchlaufen. Sie werden innerhalb eines offenen Code-Repositorys aktiv gepflegt und ihre Betreuer erachten sie als stabil genug für für den gelegentlichen bis normalen Einsatz.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Diese App ist nicht auf Sicherheitsprobleme hin überprüft und ist neu oder bekanntermaßen instabil. Die Installation erfolgt auf eigenes Risiko.",
+ "Enabling app …" : "Aktiviere App ...",
"Error while disabling app" : "Beim Deaktivieren der App ist ein Fehler aufgetreten",
"Disable" : "Deaktivieren",
"Enable" : "Aktivieren",
@@ -246,6 +247,7 @@ OC.L10N.register(
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Für diese App wurde keine obere Versionsgrenze für Nextcloud gesetzt. Dies wird zukünftig als Fehler behandelt.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Die App kann nicht installiert werden, weil die folgenden Abhängigkeiten nicht erfüllt sind:",
"Enable only for specific groups" : "Nur für bestimmte Gruppen aktivieren",
+ "Uninstall app" : "App deinstallieren",
"SSL Root Certificates" : "SSL Root Zertifikate",
"Common Name" : "Allgemeiner Name",
"Valid until" : "Gültig bis",
diff --git a/settings/l10n/de.json b/settings/l10n/de.json
index b165917e537..0d293aeb338 100644
--- a/settings/l10n/de.json
+++ b/settings/l10n/de.json
@@ -56,6 +56,7 @@
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Offizielle Apps werden von und innerhalb der Community entwickelt. Sie stellen die zentralen Funktionen bereit und sind für den produktiven Einsatz geeignet.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Geprüfte Apps werden von vertrauenswürdigen Entwicklern entwickelt und haben eine oberflächliche Sicherheitsprüfung durchlaufen. Sie werden innerhalb eines offenen Code-Repositorys aktiv gepflegt und ihre Betreuer erachten sie als stabil genug für für den gelegentlichen bis normalen Einsatz.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Diese App ist nicht auf Sicherheitsprobleme hin überprüft und ist neu oder bekanntermaßen instabil. Die Installation erfolgt auf eigenes Risiko.",
+ "Enabling app …" : "Aktiviere App ...",
"Error while disabling app" : "Beim Deaktivieren der App ist ein Fehler aufgetreten",
"Disable" : "Deaktivieren",
"Enable" : "Aktivieren",
@@ -244,6 +245,7 @@
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Für diese App wurde keine obere Versionsgrenze für Nextcloud gesetzt. Dies wird zukünftig als Fehler behandelt.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Die App kann nicht installiert werden, weil die folgenden Abhängigkeiten nicht erfüllt sind:",
"Enable only for specific groups" : "Nur für bestimmte Gruppen aktivieren",
+ "Uninstall app" : "App deinstallieren",
"SSL Root Certificates" : "SSL Root Zertifikate",
"Common Name" : "Allgemeiner Name",
"Valid until" : "Gültig bis",
diff --git a/settings/l10n/de_DE.js b/settings/l10n/de_DE.js
index 8e59f2d5b9a..6021ccc58f1 100644
--- a/settings/l10n/de_DE.js
+++ b/settings/l10n/de_DE.js
@@ -58,6 +58,7 @@ OC.L10N.register(
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Offizielle Apps werden von und innerhalb der Community entwickelt. Sie stellen die zentralen Funktionen bereit und sind für den produktiven Einsatz geeignet.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Geprüfte Apps werden von vertrauenswürdigen Entwicklern entwickelt und haben eine oberflächliche Sicherheitsprüfung durchlaufen. Sie werden innerhalb eines offenen Code-Repositorys aktiv gepflegt und ihre Betreuer erachten sie als stabil genug für für den gelegentlichen bis normalen Einsatz.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Diese App ist nicht auf Sicherheitsprobleme hin überprüft und ist neu oder bekanntermaßen instabil. Die Installation erfolgt auf eigenes Risiko.",
+ "Enabling app …" : "Aktiviere App ...",
"Error while disabling app" : "Beim Deaktivieren der App ist ein Fehler aufgetreten",
"Disable" : "Deaktivieren",
"Enable" : "Aktivieren",
@@ -246,6 +247,7 @@ OC.L10N.register(
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Für diese App wurde keine obere Versionsgrenze für Nextcloud gesetzt. Dies wird zukünftig als Fehler behandelt.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Diese App kann nicht installiert werden, weil die folgenden Abhängigkeiten nicht erfüllt sind:",
"Enable only for specific groups" : "Nur für bestimmte Gruppen aktivieren",
+ "Uninstall app" : "App deinstallieren",
"SSL Root Certificates" : "SSL Root Zertifikate",
"Common Name" : "Allgemeiner Name",
"Valid until" : "Gültig bis",
diff --git a/settings/l10n/de_DE.json b/settings/l10n/de_DE.json
index 938fbec8e19..944cb578a87 100644
--- a/settings/l10n/de_DE.json
+++ b/settings/l10n/de_DE.json
@@ -56,6 +56,7 @@
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Offizielle Apps werden von und innerhalb der Community entwickelt. Sie stellen die zentralen Funktionen bereit und sind für den produktiven Einsatz geeignet.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Geprüfte Apps werden von vertrauenswürdigen Entwicklern entwickelt und haben eine oberflächliche Sicherheitsprüfung durchlaufen. Sie werden innerhalb eines offenen Code-Repositorys aktiv gepflegt und ihre Betreuer erachten sie als stabil genug für für den gelegentlichen bis normalen Einsatz.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Diese App ist nicht auf Sicherheitsprobleme hin überprüft und ist neu oder bekanntermaßen instabil. Die Installation erfolgt auf eigenes Risiko.",
+ "Enabling app …" : "Aktiviere App ...",
"Error while disabling app" : "Beim Deaktivieren der App ist ein Fehler aufgetreten",
"Disable" : "Deaktivieren",
"Enable" : "Aktivieren",
@@ -244,6 +245,7 @@
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Für diese App wurde keine obere Versionsgrenze für Nextcloud gesetzt. Dies wird zukünftig als Fehler behandelt.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Diese App kann nicht installiert werden, weil die folgenden Abhängigkeiten nicht erfüllt sind:",
"Enable only for specific groups" : "Nur für bestimmte Gruppen aktivieren",
+ "Uninstall app" : "App deinstallieren",
"SSL Root Certificates" : "SSL Root Zertifikate",
"Common Name" : "Allgemeiner Name",
"Valid until" : "Gültig bis",
diff --git a/settings/l10n/fr.js b/settings/l10n/fr.js
index fba68be5171..3be26c9a8d3 100644
--- a/settings/l10n/fr.js
+++ b/settings/l10n/fr.js
@@ -58,6 +58,7 @@ OC.L10N.register(
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Les applications officielles sont développées par et dans la communauté. Elles offrent les fonctionnalités indispensables et sont prêtes pour être utilisées en production.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Les applications approuvées sont créées par des développeurs de confiance et ont passé les tests de sécurité. Elles sont activement maintenues et leur code source est ouvert. Leurs développeurs les considèrent stables pour une utilisation normale.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Cette application est nouvelle ou instable, et sa sécurité n'a pas été vérifiée. Installez-la à vos risques et périls!",
+ "Enabling app …" : "Activation de l'application...",
"Error while disabling app" : "Erreur lors de la désactivation de l'application",
"Disable" : "Désactiver",
"Enable" : "Activer",
@@ -246,6 +247,7 @@ OC.L10N.register(
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Cette application n'a pas de version maximum Nextcloud exigée. Ce sera considéré comme une erreur à l'avenir.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Cette application ne peut être installée à cause de ces dépendances non satisfaites :",
"Enable only for specific groups" : "Activer uniquement pour certains groupes",
+ "Uninstall app" : "Désinstaller l'application",
"SSL Root Certificates" : "Certificats Racines SSL",
"Common Name" : "Nom d'usage",
"Valid until" : "Valide jusqu'à",
diff --git a/settings/l10n/fr.json b/settings/l10n/fr.json
index 4457cf9f1e8..811a11c892e 100644
--- a/settings/l10n/fr.json
+++ b/settings/l10n/fr.json
@@ -56,6 +56,7 @@
"Official apps are developed by and within the community. They offer central functionality and are ready for production use." : "Les applications officielles sont développées par et dans la communauté. Elles offrent les fonctionnalités indispensables et sont prêtes pour être utilisées en production.",
"Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use." : "Les applications approuvées sont créées par des développeurs de confiance et ont passé les tests de sécurité. Elles sont activement maintenues et leur code source est ouvert. Leurs développeurs les considèrent stables pour une utilisation normale.",
"This app is not checked for security issues and is new or known to be unstable. Install at your own risk." : "Cette application est nouvelle ou instable, et sa sécurité n'a pas été vérifiée. Installez-la à vos risques et périls!",
+ "Enabling app …" : "Activation de l'application...",
"Error while disabling app" : "Erreur lors de la désactivation de l'application",
"Disable" : "Désactiver",
"Enable" : "Activer",
@@ -244,6 +245,7 @@
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Cette application n'a pas de version maximum Nextcloud exigée. Ce sera considéré comme une erreur à l'avenir.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Cette application ne peut être installée à cause de ces dépendances non satisfaites :",
"Enable only for specific groups" : "Activer uniquement pour certains groupes",
+ "Uninstall app" : "Désinstaller l'application",
"SSL Root Certificates" : "Certificats Racines SSL",
"Common Name" : "Nom d'usage",
"Valid until" : "Valide jusqu'à",
diff --git a/settings/l10n/it.js b/settings/l10n/it.js
index b5f0f7edc65..2ec92202fc5 100644
--- a/settings/l10n/it.js
+++ b/settings/l10n/it.js
@@ -246,6 +246,7 @@ OC.L10N.register(
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Questa applicazione non contiene l'informazione della versione massima di Nextcloud richiesta. In futuro ciò sarà considerato un errore.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Questa applicazione non può essere installata perché le seguenti dipendenze non sono soddisfatte:",
"Enable only for specific groups" : "Abilita solo per gruppi specifici",
+ "Uninstall app" : "Disinstalla applicazione",
"SSL Root Certificates" : "Certificati radice SSL",
"Common Name" : "Nome comune",
"Valid until" : "Valido fino al",
diff --git a/settings/l10n/it.json b/settings/l10n/it.json
index 88580507c62..d6bdce4809c 100644
--- a/settings/l10n/it.json
+++ b/settings/l10n/it.json
@@ -244,6 +244,7 @@
"This app has no maximum Nextcloud version assigned. This will be an error in the future." : "Questa applicazione non contiene l'informazione della versione massima di Nextcloud richiesta. In futuro ciò sarà considerato un errore.",
"This app cannot be installed because the following dependencies are not fulfilled:" : "Questa applicazione non può essere installata perché le seguenti dipendenze non sono soddisfatte:",
"Enable only for specific groups" : "Abilita solo per gruppi specifici",
+ "Uninstall app" : "Disinstalla applicazione",
"SSL Root Certificates" : "Certificati radice SSL",
"Common Name" : "Nome comune",
"Valid until" : "Valido fino al",
diff --git a/tests/Core/Command/TwoFactorAuth/DisableTest.php b/tests/Core/Command/TwoFactorAuth/DisableTest.php
new file mode 100644
index 00000000000..1a0bbc6c3d3
--- /dev/null
+++ b/tests/Core/Command/TwoFactorAuth/DisableTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace Test\Core\Command\TwoFactorAuth;
+
+use OC\Authentication\TwoFactorAuth\Manager;
+use OC\Core\Command\TwoFactorAuth\Disable;
+use OCP\IUser;
+use OCP\IUserManager;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class DisableTest extends TestCase {
+
+ /** @var Manager|\PHPUnit_Framework_MockObject_MockObject */
+ private $manager;
+
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $userManager;
+
+ /** @var Disable */
+ private $command;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->manager = $this->createMock(Manager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+
+ $this->command = new Disable($this->manager, $this->userManager);
+ }
+
+ public function testDisableSuccess() {
+ $user = $this->createMock(IUser::class);
+
+ $input = $this->createMock(InputInterface::class);
+ $output = $this->createMock(OutputInterface::class);
+
+ $input->method('getArgument')
+ ->with($this->equalTo('uid'))
+ ->willReturn('user');
+
+ $this->userManager->method('get')
+ ->with('user')
+ ->willReturn($user);
+
+ $this->manager->expects($this->once())
+ ->method('disableTwoFactorAuthentication')
+ ->with($this->equalTo($user));
+
+ $output->expects($this->once())
+ ->method('writeln')
+ ->with('Two-factor authentication disabled for user user');
+
+ $this->invokePrivate($this->command, 'execute', [$input, $output]);
+ }
+
+ public function testEnableFail() {
+ $input = $this->createMock(InputInterface::class);
+ $output = $this->createMock(OutputInterface::class);
+
+ $input->method('getArgument')
+ ->with($this->equalTo('uid'))
+ ->willReturn('user');
+
+ $this->userManager->method('get')
+ ->with('user')
+ ->willReturn(null);
+
+ $this->manager->expects($this->never())
+ ->method($this->anything());
+
+ $output->expects($this->once())
+ ->method('writeln')
+ ->with('<error>Invalid UID</error>');
+
+ $this->invokePrivate($this->command, 'execute', [$input, $output]);
+ }
+}
diff --git a/tests/Core/Command/TwoFactorAuth/EnableTest.php b/tests/Core/Command/TwoFactorAuth/EnableTest.php
new file mode 100644
index 00000000000..ebca40df9a5
--- /dev/null
+++ b/tests/Core/Command/TwoFactorAuth/EnableTest.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace Test\Core\Command\TwoFactorAuth;
+
+use OC\Authentication\TwoFactorAuth\Manager;
+use OC\Core\Command\TwoFactorAuth\Enable;
+use OCP\IUser;
+use OCP\IUserManager;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Test\TestCase;
+
+class EnableTest extends TestCase {
+
+ /** @var Manager|\PHPUnit_Framework_MockObject_MockObject */
+ private $manager;
+
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $userManager;
+
+ /** @var Enable */
+ private $command;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->manager = $this->createMock(Manager::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+
+ $this->command = new Enable($this->manager, $this->userManager);
+ }
+
+ public function testEnableSuccess() {
+ $user = $this->createMock(IUser::class);
+
+ $input = $this->createMock(InputInterface::class);
+ $output = $this->createMock(OutputInterface::class);
+
+ $input->method('getArgument')
+ ->with($this->equalTo('uid'))
+ ->willReturn('user');
+
+ $this->userManager->method('get')
+ ->with('user')
+ ->willReturn($user);
+
+ $this->manager->expects($this->once())
+ ->method('enableTwoFactorAuthentication')
+ ->with($this->equalTo($user));
+
+ $output->expects($this->once())
+ ->method('writeln')
+ ->with('Two-factor authentication enabled for user user');
+
+ $this->invokePrivate($this->command, 'execute', [$input, $output]);
+ }
+
+ public function testEnableFail() {
+ $input = $this->createMock(InputInterface::class);
+ $output = $this->createMock(OutputInterface::class);
+
+ $input->method('getArgument')
+ ->with($this->equalTo('uid'))
+ ->willReturn('user');
+
+ $this->userManager->method('get')
+ ->with('user')
+ ->willReturn(null);
+
+ $this->manager->expects($this->never())
+ ->method($this->anything());
+
+ $output->expects($this->once())
+ ->method('writeln')
+ ->with('<error>Invalid UID</error>');
+
+ $this->invokePrivate($this->command, 'execute', [$input, $output]);
+ }
+}
diff --git a/tests/lib/Command/Integrity/SignAppTest.php b/tests/lib/Command/Integrity/SignAppTest.php
index 71d9946ee88..013290b56e9 100644
--- a/tests/lib/Command/Integrity/SignAppTest.php
+++ b/tests/lib/Command/Integrity/SignAppTest.php
@@ -29,13 +29,13 @@ use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
class SignAppTest extends TestCase {
- /** @var Checker */
+ /** @var Checker|\PHPUnit_Framework_MockObject_MockObject */
private $checker;
/** @var SignApp */
private $signApp;
- /** @var FileAccessHelper */
+ /** @var FileAccessHelper|\PHPUnit_Framework_MockObject_MockObject */
private $fileAccessHelper;
- /** @var IURLGenerator */
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
private $urlGenerator;
public function setUp() {
@@ -75,7 +75,7 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('This command requires the --path, --privateKey and --certificate.');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithMissingPrivateKey() {
@@ -103,7 +103,7 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('This command requires the --path, --privateKey and --certificate.');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithMissingCertificate() {
@@ -131,7 +131,7 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('This command requires the --path, --privateKey and --certificate.');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithNotExistingPrivateKey() {
@@ -165,7 +165,7 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('Private key "privateKey" does not exists.');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithNotExistingCertificate() {
@@ -204,7 +204,51 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('Certificate "certificate" does not exists.');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
+ }
+
+ public function testExecuteWithException() {
+ $inputInterface = $this->createMock(InputInterface::class);
+ $outputInterface = $this->createMock(OutputInterface::class);
+
+ $inputInterface
+ ->expects($this->at(0))
+ ->method('getOption')
+ ->with('path')
+ ->will($this->returnValue('AppId'));
+ $inputInterface
+ ->expects($this->at(1))
+ ->method('getOption')
+ ->with('privateKey')
+ ->will($this->returnValue('privateKey'));
+ $inputInterface
+ ->expects($this->at(2))
+ ->method('getOption')
+ ->with('certificate')
+ ->will($this->returnValue('certificate'));
+
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('file_get_contents')
+ ->with('privateKey')
+ ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('file_get_contents')
+ ->with('certificate')
+ ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.crt'));
+
+ $this->checker
+ ->expects($this->once())
+ ->method('writeAppSignature')
+ ->willThrowException(new \Exception('My error message'));
+
+ $outputInterface
+ ->expects($this->at(0))
+ ->method('writeln')
+ ->with('Error: My error message');
+
+ $this->assertSame(1, self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecute() {
@@ -247,6 +291,6 @@ class SignAppTest extends TestCase {
->method('writeln')
->with('Successfully signed "AppId"');
- $this->invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertSame(0, self::invokePrivate($this->signApp, 'execute', [$inputInterface, $outputInterface]));
}
}
diff --git a/tests/lib/Command/Integrity/SignCoreTest.php b/tests/lib/Command/Integrity/SignCoreTest.php
index f3c242ae9fb..35e52b951da 100644
--- a/tests/lib/Command/Integrity/SignCoreTest.php
+++ b/tests/lib/Command/Integrity/SignCoreTest.php
@@ -28,12 +28,12 @@ use Symfony\Component\Console\Output\OutputInterface;
use Test\TestCase;
class SignCoreTest extends TestCase {
- /** @var Checker */
+ /** @var Checker|\PHPUnit_Framework_MockObject_MockObject */
private $checker;
+ /** @var FileAccessHelper|\PHPUnit_Framework_MockObject_MockObject */
+ private $fileAccessHelper;
/** @var SignCore */
private $signCore;
- /** @var FileAccessHelper */
- private $fileAccessHelper;
public function setUp() {
parent::setUp();
@@ -65,7 +65,7 @@ class SignCoreTest extends TestCase {
->method('writeln')
->with('--privateKey, --certificate and --path are required.');
- $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithMissingCertificate() {
@@ -88,7 +88,7 @@ class SignCoreTest extends TestCase {
->method('writeln')
->with('--privateKey, --certificate and --path are required.');
- $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithNotExistingPrivateKey() {
@@ -122,7 +122,7 @@ class SignCoreTest extends TestCase {
->method('writeln')
->with('Private key "privateKey" does not exists.');
- $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecuteWithNotExistingCertificate() {
@@ -161,7 +161,51 @@ class SignCoreTest extends TestCase {
->method('writeln')
->with('Certificate "certificate" does not exists.');
- $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertNull(self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
+ }
+
+ public function testExecuteWithException() {
+ $inputInterface = $this->createMock(InputInterface::class);
+ $outputInterface = $this->createMock(OutputInterface::class);
+
+ $inputInterface
+ ->expects($this->at(0))
+ ->method('getOption')
+ ->with('privateKey')
+ ->will($this->returnValue('privateKey'));
+ $inputInterface
+ ->expects($this->at(1))
+ ->method('getOption')
+ ->with('certificate')
+ ->will($this->returnValue('certificate'));
+ $inputInterface
+ ->expects($this->at(2))
+ ->method('getOption')
+ ->with('path')
+ ->will($this->returnValue('certificate'));
+
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('file_get_contents')
+ ->with('privateKey')
+ ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.key'));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('file_get_contents')
+ ->with('certificate')
+ ->will($this->returnValue(\OC::$SERVERROOT . '/tests/data/integritycheck/core.crt'));
+
+ $this->checker
+ ->expects($this->once())
+ ->method('writeCoreSignature')
+ ->willThrowException(new \Exception('My exception message'));
+
+ $outputInterface
+ ->expects($this->at(0))
+ ->method('writeln')
+ ->with('Error: My exception message');
+
+ $this->assertEquals(1, self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
}
public function testExecute() {
@@ -204,6 +248,6 @@ class SignCoreTest extends TestCase {
->method('writeln')
->with('Successfully signed "core"');
- $this->invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]);
+ $this->assertEquals(0, self::invokePrivate($this->signCore, 'execute', [$inputInterface, $outputInterface]));
}
}
diff --git a/tests/lib/IntegrityCheck/CheckerTest.php b/tests/lib/IntegrityCheck/CheckerTest.php
index 0e6bd52a5df..049017cb5e8 100644
--- a/tests/lib/IntegrityCheck/CheckerTest.php
+++ b/tests/lib/IntegrityCheck/CheckerTest.php
@@ -34,19 +34,19 @@ use OCP\ICacheFactory;
use OCP\App\IAppManager;
class CheckerTest extends TestCase {
- /** @var EnvironmentHelper */
+ /** @var EnvironmentHelper|\PHPUnit_Framework_MockObject_MockObject */
private $environmentHelper;
- /** @var AppLocator */
+ /** @var AppLocator|\PHPUnit_Framework_MockObject_MockObject */
private $appLocator;
/** @var Checker */
private $checker;
- /** @var FileAccessHelper */
+ /** @var FileAccessHelper|\PHPUnit_Framework_MockObject_MockObject */
private $fileAccessHelper;
- /** @var IConfig */
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
private $config;
- /** @var ICacheFactory */
+ /** @var ICacheFactory|\PHPUnit_Framework_MockObject_MockObject */
private $cacheFactory;
- /** @var IAppManager */
+ /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
private $appManager;
public function setUp() {
@@ -77,9 +77,20 @@ class CheckerTest extends TestCase {
/**
* @expectedException \Exception
- * @expectedExceptionMessage Directory does not exist.
+ * @expectedExceptionMessage Exception message
*/
public function testWriteAppSignatureOfNotExistingApp() {
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('assertDirectoryExists')
+ ->with('NotExistingApp/appinfo')
+ ->willThrowException(new \Exception('Exception message'));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('is_writable')
+ ->with('NotExistingApp/appinfo')
+ ->willReturn(true);
+
$keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
$rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
$rsa = new RSA();
@@ -89,6 +100,25 @@ class CheckerTest extends TestCase {
$this->checker->writeAppSignature('NotExistingApp', $x509, $rsa);
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessageRegExp /[a-zA-Z\/_-]+ is not writable/
+ */
+ public function testWriteAppSignatureWrongPermissions() {
+ $this->fileAccessHelper
+ ->expects($this->once())
+ ->method('file_put_contents')
+ ->will($this->throwException(new \Exception('Exception message')));
+
+ $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
+ $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
+ $rsa = new RSA();
+ $rsa->loadKey($rsaPrivateKey);
+ $x509 = new X509();
+ $x509->loadX509($keyBundle);
+ $this->checker->writeAppSignature(\OC::$SERVERROOT . '/tests/data/integritycheck/app/', $x509, $rsa);
+ }
+
public function testWriteAppSignature() {
$expectedSignatureFileData = '{
"hashes": {
@@ -443,6 +473,54 @@ class CheckerTest extends TestCase {
$this->assertSame([], $this->checker->verifyAppSignature('SomeApp'));
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Exception message
+ */
+ public function testWriteCoreSignatureWithException() {
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('assertDirectoryExists')
+ ->will($this->throwException(new \Exception('Exception message')));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('is_writable')
+ ->with(__DIR__ . '/core')
+ ->willReturn(true);
+
+ $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
+ $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
+ $rsa = new RSA();
+ $rsa->loadKey($rsaPrivateKey);
+ $x509 = new X509();
+ $x509->loadX509($keyBundle);
+ $this->checker->writeCoreSignature($x509, $rsa, __DIR__);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessageRegExp /[a-zA-Z\/_-]+ is not writable/
+ */
+ public function testWriteCoreSignatureWrongPermissions() {
+ $this->fileAccessHelper
+ ->expects($this->at(0))
+ ->method('assertDirectoryExists')
+ ->will($this->throwException(new \Exception('Exception message')));
+ $this->fileAccessHelper
+ ->expects($this->at(1))
+ ->method('is_writable')
+ ->with(__DIR__ . '/core')
+ ->willReturn(false);
+
+ $keyBundle = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.crt');
+ $rsaPrivateKey = file_get_contents(__DIR__ .'/../../data/integritycheck/SomeApp.key');
+ $rsa = new RSA();
+ $rsa->loadKey($rsaPrivateKey);
+ $x509 = new X509();
+ $x509->loadX509($keyBundle);
+ $this->checker->writeCoreSignature($x509, $rsa, __DIR__);
+ }
+
public function testWriteCoreSignature() {
$expectedSignatureFileData = '{
"hashes": {
@@ -948,7 +1026,7 @@ class CheckerTest extends TestCase {
->method('verifyCoreSignature');
$this->appLocator
->expects($this->at(0))
- ->Method('getAllApps')
+ ->method('getAllApps')
->will($this->returnValue([
'files',
'calendar',
@@ -1074,7 +1152,6 @@ class CheckerTest extends TestCase {
->with('integrity.check.disabled', false)
->will($this->returnValue(true));
- $result = $this->invokePrivate($this->checker, 'isCodeCheckEnforced');
- $this->assertSame(false, $result);
+ $this->assertFalse(self::invokePrivate($this->checker, 'isCodeCheckEnforced'));
}
}
diff --git a/tests/lib/IntegrityCheck/Helpers/FileAccessHelperTest.php b/tests/lib/IntegrityCheck/Helpers/FileAccessHelperTest.php
index 740b14e61c4..de4aeec78cc 100644
--- a/tests/lib/IntegrityCheck/Helpers/FileAccessHelperTest.php
+++ b/tests/lib/IntegrityCheck/Helpers/FileAccessHelperTest.php
@@ -40,4 +40,29 @@ class FileAccessHelperTest extends TestCase {
$this->fileAccessHelper->file_put_contents($filePath, $data);
$this->assertSame($data, $this->fileAccessHelper->file_get_contents($filePath));
}
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Failed to write into /anabsolutelynotexistingfolder/on/the/system.txt
+ */
+ public function testFile_put_contentsWithException() {
+ $this->fileAccessHelper->file_put_contents('/anabsolutelynotexistingfolder/on/the/system.txt', 'MyFiles');
+ }
+
+ public function testIs_writable() {
+ $this->assertFalse($this->fileAccessHelper->is_writable('/anabsolutelynotexistingfolder/on/the/system.txt'));
+ $this->assertTrue($this->fileAccessHelper->is_writable(\OC::$server->getTempManager()->getTemporaryFile('MyFile')));
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Directory /anabsolutelynotexistingfolder/on/the/system does not exist.
+ */
+ public function testAssertDirectoryExistsWithException() {
+ $this->fileAccessHelper->assertDirectoryExists('/anabsolutelynotexistingfolder/on/the/system');
+ }
+
+ public function testAssertDirectoryExists() {
+ $this->fileAccessHelper->assertDirectoryExists(\OC::$server->getTempManager()->getTemporaryFolder('/testfolder/'));
+ }
}
diff --git a/tests/lib/Memcache/APCuTest.php b/tests/lib/Memcache/APCuTest.php
index 73fd5a12880..41de75a8ea8 100644
--- a/tests/lib/Memcache/APCuTest.php
+++ b/tests/lib/Memcache/APCuTest.php
@@ -19,4 +19,16 @@ class APCuTest extends Cache {
}
$this->instance=new \OC\Memcache\APCu($this->getUniqueID());
}
+
+ public function testCasIntChanged() {
+ $this->instance->set('foo', 1);
+ $this->assertTrue($this->instance->cas('foo', 1, 2));
+ $this->assertEquals(2, $this->instance->get('foo'));
+ }
+
+ public function testCasIntNotChanged() {
+ $this->instance->set('foo', 1);
+ $this->assertFalse($this->instance->cas('foo', 2, 3));
+ $this->assertEquals(1, $this->instance->get('foo'));
+ }
}