summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/comments/js/commentstabview.js2
-rw-r--r--apps/dav/lib/Connector/Sabre/FilesPlugin.php9
-rw-r--r--apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php6
-rw-r--r--apps/federatedfilesharing/appinfo/routes.php11
-rw-r--r--apps/federatedfilesharing/lib/AppInfo/Application.php34
-rw-r--r--apps/federatedfilesharing/lib/Controller/RequestHandlerController.php (renamed from apps/federatedfilesharing/lib/RequestHandler.php)169
-rw-r--r--apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php (renamed from apps/federatedfilesharing/tests/RequestHandlerTest.php)40
-rw-r--r--apps/files/js/filelist.js16
-rw-r--r--apps/files/js/filesummary.js92
-rw-r--r--apps/files/lib/Command/Scan.php27
-rw-r--r--apps/files/tests/js/filelistSpec.js104
-rw-r--r--apps/files/tests/js/filesummarySpec.js74
-rw-r--r--apps/files_sharing/lib/sharedstorage.php10
-rw-r--r--apps/theming/lib/Controller/ThemingController.php24
-rw-r--r--apps/theming/lib/Settings/Admin.php2
-rw-r--r--apps/theming/tests/Controller/ThemingControllerTest.php88
-rw-r--r--apps/theming/tests/Settings/AdminTest.php6
-rw-r--r--apps/user_ldap/ajax/getConfiguration.php7
-rw-r--r--apps/user_ldap/ajax/testConfiguration.php16
-rw-r--r--apps/user_ldap/js/wizard/configModel.js2
-rw-r--r--apps/user_ldap/js/wizard/view.js2
21 files changed, 539 insertions, 202 deletions
diff --git a/apps/comments/js/commentstabview.js b/apps/comments/js/commentstabview.js
index 9451e828f91..eae18c1d485 100644
--- a/apps/comments/js/commentstabview.js
+++ b/apps/comments/js/commentstabview.js
@@ -32,7 +32,7 @@
'{{/if}}' +
' </div>' +
' <form class="newCommentForm">' +
- ' <input type="text" class="message" placeholder="{{newMessagePlaceholder}}" value="{{{message}}}" />' +
+ ' <input type="text" class="message" placeholder="{{newMessagePlaceholder}}" value="{{message}}" />' +
' <input class="submit icon-confirm" type="submit" value="" />' +
'{{#if isEditMode}}' +
' <input class="cancel pull-right" type="button" value="{{cancelText}}" />' +
diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
index c472f75b6bf..dd5f958ed4c 100644
--- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php
@@ -324,18 +324,13 @@ class FilesPlugin extends ServerPlugin {
return $displayName;
});
- $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
- if ($node->getPath() === '/') {
- return $this->config->getSystemValue('data-fingerprint', '');
- }
- });
-
$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
});
}
- if ($node instanceof \OCA\DAV\Files\FilesHome) {
+ if ($node instanceof \OCA\DAV\Connector\Sabre\Node
+ || $node instanceof \OCA\DAV\Files\FilesHome) {
$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
return $this->config->getSystemValue('data-fingerprint', '');
});
diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
index 6630c027541..e2d63868af0 100644
--- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
+++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php
@@ -213,7 +213,8 @@ class FilesPluginTest extends TestCase {
$this->assertEquals('http://example.com/', $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
$this->assertEquals('foo', $propFind->get(self::OWNER_ID_PROPERTYNAME));
$this->assertEquals('M. Foo', $propFind->get(self::OWNER_DISPLAY_NAME_PROPERTYNAME));
- $this->assertEquals([self::SIZE_PROPERTYNAME, self::DATA_FINGERPRINT_PROPERTYNAME], $propFind->get404Properties());
+ $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
+ $this->assertEquals([self::SIZE_PROPERTYNAME], $propFind->get404Properties());
}
public function testGetPropertiesForFileHome() {
@@ -357,7 +358,8 @@ class FilesPluginTest extends TestCase {
$this->assertEquals(1025, $propFind->get(self::SIZE_PROPERTYNAME));
$this->assertEquals('DWCKMSR', $propFind->get(self::PERMISSIONS_PROPERTYNAME));
$this->assertEquals(null, $propFind->get(self::DOWNLOADURL_PROPERTYNAME));
- $this->assertEquals([self::DOWNLOADURL_PROPERTYNAME, self::DATA_FINGERPRINT_PROPERTYNAME], $propFind->get404Properties());
+ $this->assertEquals('my_fingerprint', $propFind->get(self::DATA_FINGERPRINT_PROPERTYNAME));
+ $this->assertEquals([self::DOWNLOADURL_PROPERTYNAME], $propFind->get404Properties());
}
public function testGetPropertiesForRootDirectory() {
diff --git a/apps/federatedfilesharing/appinfo/routes.php b/apps/federatedfilesharing/appinfo/routes.php
index a4f56e372c9..9caaa939348 100644
--- a/apps/federatedfilesharing/appinfo/routes.php
+++ b/apps/federatedfilesharing/appinfo/routes.php
@@ -26,5 +26,14 @@ return [
'routes' => [
['name' => 'MountPublicLink#createFederatedShare', 'url' => '/createFederatedShare', 'verb' => 'POST'],
['name' => 'MountPublicLink#askForFederatedShare', 'url' => '/askForFederatedShare', 'verb' => 'POST'],
- ]
+ ],
+ 'ocs' => [
+ ['root' => '/cloud', 'name' => 'RequestHandler#createShare', 'url' => '/shares', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#reShare', 'url' => '/shares/{id}/reshare', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#updatePermissions', 'url' => '/shares/{id}/permissions', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#acceptShare', 'url' => '/shares/{id}/accept', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#declineShare', 'url' => '/shares/{id}/decline', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#unshare', 'url' => '/shares/{id}/unshare', 'verb' => 'POST'],
+ ['root' => '/cloud', 'name' => 'RequestHandler#revoke', 'url' => '/shares/{id}/revoke', 'verb' => 'POST'],
+ ],
];
diff --git a/apps/federatedfilesharing/lib/AppInfo/Application.php b/apps/federatedfilesharing/lib/AppInfo/Application.php
index b767a322505..b470bb3e584 100644
--- a/apps/federatedfilesharing/lib/AppInfo/Application.php
+++ b/apps/federatedfilesharing/lib/AppInfo/Application.php
@@ -24,7 +24,12 @@
namespace OCA\FederatedFileSharing\AppInfo;
+use OC\AppFramework\Utility\SimpleContainer;
+use OCA\FederatedFileSharing\AddressHandler;
+use OCA\FederatedFileSharing\Controller\RequestHandlerController;
use OCA\FederatedFileSharing\FederatedShareProvider;
+use OCA\FederatedFileSharing\Notifications;
+use OCA\FederatedFileSharing\RequestHandler;
use OCP\AppFramework\App;
class Application extends App {
@@ -34,6 +39,35 @@ class Application extends App {
public function __construct() {
parent::__construct('federatedfilesharing');
+
+ $container = $this->getContainer();
+ $server = $container->getServer();
+
+ $container->registerService('RequestHandlerController', function(SimpleContainer $c) use ($server) {
+ $addressHandler = new AddressHandler(
+ $server->getURLGenerator(),
+ $server->getL10N('federatedfilesharing')
+ );
+ $notification = new Notifications(
+ $addressHandler,
+ $server->getHTTPClientService(),
+ new \OCA\FederatedFileSharing\DiscoveryManager(
+ $server->getMemCacheFactory(),
+ $server->getHTTPClientService()
+ ),
+ \OC::$server->getJobList()
+ );
+ return new RequestHandlerController(
+ $c->query('AppName'),
+ $server->getRequest(),
+ $this->getFederatedShareProvider(),
+ $server->getDatabaseConnection(),
+ $server->getShareManager(),
+ $notification,
+ $addressHandler,
+ $server->getUserManager()
+ );
+ });
}
/**
diff --git a/apps/federatedfilesharing/lib/RequestHandler.php b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
index f531c7bcb4a..9a41962ee3a 100644
--- a/apps/federatedfilesharing/lib/RequestHandler.php
+++ b/apps/federatedfilesharing/lib/Controller/RequestHandlerController.php
@@ -24,25 +24,28 @@
*
*/
-namespace OCA\FederatedFileSharing;
+namespace OCA\FederatedFileSharing\Controller;
+use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\Files_Sharing\Activity;
+use OCA\FederatedFileSharing\AddressHandler;
+use OCA\FederatedFileSharing\FederatedShareProvider;
+use OCA\FederatedFileSharing\Notifications;
use OCP\AppFramework\Http;
+use OCP\AppFramework\OCS\OCSBadRequestException;
+use OCP\AppFramework\OCS\OCSException;
+use OCP\AppFramework\OCS\OCSForbiddenException;
+use OCP\AppFramework\OCS\OCSNotFoundException;
+use OCP\AppFramework\OCSController;
use OCP\Constants;
use OCP\Files\NotFoundException;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUserManager;
use OCP\Share;
+use OCP\Share\IShare;
-/**
- * Class RequestHandler
- *
- * handles OCS Request to the federated share API
- *
- * @package OCA\FederatedFileSharing\API
- */
-class RequestHandler {
+class RequestHandlerController extends OCSController {
/** @var FederatedShareProvider */
private $federatedShareProvider;
@@ -53,9 +56,6 @@ class RequestHandler {
/** @var Share\IManager */
private $shareManager;
- /** @var IRequest */
- private $request;
-
/** @var Notifications */
private $notifications;
@@ -71,41 +71,47 @@ class RequestHandler {
/**
* Server2Server constructor.
*
+ * @param string $appName
+ * @param IRequest $request
* @param FederatedShareProvider $federatedShareProvider
* @param IDBConnection $connection
* @param Share\IManager $shareManager
- * @param IRequest $request
* @param Notifications $notifications
* @param AddressHandler $addressHandler
* @param IUserManager $userManager
*/
- public function __construct(FederatedShareProvider $federatedShareProvider,
+ public function __construct($appName,
+ IRequest $request,
+ FederatedShareProvider $federatedShareProvider,
IDBConnection $connection,
Share\IManager $shareManager,
- IRequest $request,
Notifications $notifications,
AddressHandler $addressHandler,
IUserManager $userManager
) {
+ parent::__construct($appName, $request);
+
$this->federatedShareProvider = $federatedShareProvider;
$this->connection = $connection;
$this->shareManager = $shareManager;
- $this->request = $request;
$this->notifications = $notifications;
$this->addressHandler = $addressHandler;
$this->userManager = $userManager;
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* create a new share
*
- * @param array $params
- * @return \OC_OCS_Result
+ * @return Http\DataResponse
+ * @throws OCSException
*/
- public function createShare($params) {
+ public function createShare() {
if (!$this->isS2SEnabled(true)) {
- return new \OC_OCS_Result(null, 503, 'Server does not support federated cloud sharing');
+ throw new OCSException('Server does not support federated cloud sharing', 503);
}
$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
@@ -121,7 +127,7 @@ class RequestHandler {
if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
if(!\OCP\Util::isValidFileName($name)) {
- return new \OC_OCS_Result(null, 400, 'The mountpoint name contains invalid characters.');
+ throw new OCSException('The mountpoint name contains invalid characters.', 400);
}
// FIXME this should be a method in the user management instead
@@ -134,7 +140,7 @@ class RequestHandler {
\OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG);
if (!\OCP\User::userExists($shareWith)) {
- return new \OC_OCS_Result(null, 400, 'User does not exists');
+ throw new OCSException('User does not exists', 400);
}
\OC_Util::setupFS($shareWith);
@@ -192,25 +198,30 @@ class RequestHandler {
$notificationManager->notify($notification);
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
} catch (\Exception $e) {
\OCP\Util::writeLog('files_sharing', 'server can not add remote share, ' . $e->getMessage(), \OCP\Util::ERROR);
- return new \OC_OCS_Result(null, 500, 'internal server error, was not able to add share from ' . $remote);
+ throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
}
}
- return new \OC_OCS_Result(null, 400, 'server can not add remote share, missing parameter');
+ throw new OCSException('server can not add remote share, missing parameter', 400);
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* create re-share on behalf of another user
*
- * @param $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSBadRequestException
+ * @throws OCSForbiddenException
+ * @throws OCSNotFoundException
*/
- public function reShare($params) {
+ public function reShare($id) {
- $id = isset($params['id']) ? (int)$params['id'] : null;
$token = $this->request->getParam('token', null);
$shareWith = $this->request->getParam('shareWith', null);
$permission = (int)$this->request->getParam('permission', null);
@@ -222,13 +233,13 @@ class RequestHandler {
$permission === null ||
$remoteId === null
) {
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
+ throw new OCSBadRequestException();
}
try {
$share = $this->federatedShareProvider->getShareById($id);
} catch (Share\Exceptions\ShareNotFound $e) {
- return new \OC_OCS_Result(null, Http::STATUS_NOT_FOUND);
+ throw new OCSNotFoundException();
}
// don't allow to share a file back to the owner
@@ -236,7 +247,7 @@ class RequestHandler {
$owner = $share->getShareOwner();
$currentServer = $this->addressHandler->generateRemoteURL();
if ($this->addressHandler->compareAddresses($user, $remote,$owner , $currentServer)) {
- return new \OC_OCS_Result(null, Http::STATUS_FORBIDDEN);
+ throw new OCSForbiddenException();
}
if ($this->verifyShare($share, $token)) {
@@ -250,37 +261,42 @@ class RequestHandler {
try {
$result = $this->federatedShareProvider->create($share);
$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId);
- return new \OC_OCS_Result(['token' => $result->getToken(), 'remoteId' => $result->getId()]);
+ return new Http\DataResponse([
+ 'token' => $result->getToken(),
+ 'remoteId' => $result->getId()
+ ]);
} catch (\Exception $e) {
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
+ throw new OCSBadRequestException();
}
} else {
- return new \OC_OCS_Result(null, Http::STATUS_FORBIDDEN);
+ throw new OCSForbiddenException();
}
}
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
-
+ throw new OCSBadRequestException();
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* accept server-to-server share
*
- * @param array $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSException
*/
- public function acceptShare($params) {
+ public function acceptShare($id) {
if (!$this->isS2SEnabled()) {
- return new \OC_OCS_Result(null, 503, 'Server does not support federated cloud sharing');
+ throw new OCSException('Server does not support federated cloud sharing', 503);
}
- $id = $params['id'];
$token = isset($_POST['token']) ? $_POST['token'] : null;
try {
$share = $this->federatedShareProvider->getShareById($id);
} catch (Share\Exceptions\ShareNotFound $e) {
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
if ($this->verifyShare($share, $token)) {
@@ -292,7 +308,7 @@ class RequestHandler {
}
}
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
protected function executeAcceptShare(Share\IShare $share) {
@@ -309,24 +325,27 @@ class RequestHandler {
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* decline server-to-server share
*
- * @param array $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSException
*/
- public function declineShare($params) {
+ public function declineShare($id) {
if (!$this->isS2SEnabled()) {
- return new \OC_OCS_Result(null, 503, 'Server does not support federated cloud sharing');
+ throw new OCSException('Server does not support federated cloud sharing', 503);
}
- $id = (int)$params['id'];
$token = isset($_POST['token']) ? $_POST['token'] : null;
try {
$share = $this->federatedShareProvider->getShareById($id);
} catch (Share\Exceptions\ShareNotFound $e) {
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
if($this->verifyShare($share, $token)) {
@@ -338,7 +357,7 @@ class RequestHandler {
$this->executeDeclineShare($share);
}
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
/**
@@ -376,18 +395,21 @@ class RequestHandler {
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* remove server-to-server share if it was unshared by the owner
*
- * @param array $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSException
*/
- public function unshare($params) {
+ public function unshare($id) {
if (!$this->isS2SEnabled()) {
- return new \OC_OCS_Result(null, 503, 'Server does not support federated cloud sharing');
+ throw new OCSException('Server does not support federated cloud sharing', 503);
}
- $id = $params['id'];
$token = isset($_POST['token']) ? $_POST['token'] : null;
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?');
@@ -423,7 +445,7 @@ class RequestHandler {
'', '', $user, Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_MEDIUM);
}
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
private function cleanupRemote($remote) {
@@ -434,24 +456,26 @@ class RequestHandler {
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* federated share was revoked, either by the owner or the re-sharer
*
- * @param $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSBadRequestException
*/
- public function revoke($params) {
- $id = (int)$params['id'];
+ public function revoke($id) {
$token = $this->request->getParam('token');
$share = $this->federatedShareProvider->getShareById($id);
if ($this->verifyShare($share, $token)) {
$this->federatedShareProvider->removeShareFromTable($share);
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
-
+ throw new OCSBadRequestException();
}
/**
@@ -537,20 +561,23 @@ class RequestHandler {
}
/**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
* update share information to keep federated re-shares in sync
*
- * @param array $params
- * @return \OC_OCS_Result
+ * @param int $id
+ * @return Http\DataResponse
+ * @throws OCSBadRequestException
*/
- public function updatePermissions($params) {
- $id = (int)$params['id'];
+ public function updatePermissions($id) {
$token = $this->request->getParam('token', null);
$permissions = $this->request->getParam('permissions', null);
try {
$share = $this->federatedShareProvider->getShareById($id);
} catch (Share\Exceptions\ShareNotFound $e) {
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
+ throw new OCSBadRequestException();
}
$validPermission = ctype_digit($permissions);
@@ -558,10 +585,10 @@ class RequestHandler {
if ($validPermission && $validToken) {
$this->updatePermissionsInDatabase($share, (int)$permissions);
} else {
- return new \OC_OCS_Result(null, Http::STATUS_BAD_REQUEST);
+ throw new OCSBadRequestException();
}
- return new \OC_OCS_Result();
+ return new Http\DataResponse();
}
/**
diff --git a/apps/federatedfilesharing/tests/RequestHandlerTest.php b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
index 8f9f1384184..8e1000fb500 100644
--- a/apps/federatedfilesharing/tests/RequestHandlerTest.php
+++ b/apps/federatedfilesharing/tests/Controller/RequestHandlerControllerTest.php
@@ -30,7 +30,7 @@ namespace OCA\FederatedFileSharing\Tests;
use OC\Files\Filesystem;
use OCA\FederatedFileSharing\DiscoveryManager;
use OCA\FederatedFileSharing\FederatedShareProvider;
-use OCA\FederatedFileSharing\RequestHandler;
+use OCA\FederatedFileSharing\Controller\RequestHandlerController;
use OCP\IUserManager;
use OCP\Share\IShare;
@@ -40,7 +40,7 @@ use OCP\Share\IShare;
* @package OCA\FederatedFileSharing\Tests
* @group DB
*/
-class RequestHandlerTest extends TestCase {
+class RequestHandlerControllerTest extends TestCase {
const TEST_FOLDER_NAME = '/folder_share_api_test';
@@ -50,23 +50,23 @@ class RequestHandlerTest extends TestCase {
private $connection;
/**
- * @var RequestHandler
+ * @var RequestHandlerController
*/
private $s2s;
- /** @var \OCA\FederatedFileSharing\FederatedShareProvider | PHPUnit_Framework_MockObject_MockObject */
+ /** @var \OCA\FederatedFileSharing\FederatedShareProvider|\PHPUnit_Framework_MockObject_MockObject */
private $federatedShareProvider;
- /** @var \OCA\FederatedFileSharing\Notifications | PHPUnit_Framework_MockObject_MockObject */
+ /** @var \OCA\FederatedFileSharing\Notifications|\PHPUnit_Framework_MockObject_MockObject */
private $notifications;
- /** @var \OCA\FederatedFileSharing\AddressHandler | PHPUnit_Framework_MockObject_MockObject */
+ /** @var \OCA\FederatedFileSharing\AddressHandler|\PHPUnit_Framework_MockObject_MockObject */
private $addressHandler;
- /** @var IUserManager | \PHPUnit_Framework_MockObject_MockObject */
+ /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */
private $userManager;
- /** @var IShare | \PHPUnit_Framework_MockObject_MockObject */
+ /** @var IShare|\PHPUnit_Framework_MockObject_MockObject */
private $share;
protected function setUp() {
@@ -77,12 +77,12 @@ class RequestHandlerTest extends TestCase {
$config = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()->getMock();
- $clientService = $this->getMock('\OCP\Http\Client\IClientService');
+ $clientService = $this->getMockBuilder('\OCP\Http\Client\IClientService')->getMock();
$httpHelperMock = $this->getMockBuilder('\OC\HTTPHelper')
->setConstructorArgs([$config, $clientService])
->getMock();
$httpHelperMock->expects($this->any())->method('post')->with($this->anything())->will($this->returnValue(true));
- $this->share = $this->getMock('\OCP\Share\IShare');
+ $this->share = $this->getMockBuilder('\OCP\Share\IShare')->getMock();
$this->federatedShareProvider = $this->getMockBuilder('OCA\FederatedFileSharing\FederatedShareProvider')
->disableOriginalConstructor()->getMock();
$this->federatedShareProvider->expects($this->any())
@@ -96,15 +96,16 @@ class RequestHandlerTest extends TestCase {
->disableOriginalConstructor()->getMock();
$this->addressHandler = $this->getMockBuilder('OCA\FederatedFileSharing\AddressHandler')
->disableOriginalConstructor()->getMock();
- $this->userManager = $this->getMock('OCP\IUserManager');
+ $this->userManager = $this->getMockBuilder('OCP\IUserManager')->getMock();
$this->registerHttpHelper($httpHelperMock);
- $this->s2s = new RequestHandler(
+ $this->s2s = new RequestHandlerController(
+ 'federatedfilesharing',
+ \OC::$server->getRequest(),
$this->federatedShareProvider,
\OC::$server->getDatabaseConnection(),
\OC::$server->getShareManager(),
- \OC::$server->getRequest(),
$this->notifications,
$this->addressHandler,
$this->userManager
@@ -127,7 +128,7 @@ class RequestHandlerTest extends TestCase {
/**
* Register an http helper mock for testing purposes.
- * @param $httpHelper http helper mock
+ * @param \OC\HTTPHelper $httpHelper helper mock
*/
private function registerHttpHelper($httpHelper) {
$this->oldHttpHelper = \OC::$server->query('HTTPHelper');
@@ -158,9 +159,7 @@ class RequestHandlerTest extends TestCase {
$_POST['shareWith'] = self::TEST_FILES_SHARING_API_USER2;
$_POST['remoteId'] = 1;
- $result = $this->s2s->createShare(null);
-
- $this->assertTrue($result->succeeded());
+ $this->s2s->createShare(null);
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ?');
$result = $query->execute(array('1'));
@@ -178,13 +177,14 @@ class RequestHandlerTest extends TestCase {
function testDeclineShare() {
- $this->s2s = $this->getMockBuilder('\OCA\FederatedFileSharing\RequestHandler')
+ $this->s2s = $this->getMockBuilder('\OCA\FederatedFileSharing\Controller\RequestHandlerController')
->setConstructorArgs(
[
+ 'federatedfilessharing',
+ \OC::$server->getRequest(),
$this->federatedShareProvider,
\OC::$server->getDatabaseConnection(),
\OC::$server->getShareManager(),
- \OC::$server->getRequest(),
$this->notifications,
$this->addressHandler,
$this->userManager
@@ -197,7 +197,7 @@ class RequestHandlerTest extends TestCase {
$_POST['token'] = 'token';
- $this->s2s->declineShare(array('id' => 42));
+ $this->s2s->declineShare(42);
}
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index f191ade240b..ca41012764a 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -199,6 +199,7 @@
* @param options.folderDropOptions folder drop options, disabled by default
* @param options.scrollTo name of file to scroll to after the first load
* @param {OC.Files.Client} [options.filesClient] files API client
+ * @param {OC.Backbone.Model} [options.filesConfig] files app configuration
* @private
*/
initialize: function($el, options) {
@@ -212,6 +213,10 @@
this._filesConfig = options.config;
} else if (!_.isUndefined(OCA.Files) && !_.isUndefined(OCA.Files.App)) {
this._filesConfig = OCA.Files.App.getFilesConfig();
+ } else {
+ this._filesConfig = new OC.Backbone.Model({
+ 'showhidden': false
+ });
}
if (options.dragOptions) {
@@ -239,6 +244,7 @@
this._filesConfig.on('change:showhidden', function() {
var showHidden = this.get('showhidden');
self.$el.toggleClass('hide-hidden-files', !showHidden);
+ self.updateSelectionSummary();
if (!showHidden) {
// hiding files could make the page too small, need to try rendering next page
@@ -264,7 +270,7 @@
this.files = [];
this._selectedFiles = {};
- this._selectionSummary = new OCA.Files.FileSummary();
+ this._selectionSummary = new OCA.Files.FileSummary(undefined, {config: this._filesConfig});
// dummy root dir info
this.dirInfo = new OC.Files.FileInfo({});
@@ -2304,7 +2310,7 @@
var $tr = $('<tr class="summary"></tr>');
this.$el.find('tfoot').append($tr);
- return new OCA.Files.FileSummary($tr);
+ return new OCA.Files.FileSummary($tr, {config: this._filesConfig});
},
updateEmptyContent: function() {
var permissions = this.getDirectoryPermissions();
@@ -2451,6 +2457,7 @@
var summary = this._selectionSummary.summary;
var selection;
+ var showHidden = !!this._filesConfig.get('showhidden');
if (summary.totalFiles === 0 && summary.totalDirs === 0) {
this.$el.find('#headerName a.name>span:first').text(t('files','Name'));
this.$el.find('#headerSize a>span:first').text(t('files','Size'));
@@ -2477,6 +2484,11 @@
selection = fileInfo;
}
+ if (!showHidden && summary.totalHidden > 0) {
+ var hiddenInfo = n('files', 'including %n hidden', 'including %n hidden', summary.totalHidden);
+ selection += ' (' + hiddenInfo + ')';
+ }
+
this.$el.find('#headerName a.name>span:first').text(selection);
this.$el.find('#modified a>span:first').text('');
this.$el.find('table').addClass('multiselect');
diff --git a/apps/files/js/filesummary.js b/apps/files/js/filesummary.js
index a4cefe692a8..519718cfc82 100644
--- a/apps/files/js/filesummary.js
+++ b/apps/files/js/filesummary.js
@@ -20,6 +20,15 @@
*/
(function() {
+ var INFO_TEMPLATE =
+ '<span class="info">' +
+ '<span class="dirinfo"></span>' +
+ '<span class="connector"> and </span>' +
+ '<span class="fileinfo"></span>' +
+ '<span class="hiddeninfo"></span>' +
+ '<span class="filter"></span>' +
+ '</span>';
+
/**
* The FileSummary class encapsulates the file summary values and
* the logic to render it in the given container
@@ -28,26 +37,51 @@
* @memberof OCA.Files
*
* @param $tr table row element
+ * @param {OC.Backbone.Model} [options.filesConfig] files app configuration
*/
- var FileSummary = function($tr) {
+ var FileSummary = function($tr, options) {
+ options = options || {};
+ var self = this;
this.$el = $tr;
+ var filesConfig = options.config;
+ if (filesConfig) {
+ this._showHidden = !!filesConfig.get('showhidden');
+ filesConfig.on('change:showhidden', function() {
+ self._showHidden = !!this.get('showhidden');
+ self.update();
+ });
+ }
this.clear();
this.render();
};
FileSummary.prototype = {
+ _showHidden: null,
+
summary: {
totalFiles: 0,
totalDirs: 0,
+ totalHidden: 0,
totalSize: 0,
filter:'',
sumIsPending:false
},
/**
+ * Returns whether the given file info must be hidden
+ *
+ * @param {OC.Files.FileInfo} fileInfo file info
+ *
+ * @return {boolean} true if the file is a hidden file, false otherwise
+ */
+ _isHiddenFile: function(file) {
+ return file.name && file.name.charAt(0) === '.';
+ },
+
+ /**
* Adds file
- * @param file file to add
- * @param update whether to update the display
+ * @param {OC.Files.FileInfo} file file to add
+ * @param {boolean} update whether to update the display
*/
add: function(file, update) {
if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) {
@@ -59,6 +93,10 @@
else {
this.summary.totalFiles++;
}
+ if (this._isHiddenFile(file)) {
+ this.summary.totalHidden++;
+ }
+
var size = parseInt(file.size, 10) || 0;
if (size >=0) {
this.summary.totalSize += size;
@@ -71,8 +109,8 @@
},
/**
* Removes file
- * @param file file to remove
- * @param update whether to update the display
+ * @param {OC.Files.FileInfo} file file to remove
+ * @param {boolean} update whether to update the display
*/
remove: function(file, update) {
if (file.name && file.name.toLowerCase().indexOf(this.summary.filter) === -1) {
@@ -84,6 +122,9 @@
else {
this.summary.totalFiles--;
}
+ if (this._isHiddenFile(file)) {
+ this.summary.totalHidden--;
+ }
var size = parseInt(file.size, 10) || 0;
if (size >=0) {
this.summary.totalSize -= size;
@@ -111,6 +152,7 @@
var summary = {
totalDirs: 0,
totalFiles: 0,
+ totalHidden: 0,
totalSize: 0,
filter: this.summary.filter,
sumIsPending: false
@@ -127,6 +169,9 @@
else {
summary.totalFiles++;
}
+ if (this._isHiddenFile(file)) {
+ summary.totalHidden++;
+ }
var size = parseInt(file.size, 10) || 0;
if (size >=0) {
summary.totalSize += size;
@@ -154,6 +199,13 @@
this.update();
},
+ _infoTemplate: function(data) {
+ if (!this._infoTemplateCompiled) {
+ this._infoTemplateCompiled = Handlebars.compile(INFO_TEMPLATE);
+ }
+ return this._infoTemplateCompiled(data);
+ },
+
/**
* Renders the file summary element
*/
@@ -171,10 +223,12 @@
var $fileInfo = this.$el.find('.fileinfo');
var $connector = this.$el.find('.connector');
var $filterInfo = this.$el.find('.filter');
+ var $hiddenInfo = this.$el.find('.hiddeninfo');
// Substitute old content with new translations
$dirInfo.html(n('files', '%n folder', '%n folders', this.summary.totalDirs));
$fileInfo.html(n('files', '%n file', '%n files', this.summary.totalFiles));
+ $hiddenInfo.html(' (' + n('files', 'including %n hidden', 'including %n hidden', this.summary.totalHidden) + ')');
var fileSize = this.summary.sumIsPending ? t('files', 'Pending') : OC.Util.humanFileSize(this.summary.totalSize);
this.$el.find('.filesize').html(fileSize);
@@ -194,6 +248,7 @@
if (this.summary.totalDirs > 0 && this.summary.totalFiles > 0) {
$connector.removeClass('hidden');
}
+ $hiddenInfo.toggleClass('hidden', this.summary.totalHidden === 0 || this._showHidden)
if (this.summary.filter === '') {
$filterInfo.html('');
$filterInfo.addClass('hidden');
@@ -206,19 +261,7 @@
if (!this.$el) {
return;
}
- // TODO: ideally this should be separate to a template or something
var summary = this.summary;
- var directoryInfo = n('files', '%n folder', '%n folders', summary.totalDirs);
- var fileInfo = n('files', '%n file', '%n files', summary.totalFiles);
- var filterInfo = '';
- if (this.summary.filter !== '') {
- filterInfo = ' ' + n('files', 'matches \'{filter}\'', 'match \'{filter}\'', summary.totalFiles + summary.totalDirs, {filter: summary.filter});
- }
-
- var infoVars = {
- dirs: '<span class="dirinfo">'+directoryInfo+'</span><span class="connector">',
- files: '</span><span class="fileinfo">'+fileInfo+'</span>'
- };
// don't show the filesize column, if filesize is NaN (e.g. in trashbin)
var fileSize = '';
@@ -227,15 +270,14 @@
fileSize = '<td class="filesize">' + fileSize + '</td>';
}
- var info = t('files', '{dirs} and {files}', infoVars, null, {'escape': false});
-
- var $summary = $('<td><span class="info">'+info+'<span class="filter">'+filterInfo+'</span></span></td>'+fileSize+'<td class="date"></td>');
-
- if (!this.summary.totalFiles && !this.summary.totalDirs) {
- this.$el.addClass('hidden');
- }
-
+ var $summary = $(
+ '<td>' + this._infoTemplate() + '</td>' +
+ fileSize +
+ '<td class="date"></td>'
+ );
+ this.$el.addClass('hidden');
this.$el.append($summary);
+ this.update();
}
};
OCA.Files.FileSummary = FileSummary;
diff --git a/apps/files/lib/Command/Scan.php b/apps/files/lib/Command/Scan.php
index 25933ae25aa..0234fb435a7 100644
--- a/apps/files/lib/Command/Scan.php
+++ b/apps/files/lib/Command/Scan.php
@@ -28,9 +28,11 @@
namespace OCA\Files\Command;
+use Doctrine\DBAL\Connection;
use OC\Core\Command\Base;
use OC\ForbiddenException;
use OCP\Files\StorageNotAvailableException;
+use OCP\IDBConnection;
use OCP\IUserManager;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -106,7 +108,8 @@ class Scan extends Base {
}
protected function scanFiles($user, $path, $verbose, OutputInterface $output, $backgroundScan = false) {
- $scanner = new \OC\Files\Utils\Scanner($user, \OC::$server->getDatabaseConnection(), \OC::$server->getLogger());
+ $connection = $this->reconnectToDatabase($output);
+ $scanner = new \OC\Files\Utils\Scanner($user, $connection, \OC::$server->getLogger());
# check on each file/folder if there was a user interrupt (ctrl-c) and throw an exception
# printout and count
if ($verbose) {
@@ -318,4 +321,26 @@ class Scan extends Base {
return date('H:i:s', $secs);
}
+ /**
+ * @return \OCP\IDBConnection
+ */
+ protected function reconnectToDatabase(OutputInterface $output) {
+ /** @var Connection | IDBConnection $connection*/
+ $connection = \OC::$server->getDatabaseConnection();
+ try {
+ $connection->close();
+ } catch (\Exception $ex) {
+ $output->writeln("<info>Error while disconnecting from database: {$ex->getMessage()}</info>");
+ }
+ while (!$connection->isConnected()) {
+ try {
+ $connection->connect();
+ } catch (\Exception $ex) {
+ $output->writeln("<info>Error while re-connecting to database: {$ex->getMessage()}</info>");
+ sleep(60);
+ }
+ }
+ return $connection;
+ }
+
}
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index cf9f43f2d59..0a4812f3a81 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -385,8 +385,9 @@ describe('OCA.Files.FileList tests', function() {
$summary = $('#filestable .summary');
expect($summary.hasClass('hidden')).toEqual(false);
// yes, ugly...
- expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.connector').hasClass('hidden')).toEqual(true);
expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false);
expect($summary.find('.filesize').text()).toEqual('12 B');
expect($('#filestable thead th').hasClass('hidden')).toEqual(false);
@@ -456,7 +457,8 @@ describe('OCA.Files.FileList tests', function() {
$summary = $('#filestable .summary');
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual('1 folder and 2 files');
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('2 files');
expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false);
expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false);
expect($summary.find('.filesize').text()).toEqual('69 KB');
@@ -511,7 +513,8 @@ describe('OCA.Files.FileList tests', function() {
$summary = $('#filestable .summary');
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual('1 folder and 1 file');
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(false);
expect($summary.find('.fileinfo').hasClass('hidden')).toEqual(false);
expect($summary.find('.filesize').text()).toEqual('57 KB');
@@ -677,12 +680,14 @@ describe('OCA.Files.FileList tests', function() {
deferredRename.resolve(201);
- expect($summary.find('.info').text()).toEqual('1 folder and 3 files');
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('3 files');
});
it('Leaves the summary alone when cancel renaming', function() {
var $summary = $('#filestable .summary');
doCancelRename();
- expect($summary.find('.info').text()).toEqual('1 folder and 3 files');
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('3 files');
});
it('Shows busy state while rename in progress', function() {
var $tr;
@@ -856,11 +861,14 @@ describe('OCA.Files.FileList tests', function() {
});
var $tr = fileList.add(fileData);
- expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
var model = fileList.getModelForFile('test file');
model.set({size: '100'});
- expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
+
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
});
})
describe('List rendering', function() {
@@ -877,7 +885,8 @@ describe('OCA.Files.FileList tests', function() {
fileList.setFiles(testFiles);
$summary = $('#filestable .summary');
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual('1 folder and 3 files');
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('3 files');
expect($summary.find('.filesize').text()).toEqual('69 KB');
});
it('shows headers, summary and hide empty content message after setting files', function(){
@@ -962,10 +971,12 @@ describe('OCA.Files.FileList tests', function() {
fileList.setFiles([testFiles[0]]);
$summary = $('#filestable .summary');
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
fileList.remove('unexist.txt');
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual('0 folders and 1 file');
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
});
});
describe('Filtered list rendering', function() {
@@ -987,14 +998,18 @@ describe('OCA.Files.FileList tests', function() {
expect($('#fileList tr:not(.hidden)').length).toEqual(3);
expect(fileList.files.length).toEqual(4);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("1 folder and 2 files match 'e'");
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('2 files');
+ expect($summary.find('.filter').text()).toEqual(" match 'e'");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
fileList.setFilter('ee');
expect($('#fileList tr:not(.hidden)').length).toEqual(1);
expect(fileList.files.length).toEqual(4);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches 'ee'");
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
+ expect($summary.find('.filter').text()).toEqual(" matches 'ee'");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
fileList.setFilter('eee');
@@ -1007,21 +1022,26 @@ describe('OCA.Files.FileList tests', function() {
expect($('#fileList tr:not(.hidden)').length).toEqual(1);
expect(fileList.files.length).toEqual(4);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches 'ee'");
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
+ expect($summary.find('.filter').text()).toEqual(" matches 'ee'");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
fileList.setFilter('e');
expect($('#fileList tr:not(.hidden)').length).toEqual(3);
expect(fileList.files.length).toEqual(4);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("1 folder and 2 files match 'e'");
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('2 files');
+ expect($summary.find('.filter').text()).toEqual(" match 'e'");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
fileList.setFilter('');
expect($('#fileList tr:not(.hidden)').length).toEqual(4);
expect(fileList.files.length).toEqual(4);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("1 folder and 3 files");
+ expect($summary.find('.dirinfo').text()).toEqual('1 folder');
+ expect($summary.find('.fileinfo').text()).toEqual('3 files');
expect($nofilterresults.hasClass('hidden')).toEqual(true);
});
it('filters the list of non-rendered rows using filter()', function() {
@@ -1032,7 +1052,9 @@ describe('OCA.Files.FileList tests', function() {
fileList.setFilter('63');
expect($('#fileList tr:not(.hidden)').length).toEqual(1);
expect($summary.hasClass('hidden')).toEqual(false);
- expect($summary.find('.info').text()).toEqual("0 folders and 1 file matches '63'");
+ expect($summary.find('.dirinfo').hasClass('hidden')).toEqual(true);
+ expect($summary.find('.fileinfo').text()).toEqual('1 file');
+ expect($summary.find('.filter').text()).toEqual(" matches '63'");
expect($nofilterresults.hasClass('hidden')).toEqual(true);
});
it('hides the emptyfiles notice when using filter()', function() {
@@ -1654,6 +1676,18 @@ describe('OCA.Files.FileList tests', function() {
$('#fileList tr td.filename input:checkbox').click();
expect($('.select-all').prop('checked')).toEqual(false);
});
+ it('Selecting all files also selects hidden files when invisible', function() {
+ filesConfig.set('showhidden', false);
+ var $tr = fileList.add(new FileInfo({
+ name: '.hidden',
+ type: 'dir',
+ mimetype: 'httpd/unix-directory',
+ size: 150
+ }));
+ $('.select-all').click();
+ expect($tr.find('td.filename input:checkbox').prop('checked')).toEqual(true);
+ expect(_.pluck(fileList.getSelectedFiles(), 'name')).toContain('.hidden');
+ });
it('Clicking "select all" will select/deselect all files', function() {
fileList.setFiles(generateFiles(0, 41));
$('.select-all').click();
@@ -1731,6 +1765,44 @@ describe('OCA.Files.FileList tests', function() {
fileList.findFileEl('One.txt').find('input:checkbox').click().click();
expect($summary.text()).toEqual('Name');
});
+ it('Displays the number of hidden files in selection summary if hidden files are invisible', function() {
+ filesConfig.set('showhidden', false);
+ var $tr = fileList.add(new FileInfo({
+ name: '.hidden',
+ type: 'dir',
+ mimetype: 'httpd/unix-directory',
+ size: 150
+ }));
+ $('.select-all').click();
+ var $summary = $('#headerName a.name>span:first');
+ expect($summary.text()).toEqual('2 folders and 3 files (including 1 hidden)');
+ });
+ it('Does not displays the number of hidden files in selection summary if hidden files are visible', function() {
+ filesConfig.set('showhidden', true);
+ var $tr = fileList.add(new FileInfo({
+ name: '.hidden',
+ type: 'dir',
+ mimetype: 'httpd/unix-directory',
+ size: 150
+ }));
+ $('.select-all').click();
+ var $summary = $('#headerName a.name>span:first');
+ expect($summary.text()).toEqual('2 folders and 3 files');
+ });
+ it('Toggling hidden file visibility updates selection summary', function() {
+ filesConfig.set('showhidden', false);
+ var $tr = fileList.add(new FileInfo({
+ name: '.hidden',
+ type: 'dir',
+ mimetype: 'httpd/unix-directory',
+ size: 150
+ }));
+ $('.select-all').click();
+ var $summary = $('#headerName a.name>span:first');
+ expect($summary.text()).toEqual('2 folders and 3 files (including 1 hidden)');
+ filesConfig.set('showhidden', true);
+ expect($summary.text()).toEqual('2 folders and 3 files');
+ });
it('Select/deselect files shows/hides file actions', function() {
var $actions = $('#headerName .selectedActions');
var $checkbox = fileList.findFileEl('One.txt').find('input:checkbox');
diff --git a/apps/files/tests/js/filesummarySpec.js b/apps/files/tests/js/filesummarySpec.js
index ec94c28acb6..e3f24d9ad43 100644
--- a/apps/files/tests/js/filesummarySpec.js
+++ b/apps/files/tests/js/filesummarySpec.js
@@ -39,7 +39,8 @@ describe('OCA.Files.FileSummary tests', function() {
totalSize: 256000
});
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('5 folders and 2 files');
+ expect($container.find('.dirinfo').text()).toEqual('5 folders');
+ expect($container.find('.fileinfo').text()).toEqual('2 files');
expect($container.find('.filesize').text()).toEqual('250 KB');
});
it('hides summary when no files or folders', function() {
@@ -62,7 +63,8 @@ describe('OCA.Files.FileSummary tests', function() {
s.add({type: 'dir', size: 100});
s.update();
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('6 folders and 3 files');
+ expect($container.find('.dirinfo').text()).toEqual('6 folders');
+ expect($container.find('.fileinfo').text()).toEqual('3 files');
expect($container.find('.filesize').text()).toEqual('500 KB');
expect(s.summary.totalDirs).toEqual(6);
expect(s.summary.totalFiles).toEqual(3);
@@ -79,7 +81,8 @@ describe('OCA.Files.FileSummary tests', function() {
s.remove({type: 'dir', size: 100});
s.update();
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('4 folders and 1 file');
+ expect($container.find('.dirinfo').text()).toEqual('4 folders');
+ expect($container.find('.fileinfo').text()).toEqual('1 file');
expect($container.find('.filesize').text()).toEqual('125 KB');
expect(s.summary.totalDirs).toEqual(4);
expect(s.summary.totalFiles).toEqual(1);
@@ -95,7 +98,9 @@ describe('OCA.Files.FileSummary tests', function() {
filter: 'foo'
});
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('5 folders and 2 files match \'foo\'');
+ expect($container.find('.dirinfo').text()).toEqual('5 folders');
+ expect($container.find('.fileinfo').text()).toEqual('2 files');
+ expect($container.find('.filter').text()).toEqual(' match \'foo\'');
expect($container.find('.filesize').text()).toEqual('250 KB');
});
it('hides filtered summary when no files or folders', function() {
@@ -122,7 +127,9 @@ describe('OCA.Files.FileSummary tests', function() {
s.add({name: 'foo', type: 'dir', size: 102});
s.update();
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('6 folders and 3 files match \'foo\'');
+ expect($container.find('.dirinfo').text()).toEqual('6 folders');
+ expect($container.find('.fileinfo').text()).toEqual('3 files');
+ expect($container.find('.filter').text()).toEqual(' match \'foo\'');
expect($container.find('.filesize').text()).toEqual('500 KB');
expect(s.summary.totalDirs).toEqual(6);
expect(s.summary.totalFiles).toEqual(3);
@@ -142,7 +149,9 @@ describe('OCA.Files.FileSummary tests', function() {
s.remove({name: 'foo', type: 'dir', size: 98});
s.update();
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('4 folders and 1 file match \'foo\'');
+ expect($container.find('.dirinfo').text()).toEqual('4 folders');
+ expect($container.find('.fileinfo').text()).toEqual('1 file');
+ expect($container.find('.filter').text()).toEqual(' match \'foo\'');
expect($container.find('.filesize').text()).toEqual('125 KB');
expect(s.summary.totalDirs).toEqual(4);
expect(s.summary.totalFiles).toEqual(1);
@@ -158,7 +167,8 @@ describe('OCA.Files.FileSummary tests', function() {
s.add({type: 'dir', size: -1});
s.update();
expect($container.hasClass('hidden')).toEqual(false);
- expect($container.find('.info').text()).toEqual('1 folder and 0 files');
+ expect($container.find('.dirinfo').text()).toEqual('1 folder');
+ expect($container.find('.fileinfo').hasClass('hidden')).toEqual(true);
expect($container.find('.filesize').text()).toEqual('Pending');
expect(s.summary.totalDirs).toEqual(1);
expect(s.summary.totalFiles).toEqual(0);
@@ -175,10 +185,56 @@ describe('OCA.Files.FileSummary tests', function() {
s.remove({type: 'dir', size: -1});
s.update();
expect($container.hasClass('hidden')).toEqual(true);
- expect($container.find('.info').text()).toEqual('0 folders and 0 files');
- expect($container.find('.filesize').text()).toEqual('0 B');
expect(s.summary.totalDirs).toEqual(0);
expect(s.summary.totalFiles).toEqual(0);
expect(s.summary.totalSize).toEqual(0);
});
+ describe('hidden files', function() {
+ var config;
+ var summary;
+
+ beforeEach(function() {
+ config = new OC.Backbone.Model();
+ summary = new FileSummary($container, {
+ config: config
+ });
+ });
+
+ it('renders hidden count section when hidden files are hidden', function() {
+ config.set('showhidden', false);
+ summary.add({name: 'abc', type: 'file', size: 256000});
+ summary.add({name: 'def', type: 'dir', size: 100});
+ summary.add({name: '.hidden', type: 'dir', size: 512000});
+ summary.update();
+ expect($container.hasClass('hidden')).toEqual(false);
+ expect($container.find('.dirinfo').text()).toEqual('2 folders');
+ expect($container.find('.fileinfo').text()).toEqual('1 file');
+ expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(false);
+ expect($container.find('.hiddeninfo').text()).toEqual(' (including 1 hidden)');
+ expect($container.find('.filesize').text()).toEqual('750 KB');
+ });
+ it('does not render hidden count section when hidden files exist but are visible', function() {
+ config.set('showhidden', true);
+ summary.add({name: 'abc', type: 'file', size: 256000});
+ summary.add({name: 'def', type: 'dir', size: 100});
+ summary.add({name: '.hidden', type: 'dir', size: 512000});
+ summary.update();
+ expect($container.hasClass('hidden')).toEqual(false);
+ expect($container.find('.dirinfo').text()).toEqual('2 folders');
+ expect($container.find('.fileinfo').text()).toEqual('1 file');
+ expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(true);
+ expect($container.find('.filesize').text()).toEqual('750 KB');
+ });
+ it('does not render hidden count section when no hidden files exist', function() {
+ config.set('showhidden', false);
+ summary.add({name: 'abc', type: 'file', size: 256000});
+ summary.add({name: 'def', type: 'dir', size: 100});
+ summary.update();
+ expect($container.hasClass('hidden')).toEqual(false);
+ expect($container.find('.dirinfo').text()).toEqual('1 folder');
+ expect($container.find('.fileinfo').text()).toEqual('1 file');
+ expect($container.find('.hiddeninfo').hasClass('hidden')).toEqual(true);
+ expect($container.find('.filesize').text()).toEqual('250 KB');
+ });
+ });
});
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php
index 3ceca430424..e1875fe2394 100644
--- a/apps/files_sharing/lib/sharedstorage.php
+++ b/apps/files_sharing/lib/sharedstorage.php
@@ -106,6 +106,16 @@ class Shared extends \OC\Files\Storage\Wrapper\Jail implements ISharedStorage {
}
/**
+ * @inheritdoc
+ */
+ public function instanceOfStorage($class) {
+ if (in_array($class, ['\OC\Files\Storage\Home', '\OC\Files\ObjectStore\HomeObjectStoreStorage'])) {
+ return false;
+ }
+ return parent::instanceOfStorage($class);
+ }
+
+ /**
* @return string
*/
public function getShareId() {
diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php
index fbb4c904773..b4e3a95710f 100644
--- a/apps/theming/lib/Controller/ThemingController.php
+++ b/apps/theming/lib/Controller/ThemingController.php
@@ -304,6 +304,13 @@ class ThemingController extends Controller {
$responseCss = '';
$color = $this->config->getAppValue($this->appName, 'color');
$elementColor = $this->util->elementColor($color);
+
+ if($this->util->invertTextColor($color)) {
+ $textColor = '#000000';
+ } else {
+ $textColor = '#ffffff';
+ }
+
if($color !== '') {
$responseCss .= sprintf(
'#body-user #header,#body-settings #header,#body-public #header,#body-login,.searchbox input[type="search"]:focus,.searchbox input[type="search"]:active,.searchbox input[type="search"]:valid {background-color: %s}' . "\n",
@@ -321,19 +328,26 @@ class ThemingController extends Controller {
'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton($elementColor).'\');' .
"}\n";
$responseCss .= '.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary,' .
- '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,' .
- '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
- '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
- '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active {' .
'border: 1px solid '.$elementColor.';'.
'background-color: '.$elementColor.';'.
- 'opacity: 0.8' .
+ 'opacity: 0.8;' .
+ 'color: ' . $textColor . ';'.
"}\n" .
'.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,' .
'.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {' .
'border: 1px solid '.$elementColor.';'.
'background-color: '.$elementColor.';'.
'opacity: 1.0;' .
+ 'color: ' . $textColor . ';'.
+ "}\n" .
+ '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
+ '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
+ '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
+ 'opacity: 0.4;' .
+ 'color: '.$textColor.';'.
"}\n";
$responseCss .= '.ui-widget-header { border: 1px solid ' . $color . '; background: '. $color . '; color: #ffffff;' . "}\n";
$responseCss .= '.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {' .
diff --git a/apps/theming/lib/Settings/Admin.php b/apps/theming/lib/Settings/Admin.php
index afd74ced217..22ab5650e5b 100644
--- a/apps/theming/lib/Settings/Admin.php
+++ b/apps/theming/lib/Settings/Admin.php
@@ -61,7 +61,7 @@ class Admin implements ISettings {
$theme = $this->config->getSystemValue('theme', '');
if ($theme !== '') {
$themable = false;
- $errorMessage = $this->l->t('You already use a custom theme');
+ $errorMessage = $this->l->t('You are already using a custom theme');
}
$parameters = [
diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php
index d053d8c1a1c..193e0bdcb4b 100644
--- a/apps/theming/tests/Controller/ThemingControllerTest.php
+++ b/apps/theming/tests/Controller/ThemingControllerTest.php
@@ -437,19 +437,26 @@ class ThemingControllerTest extends TestCase {
'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton($color).'\');' .
"}\n";
$expectedData .= '.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary,' .
- '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,' .
- '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
- '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
- '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
- 'border: 1px solid '.$color .';'.
+ '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active {' .
+ 'border: 1px solid '.$color.';'.
'background-color: '.$color.';'.
- 'opacity: 0.8' .
+ 'opacity: 0.8;' .
+ 'color: #ffffff;'.
"}\n" .
'.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,' .
'.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {' .
'border: 1px solid '.$color.';'.
'background-color: '.$color.';'.
'opacity: 1.0;' .
+ 'color: #ffffff;'.
+ "}\n" .
+ '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
+ '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
+ '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ 'border: 1px solid '.$color.';'.
+ 'background-color: '.$color.';'.
+ 'opacity: 0.4;' .
+ 'color: #ffffff;'.
"}\n";
$expectedData .= '.ui-widget-header { border: 1px solid ' . $color . '; background: '. $color . '; color: #ffffff;' . "}\n";
$expectedData .= '.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {' .
@@ -520,19 +527,26 @@ class ThemingControllerTest extends TestCase {
'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton('#555555').'\');' .
"}\n";
$expectedData .= '.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary,' .
- '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,' .
- '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
- '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
- '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
- 'border: 1px solid #555555;'.
- 'background-color: #555555;'.
- 'opacity: 0.8' .
+ '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active {' .
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
+ 'opacity: 0.8;' .
+ 'color: #000000;'.
"}\n" .
'.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,' .
'.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {' .
- 'border: 1px solid #555555;'.
- 'background-color: #555555;'.
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
'opacity: 1.0;' .
+ 'color: #000000;'.
+ "}\n" .
+ '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
+ '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
+ '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
+ 'opacity: 0.4;' .
+ 'color: #000000;'.
"}\n";
$expectedData .= '.ui-widget-header { border: 1px solid ' . $color . '; background: '. $color . '; color: #ffffff;' . "}\n";
$expectedData .= '.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {' .
@@ -689,19 +703,26 @@ class ThemingControllerTest extends TestCase {
'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton($color).'\');' .
"}\n";
$expectedData .= '.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary,' .
- '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,' .
- '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
- '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
- '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
- 'border: 1px solid '.$color .';'.
+ '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active {' .
+ 'border: 1px solid '.$color.';'.
'background-color: '.$color.';'.
- 'opacity: 0.8' .
+ 'opacity: 0.8;' .
+ 'color: #ffffff;'.
"}\n" .
'.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,' .
'.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {' .
'border: 1px solid '.$color.';'.
'background-color: '.$color.';'.
'opacity: 1.0;' .
+ 'color: #ffffff;'.
+ "}\n" .
+ '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
+ '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
+ '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ 'border: 1px solid '.$color.';'.
+ 'background-color: '.$color.';'.
+ 'opacity: 0.4;' .
+ 'color: #ffffff;'.
"}\n";
$expectedData .= '.ui-widget-header { border: 1px solid ' . $color . '; background: '. $color . '; color: #ffffff;' . "}\n";
$expectedData .= '.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {' .
@@ -789,19 +810,26 @@ class ThemingControllerTest extends TestCase {
'background-image: url(\'data:image/svg+xml;base64,'.$this->util->generateRadioButton('#555555').'\');' .
"}\n";
$expectedData .= '.primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary,' .
- '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active,' .
- '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
- '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
- '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
- 'border: 1px solid #555555;'.
- 'background-color: #555555;'.
- 'opacity: 0.8' .
+ '.primary:active, input[type="submit"].primary:active, input[type="button"].primary:active, button.primary:active, .button.primary:active {' .
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
+ 'opacity: 0.8;' .
+ 'color: #000000;'.
"}\n" .
'.primary:hover, input[type="submit"].primary:hover, input[type="button"].primary:hover, button.primary:hover, .button.primary:hover,' .
'.primary:focus, input[type="submit"].primary:focus, input[type="button"].primary:focus, button.primary:focus, .button.primary:focus {' .
- 'border: 1px solid #555555;'.
- 'background-color: #555555;'.
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
'opacity: 1.0;' .
+ 'color: #000000;'.
+ "}\n" .
+ '.primary:disabled, input[type="submit"].primary:disabled, input[type="button"].primary:disabled, button.primary:disabled, .button.primary:disabled,' .
+ '.primary:disabled:hover, input[type="submit"].primary:disabled:hover, input[type="button"].primary:disabled:hover, button.primary:disabled:hover, .button.primary:disabled:hover,' .
+ '.primary:disabled:focus, input[type="submit"].primary:disabled:focus, input[type="button"].primary:disabled:focus, button.primary:disabled:focus, .button.primary:disabled:focus {' .
+ 'border: 1px solid '.$elementColor.';'.
+ 'background-color: '.$elementColor.';'.
+ 'opacity: 0.4;' .
+ 'color: #000000;'.
"}\n";
$expectedData .= '.ui-widget-header { border: 1px solid ' . $color . '; background: '. $color . '; color: #ffffff;' . "}\n";
$expectedData .= '.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {' .
diff --git a/apps/theming/tests/Settings/AdminTest.php b/apps/theming/tests/Settings/AdminTest.php
index 73339cf86b7..d4f5490d352 100644
--- a/apps/theming/tests/Settings/AdminTest.php
+++ b/apps/theming/tests/Settings/AdminTest.php
@@ -112,8 +112,8 @@ class AdminTest extends TestCase {
$this->l10n
->expects($this->once())
->method('t')
- ->with('You already use a custom theme')
- ->willReturn('You already use a custom theme');
+ ->with('You are already using a custom theme')
+ ->willReturn('You are already using a custom theme');
$this->themingDefaults
->expects($this->once())
->method('getEntity')
@@ -137,7 +137,7 @@ class AdminTest extends TestCase {
->willReturn('/my/route');
$params = [
'themable' => false,
- 'errorMessage' => 'You already use a custom theme',
+ 'errorMessage' => 'You are already using a custom theme',
'name' => 'MyEntity',
'url' => 'https://example.com',
'slogan' => 'MySlogan',
diff --git a/apps/user_ldap/ajax/getConfiguration.php b/apps/user_ldap/ajax/getConfiguration.php
index 0537349bbeb..34ac97f29e7 100644
--- a/apps/user_ldap/ajax/getConfiguration.php
+++ b/apps/user_ldap/ajax/getConfiguration.php
@@ -32,4 +32,9 @@ OCP\JSON::callCheck();
$prefix = (string)$_POST['ldap_serverconfig_chooser'];
$ldapWrapper = new OCA\User_LDAP\LDAP();
$connection = new \OCA\User_LDAP\Connection($ldapWrapper, $prefix);
-OCP\JSON::success(array('configuration' => $connection->getConfiguration()));
+$configuration = $connection->getConfiguration();
+if (isset($configuration['ldap_agent_password']) && $configuration['ldap_agent_password'] !== '') {
+ // hide password
+ $configuration['ldap_agent_password'] = '**PASSWORD SET**';
+}
+OCP\JSON::success(array('configuration' => $configuration));
diff --git a/apps/user_ldap/ajax/testConfiguration.php b/apps/user_ldap/ajax/testConfiguration.php
index f73e11d3e21..0416e49767b 100644
--- a/apps/user_ldap/ajax/testConfiguration.php
+++ b/apps/user_ldap/ajax/testConfiguration.php
@@ -33,12 +33,19 @@ OCP\JSON::callCheck();
$l = \OC::$server->getL10N('user_ldap');
$ldapWrapper = new OCA\User_LDAP\LDAP();
-$connection = new \OCA\User_LDAP\Connection($ldapWrapper, '', null);
-//needs to be true, otherwise it will also fail with an irritating message
-$_POST['ldap_configuration_active'] = 1;
+$connection = new \OCA\User_LDAP\Connection($ldapWrapper, $_POST['ldap_serverconfig_chooser']);
+
try {
- if ($connection->setConfiguration($_POST)) {
+ $configurationOk = true;
+ $conf = $connection->getConfiguration();
+ if ($conf['ldap_configuration_active'] === '0') {
+ //needs to be true, otherwise it will also fail with an irritating message
+ $conf['ldap_configuration_active'] = '1';
+ $configurationOk = $connection->setConfiguration($conf);
+ }
+ if ($configurationOk) {
+ //Configuration is okay
/*
* Clossing the session since it won't be used from this point on. There might be a potential
* race condition if a second request is made: either this request or the other might not
@@ -46,7 +53,6 @@ try {
* problem with that other than the extra connection.
*/
\OC::$server->getSession()->close();
- //Configuration is okay
if ($connection->bind()) {
/*
* This shiny if block is an ugly hack to find out whether anonymous
diff --git a/apps/user_ldap/js/wizard/configModel.js b/apps/user_ldap/js/wizard/configModel.js
index c3f1e85b592..3732409c3e1 100644
--- a/apps/user_ldap/js/wizard/configModel.js
+++ b/apps/user_ldap/js/wizard/configModel.js
@@ -318,7 +318,7 @@ OCA = OCA || {};
*/
requestConfigurationTest: function() {
var url = OC.generateUrl('apps/user_ldap/ajax/testConfiguration.php');
- var params = OC.buildQueryString(this.configuration);
+ var params = OC.buildQueryString({ldap_serverconfig_chooser: this.configID});
var model = this;
$.post(url, params, function(result) { model._processTestResult(model, result) });
//TODO: make sure only one test is running at a time
diff --git a/apps/user_ldap/js/wizard/view.js b/apps/user_ldap/js/wizard/view.js
index 9c7e2132dc6..1a89eba3515 100644
--- a/apps/user_ldap/js/wizard/view.js
+++ b/apps/user_ldap/js/wizard/view.js
@@ -271,7 +271,7 @@ OCA = OCA || {};
* requests a configuration test
*/
onTestButtonClick: function() {
- this.configModel.requestWizard('ldap_action_test_connection', this.configModel.configuration);
+ this.configModel.requestWizard('ldap_action_test_connection', {ldap_serverconfig_chooser: this.configModel.configID});
},
/**