diff options
98 files changed, 2478 insertions, 175 deletions
diff --git a/apps/dav/lib/rootcollection.php b/apps/dav/lib/rootcollection.php index c1635c9cde5..9ee32822bbd 100644 --- a/apps/dav/lib/rootcollection.php +++ b/apps/dav/lib/rootcollection.php @@ -33,6 +33,13 @@ class RootCollection extends SimpleCollection { $caldavBackend = new CalDavBackend($db); $calendarRoot = new CalendarRoot($principalBackend, $caldavBackend, 'principals/users'); $calendarRoot->disableListing = $disableListing; + $systemTagCollection = new SystemTag\SystemTagsByIdCollection( + \OC::$server->getSystemTagManager() + ); + $systemTagRelationsCollection = new SystemTag\SystemTagsRelationsCollection( + \OC::$server->getSystemTagManager(), + \OC::$server->getSystemTagObjectMapper() + ); $usersCardDavBackend = new CardDavBackend($db, $principalBackend); $usersAddressBookRoot = new AddressBookRoot($principalBackend, $usersCardDavBackend, 'principals/users'); @@ -51,6 +58,8 @@ class RootCollection extends SimpleCollection { new SimpleCollection('addressbooks', [ $usersAddressBookRoot, $systemAddressBookRoot]), + $systemTagCollection, + $systemTagRelationsCollection, ]; parent::__construct('root', $children); diff --git a/apps/dav/lib/server.php b/apps/dav/lib/server.php index a031f2c442b..ffcbb02db70 100644 --- a/apps/dav/lib/server.php +++ b/apps/dav/lib/server.php @@ -60,6 +60,9 @@ class Server { // addressbook plugins $this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin()); + // system tags plugins + $this->server->addPlugin(new \OCA\DAV\SystemTag\SystemTagPlugin(\OC::$server->getSystemTagManager())); + // Finder on OS X requires Class 2 WebDAV support (locking), since we do // not provide locking we emulate it using a fake locking plugin. if($request->isUserAgent(['/WebDAVFS/'])) { diff --git a/apps/dav/lib/systemtag/systemtagmappingnode.php b/apps/dav/lib/systemtag/systemtagmappingnode.php new file mode 100644 index 00000000000..cbf8542a4fd --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagmappingnode.php @@ -0,0 +1,102 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\NotFound; + +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; +use OCP\SystemTag\TagNotFoundException; + +/** + * Mapping node for system tag to object id + */ +class SystemTagMappingNode extends SystemTagNode { + + /** + * @var ISystemTagObjectMapper + */ + private $tagMapper; + + /** + * @var string + */ + private $objectId; + + /** + * @var string + */ + private $objectType; + + /** + * Sets up the node, expects a full path name + * + * @param ISystemTag $tag system tag + * @param string $objectId + * @param string $objectType + * @param ISystemTagManager $tagManager + * @param ISystemTagObjectMapper $tagMapper + */ + public function __construct( + ISystemTag $tag, + $objectId, + $objectType, + ISystemTagManager $tagManager, + ISystemTagObjectMapper $tagMapper + ) { + $this->objectId = $objectId; + $this->objectType = $objectType; + $this->tagMapper = $tagMapper; + parent::__construct($tag, $tagManager); + } + + /** + * Returns the object id of the relationship + * + * @return string object id + */ + public function getObjectId() { + return $this->objectId; + } + + /** + * Returns the object type of the relationship + * + * @return string object type + */ + public function getObjectType() { + return $this->objectType; + } + + /** + * Delete tag to object association + */ + public function delete() { + try { + $this->tagMapper->unassignTags($this->objectId, $this->objectType, $this->tag->getId()); + } catch (TagNotFoundException $e) { + // can happen if concurrent deletion occurred + throw new NotFound('Tag with id ' . $this->tag->getId() . ' not found', 0, $e); + } + } +} diff --git a/apps/dav/lib/systemtag/systemtagnode.php b/apps/dav/lib/systemtag/systemtagnode.php new file mode 100644 index 00000000000..7ab4a8a14f4 --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagnode.php @@ -0,0 +1,126 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\Conflict; + +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagAlreadyExistsException; + +/** + * DAV node representing a system tag, with the name being the tag id. + */ +class SystemTagNode implements \Sabre\DAV\INode { + + /** + * @var ISystemTag + */ + protected $tag; + + /** + * @var ISystemTagManager + */ + protected $tagManager; + + /** + * Sets up the node, expects a full path name + * + * @param ISystemTag $tag system tag + * @param ISystemTagManager $tagManager + */ + public function __construct(ISystemTag $tag, ISystemTagManager $tagManager) { + $this->tag = $tag; + $this->tagManager = $tagManager; + } + + /** + * Returns the id of the tag + * + * @return string + */ + public function getName() { + return $this->tag->getId(); + } + + /** + * Returns the system tag represented by this node + * + * @return ISystemTag system tag + */ + public function getSystemTag() { + return $this->tag; + } + + /** + * Renames the node + * + * @param string $name The new name + * + * @throws MethodNotAllowed not allowed to rename node + */ + public function setName($name) { + throw new MethodNotAllowed(); + } + + /** + * Update tag + * + * @param string $name new tag name + * @param bool $userVisible user visible + * @param bool $userAssignable user assignable + * @throws NotFound whenever the given tag id does not exist + * @throws Conflict whenever a tag already exists with the given attributes + */ + public function update($name, $userVisible, $userAssignable) { + try { + $this->tagManager->updateTag($this->tag->getId(), $name, $userVisible, $userAssignable); + } catch (TagNotFoundException $e) { + throw new NotFound('Tag with id ' . $this->tag->getId() . ' does not exist'); + } catch (TagAlreadyExistsException $e) { + throw new Conflict( + 'Tag with the properties "' . $name . '", ' . + $userVisible . ', ' . $userAssignable . ' already exists' + ); + } + } + + /** + * Returns null, not supported + * + */ + public function getLastModified() { + return null; + } + + public function delete() { + try { + $this->tagManager->deleteTags($this->tag->getId()); + } catch (TagNotFoundException $e) { + // can happen if concurrent deletion occurred + throw new NotFound('Tag with id ' . $this->tag->getId() . ' not found', 0, $e); + } + } +} diff --git a/apps/dav/lib/systemtag/systemtagplugin.php b/apps/dav/lib/systemtag/systemtagplugin.php new file mode 100644 index 00000000000..51db0632549 --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagplugin.php @@ -0,0 +1,249 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\PropFind; +use Sabre\DAV\PropPatch; +use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\Exception\UnsupportedMediaType; +use Sabre\DAV\Exception\Conflict; + +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\TagAlreadyExistsException; +use Sabre\HTTP\RequestInterface; +use Sabre\HTTP\ResponseInterface; + +/** + * Sabre plugin to handle system tags: + * + * - makes it possible to create new tags with POST operation + * - get/set Webdav properties for tags + * + */ +class SystemTagPlugin extends \Sabre\DAV\ServerPlugin { + + // namespace + const NS_OWNCLOUD = 'http://owncloud.org/ns'; + const ID_PROPERTYNAME = '{http://owncloud.org/ns}id'; + const DISPLAYNAME_PROPERTYNAME = '{http://owncloud.org/ns}display-name'; + const USERVISIBLE_PROPERTYNAME = '{http://owncloud.org/ns}user-visible'; + const USERASSIGNABLE_PROPERTYNAME = '{http://owncloud.org/ns}user-assignable'; + + /** + * @var \Sabre\DAV\Server $server + */ + private $server; + + /** + * @var ISystemTagManager + */ + protected $tagManager; + + /** + * System tags plugin + * + * @param ISystemTagManager $tagManager tag manager + */ + public function __construct(ISystemTagManager $tagManager) { + $this->tagManager = $tagManager; + } + + /** + * This initializes the plugin. + * + * This function is called by \Sabre\DAV\Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param \Sabre\DAV\Server $server + * @return void + */ + public function initialize(\Sabre\DAV\Server $server) { + + $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc'; + + $server->protectedProperties[] = self::ID_PROPERTYNAME; + + $server->on('propFind', array($this, 'handleGetProperties')); + $server->on('propPatch', array($this, 'handleUpdateProperties')); + $server->on('method:POST', [$this, 'httpPost']); + + $this->server = $server; + } + + /** + * POST operation on system tag collections + * + * @param RequestInterface $request request object + * @param ResponseInterface $response response object + * @return null|false + */ + public function httpPost(RequestInterface $request, ResponseInterface $response) { + $path = $request->getPath(); + + // Making sure the node exists + try { + $node = $this->server->tree->getNodeForPath($path); + } catch (NotFound $e) { + return null; + } + + if ($node instanceof SystemTagsByIdCollection || $node instanceof SystemTagsObjectMappingCollection) { + $data = $request->getBodyAsString(); + + $tag = $this->createTag($data, $request->getHeader('Content-Type')); + + if ($node instanceof SystemTagsObjectMappingCollection) { + // also add to collection + $node->createFile($tag->getId()); + $url = $request->getBaseUrl() . 'systemtags/'; + } else { + $url = $request->getUrl(); + } + + if ($url[strlen($url) - 1] !== '/') { + $url .= '/'; + } + + $response->setHeader('Location', $url . $tag->getId()); + + // created + $response->setStatus(201); + return false; + } + } + + /** + * Creates a new tag + * + * @param string $data JSON encoded string containing the properties of the tag to create + * @param string $contentType content type of the data + * @return ISystemTag newly created system tag + * + * @throws BadRequest if a field was missing + * @throws Conflict if a tag with the same properties already exists + * @throws UnsupportedMediaType if the content type is not supported + */ + private function createTag($data, $contentType = 'application/json') { + if ($contentType === 'application/json') { + $data = json_decode($data, true); + } else { + throw new UnsupportedMediaType(); + } + + if (!isset($data['name'])) { + throw new BadRequest('Missing "name" attribute'); + } + + $tagName = $data['name']; + $userVisible = true; + $userAssignable = true; + + if (isset($data['userVisible'])) { + $userVisible = (bool)$data['userVisible']; + } + + if (isset($data['userAssignable'])) { + $userAssignable = (bool)$data['userAssignable']; + } + try { + return $this->tagManager->createTag($tagName, $userVisible, $userAssignable); + } catch (TagAlreadyExistsException $e) { + throw new Conflict('Tag already exists', 0, $e); + } + } + + + /** + * Retrieves system tag properties + * + * @param PropFind $propFind + * @param \Sabre\DAV\INode $node + */ + public function handleGetProperties( + PropFind $propFind, + \Sabre\DAV\INode $node + ) { + if (!($node instanceof SystemTagNode)) { + return; + } + + $propFind->handle(self::ID_PROPERTYNAME, function() use ($node) { + return $node->getSystemTag()->getId(); + }); + + $propFind->handle(self::DISPLAYNAME_PROPERTYNAME, function() use ($node) { + return $node->getSystemTag()->getName(); + }); + + $propFind->handle(self::USERVISIBLE_PROPERTYNAME, function() use ($node) { + return (int)$node->getSystemTag()->isUserVisible(); + }); + + $propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function() use ($node) { + return (int)$node->getSystemTag()->isUserAssignable(); + }); + } + + /** + * Updates tag attributes + * + * @param string $path + * @param PropPatch $propPatch + * + * @return void + */ + public function handleUpdateProperties($path, PropPatch $propPatch) { + $propPatch->handle([ + self::DISPLAYNAME_PROPERTYNAME, + self::USERVISIBLE_PROPERTYNAME, + self::USERASSIGNABLE_PROPERTYNAME, + ], function($props) use ($path) { + $node = $this->server->tree->getNodeForPath($path); + if (!($node instanceof SystemTagNode)) { + return; + } + + $tag = $node->getSystemTag(); + $name = $tag->getName(); + $userVisible = $tag->isUserVisible(); + $userAssignable = $tag->isUserAssignable(); + + if (isset($props[self::DISPLAYNAME_PROPERTYNAME])) { + $name = $props[self::DISPLAYNAME_PROPERTYNAME]; + } + + if (isset($props[self::USERVISIBLE_PROPERTYNAME])) { + $userVisible = (bool)$props[self::USERVISIBLE_PROPERTYNAME]; + } + + if (isset($props[self::USERASSIGNABLE_PROPERTYNAME])) { + $userAssignable = (bool)$props[self::USERASSIGNABLE_PROPERTYNAME]; + } + + $node->update($name, $userVisible, $userAssignable); + return true; + }); + } +} diff --git a/apps/dav/lib/systemtag/systemtagsbyidcollection.php b/apps/dav/lib/systemtag/systemtagsbyidcollection.php new file mode 100644 index 00000000000..e7b7b6d0acc --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagsbyidcollection.php @@ -0,0 +1,117 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\ICollection; + +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\TagNotFoundException; + +class SystemTagsByIdCollection implements ICollection { + + /** + * @var ISystemTagManager + */ + private $tagManager; + + /** + * SystemTagsByIdCollection constructor. + * + * @param ISystemTagManager $tagManager + */ + public function __construct($tagManager) { + $this->tagManager = $tagManager; + } + + function createFile($name, $data = null) { + throw new Forbidden('Cannot create tags by id'); + } + + function createDirectory($name) { + throw new Forbidden('Permission denied to create collections'); + } + + function getChild($name) { + try { + $tags = $this->tagManager->getTagsByIds([$name]); + return $this->makeNode(current($tags)); + } catch (\InvalidArgumentException $e) { + throw new BadRequest('Invalid tag id', 0, $e); + } catch (TagNotFoundException $e) { + throw new NotFound('Tag with id ' . $name . ' not found', 0, $e); + } + } + + function getChildren() { + $tags = $this->tagManager->getAllTags(true); + return array_map(function($tag) { + return $this->makeNode($tag); + }, $tags); + } + + function childExists($name) { + try { + $this->tagManager->getTagsByIds([$name]); + return true; + } catch (\InvalidArgumentException $e) { + throw new BadRequest('Invalid tag id', 0, $e); + } catch (TagNotFoundException $e) { + return false; + } + } + + function delete() { + throw new Forbidden('Permission denied to delete this collection'); + } + + function getName() { + return 'systemtags'; + } + + function setName($name) { + throw new Forbidden('Permission denied to rename this collection'); + } + + /** + * Returns the last modification time, as a unix timestamp + * + * @return int + */ + function getLastModified() { + return null; + } + + /** + * Create a sabre node for the given system tag + * + * @param ISystemTag $tag + * + * @return SystemTagNode + */ + private function makeNode(ISystemTag $tag) { + return new SystemTagNode($tag, $this->tagManager); + } +} diff --git a/apps/dav/lib/systemtag/systemtagsobjectmappingcollection.php b/apps/dav/lib/systemtag/systemtagsobjectmappingcollection.php new file mode 100644 index 00000000000..89e8620614b --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagsobjectmappingcollection.php @@ -0,0 +1,160 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\BadRequest; +use Sabre\DAV\Exception\PreconditionFailed; +use Sabre\DAV\ICollection; + +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; +use OCP\SystemTag\ISystemTag; +use OCP\SystemTag\TagNotFoundException; + +/** + * Collection containing tags by object id + */ +class SystemTagsObjectMappingCollection implements ICollection { + + /** + * @var string + */ + private $objectId; + + /** + * @var string + */ + private $objectType; + + /** + * @var ISystemTagManager + */ + private $tagManager; + + /** + * @var ISystemTagObjectMapper + */ + private $tagMapper; + + /** + * Constructor + * + * @param string $objectId object id + * @param string $objectType object type + * @param ISystemTagManager $tagManager + * @param ISystemTagObjectMapper $tagMapper + */ + public function __construct($objectId, $objectType, $tagManager, $tagMapper) { + $this->tagManager = $tagManager; + $this->tagMapper = $tagMapper; + $this->objectId = $objectId; + $this->objectType = $objectType; + } + + function createFile($tagId, $data = null) { + try { + $this->tagMapper->assignTags($this->objectId, $this->objectType, $tagId); + } catch (TagNotFoundException $e) { + throw new PreconditionFailed('Tag with id ' . $tagId . ' does not exist, cannot assign'); + } + } + + function createDirectory($name) { + throw new Forbidden('Permission denied to create collections'); + } + + function getChild($tagId) { + try { + if ($this->tagMapper->haveTag([$this->objectId], $this->objectType, $tagId, true)) { + $tag = $this->tagManager->getTagsByIds([$tagId]); + return $this->makeNode(current($tag)); + } + throw new NotFound('Tag with id ' . $tagId . ' not present for object ' . $this->objectId); + } catch (\InvalidArgumentException $e) { + throw new BadRequest('Invalid tag id', 0, $e); + } catch (TagNotFoundException $e) { + throw new NotFound('Tag with id ' . $tagId . ' not found', 0, $e); + } + } + + function getChildren() { + $tagIds = current($this->tagMapper->getTagIdsForObjects([$this->objectId], $this->objectType)); + if (empty($tagIds)) { + return []; + } + $tags = $this->tagManager->getTagsByIds($tagIds); + return array_values(array_map(function($tag) { + return $this->makeNode($tag); + }, $tags)); + } + + function childExists($tagId) { + try { + return ($this->tagMapper->haveTag([$this->objectId], $this->objectType, $tagId, true)); + } catch (\InvalidArgumentException $e) { + throw new BadRequest('Invalid tag id', 0, $e); + } catch (TagNotFoundException $e) { + return false; + } + } + + function delete() { + throw new Forbidden('Permission denied to delete this collection'); + } + + function getName() { + return $this->objectId; + } + + function setName($name) { + throw new Forbidden('Permission denied to rename this collection'); + } + + /** + * Returns the last modification time, as a unix timestamp + * + * @return int + */ + function getLastModified() { + return null; + } + + /** + * Create a sabre node for the mapping of the + * given system tag to the collection's object + * + * @param ISystemTag $tag + * + * @return SystemTagNode + */ + private function makeNode(ISystemTag $tag) { + return new SystemTagMappingNode( + $tag, + $this->objectId, + $this->objectType, + $this->tagManager, + $this->tagMapper + ); + } +} diff --git a/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php b/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php new file mode 100644 index 00000000000..e544073613f --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagsobjecttypecollection.php @@ -0,0 +1,110 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\ICollection; + +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; + +/** + * Collection containing object ids by object type + */ +class SystemTagsObjectTypeCollection implements ICollection { + + /** + * @var string + */ + private $objectType; + + /** + * @var ISystemTagManager + */ + private $tagManager; + + /** + * @var ISystemTagObjectMapper + */ + private $tagMapper; + + /** + * Constructor + * + * @param string $objectType object type + * @param ISystemTagManager $tagManager + * @param ISystemTagObjectMapper $tagMapper + */ + public function __construct($objectType, $tagManager, $tagMapper) { + $this->tagManager = $tagManager; + $this->tagMapper = $tagMapper; + $this->objectType = $objectType; + } + + function createFile($name, $data = null) { + throw new Forbidden('Permission denied to create nodes'); + } + + function createDirectory($name) { + throw new Forbidden('Permission denied to create collections'); + } + + function getChild($objectId) { + return new SystemTagsObjectMappingCollection( + $objectId, + $this->objectType, + $this->tagManager, + $this->tagMapper + ); + } + + function getChildren() { + // do not list object ids + throw new MethodNotAllowed(); + } + + function childExists($name) { + return true; + } + + function delete() { + throw new Forbidden('Permission denied to delete this collection'); + } + + function getName() { + return $this->objectType; + } + + function setName($name) { + throw new Forbidden('Permission denied to rename this collection'); + } + + /** + * Returns the last modification time, as a unix timestamp + * + * @return int + */ + function getLastModified() { + return null; + } +} diff --git a/apps/dav/lib/systemtag/systemtagsrelationscollection.php b/apps/dav/lib/systemtag/systemtagsrelationscollection.php new file mode 100644 index 00000000000..44069bca02c --- /dev/null +++ b/apps/dav/lib/systemtag/systemtagsrelationscollection.php @@ -0,0 +1,53 @@ +<?php +/** + * @author Vincent Petry <pvince81@owncloud.com> + * + * @copyright Copyright (c) 2015, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\SystemTag; + +use OCP\SystemTag\ISystemTagManager; +use OCP\SystemTag\ISystemTagObjectMapper; +use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\SimpleCollection; + +class SystemTagsRelationsCollection extends SimpleCollection { + + /** + * SystemTagsRelationsCollection constructor. + * + * @param ISystemTagManager $tagManager + * @param ISystemTagObjectMapper $tagMapper + */ + public function __construct($tagManager, $tagMapper) { + $children = [ + new SystemTagsObjectTypeCollection('files', $tagManager, $tagMapper), + ]; + + parent::__construct('root', $children); + } + + function getName() { + return 'systemtags-relations'; + } + + function setName($name) { + throw new Forbidden('Permission denied to rename this collection'); + } + +} diff --git a/apps/dav/tests/unit/systemtag/systemtagmappingnode.php b/apps/dav/tests/unit/systemtag/systemtagmappingnode.php new file mode 100644 index 00000000000..849f7c2fa54 --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagmappingnode.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\Conflict; + +use OC\SystemTag\SystemTag; +use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagAlreadyExistsException; + +class SystemTagMappingNode extends SystemTagNode { + + /** + * @var \OCA\DAV\SystemTag\SystemTagMappingNode + */ + private $node; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + /** + * @var \OCP\SystemTag\ISystemTagObjectMapper + */ + private $tagMapper; + + /** + * @var \OCP\SystemTag\ISystemTag + */ + private $tag; + + protected function setUp() { + parent::setUp(); + + $this->tag = new SystemTag(1, 'Test', true, false); + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + $this->tagMapper = $this->getMock('\OCP\SystemTag\ISystemTagObjectMapper'); + + $this->node = new \OCA\DAV\SystemTag\SystemTagMappingNode( + $this->tag, + 123, + 'files', + $this->tagManager, + $this->tagMapper + ); + } + + public function testGetters() { + parent::testGetters(); + $this->assertEquals(123, $this->node->getObjectId()); + $this->assertEquals('files', $this->node->getObjectType()); + } + + public function testDeleteTag() { + $this->tagManager->expects($this->never()) + ->method('deleteTags'); + $this->tagMapper->expects($this->once()) + ->method('unassignTags') + ->with(123, 'files', 1); + + $this->node->delete(); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testDeleteTagNotFound() { + $this->tagMapper->expects($this->once()) + ->method('unassignTags') + ->with(123, 'files', 1) + ->will($this->throwException(new TagNotFoundException())); + + $this->node->delete(); + } +} diff --git a/apps/dav/tests/unit/systemtag/systemtagnode.php b/apps/dav/tests/unit/systemtag/systemtagnode.php new file mode 100644 index 00000000000..a43dda3025d --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagnode.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + +use Sabre\DAV\Exception\NotFound; +use Sabre\DAV\Exception\MethodNotAllowed; +use Sabre\DAV\Exception\Conflict; + +use OC\SystemTag\SystemTag; +use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagAlreadyExistsException; + +class SystemTagNode extends \Test\TestCase { + + /** + * @var \OCA\DAV\SystemTag\SystemTagNode + */ + private $node; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + /** + * @var \OCP\SystemTag\ISystemTag + */ + private $tag; + + protected function setUp() { + parent::setUp(); + + $this->tag = new SystemTag(1, 'Test', true, false); + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + + $this->node = new \OCA\DAV\SystemTag\SystemTagNode($this->tag, $this->tagManager); + } + + public function testGetters() { + $this->assertEquals('1', $this->node->getName()); + $this->assertEquals($this->tag, $this->node->getSystemTag()); + } + + /** + * @expectedException Sabre\DAV\Exception\MethodNotAllowed + */ + public function testSetName() { + $this->node->setName('2'); + } + + public function testUpdateTag() { + $this->tagManager->expects($this->once()) + ->method('updateTag') + ->with(1, 'Renamed', false, true); + $this->node->update('Renamed', false, true); + } + + /** + * @expectedException Sabre\DAV\Exception\Conflict + */ + public function testUpdateTagAlreadyExists() { + $this->tagManager->expects($this->once()) + ->method('updateTag') + ->with(1, 'Renamed', false, true) + ->will($this->throwException(new TagAlreadyExistsException())); + $this->node->update('Renamed', false, true); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testUpdateTagNotFound() { + $this->tagManager->expects($this->once()) + ->method('updateTag') + ->with(1, 'Renamed', false, true) + ->will($this->throwException(new TagNotFoundException())); + $this->node->update('Renamed', false, true); + } + + public function testDeleteTag() { + $this->tagManager->expects($this->once()) + ->method('deleteTags') + ->with('1'); + $this->node->delete(); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testDeleteTagNotFound() { + $this->tagManager->expects($this->once()) + ->method('deleteTags') + ->with('1') + ->will($this->throwException(new TagNotFoundException())); + $this->node->delete(); + } +} diff --git a/apps/dav/tests/unit/systemtag/systemtagplugin.php b/apps/dav/tests/unit/systemtag/systemtagplugin.php new file mode 100644 index 00000000000..48c9aa69f7b --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagplugin.php @@ -0,0 +1,308 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + +use OC\SystemTag\SystemTag; +use OCP\SystemTag\TagAlreadyExistsException; + +class SystemTagPlugin extends \Test\TestCase { + + const ID_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::ID_PROPERTYNAME; + const DISPLAYNAME_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::DISPLAYNAME_PROPERTYNAME; + const USERVISIBLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USERVISIBLE_PROPERTYNAME; + const USERASSIGNABLE_PROPERTYNAME = \OCA\DAV\SystemTag\SystemTagPlugin::USERASSIGNABLE_PROPERTYNAME; + + /** + * @var \Sabre\DAV\Server + */ + private $server; + + /** + * @var \Sabre\DAV\Tree + */ + private $tree; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + /** + * @var \OCA\DAV\Connector\Sabre\TagsPlugin + */ + private $plugin; + + public function setUp() { + parent::setUp(); + $this->tree = $this->getMockBuilder('\Sabre\DAV\Tree') + ->disableOriginalConstructor() + ->getMock(); + + $this->server = new \Sabre\DAV\Server($this->tree); + + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + + $this->plugin = new \OCA\DAV\SystemTag\SystemTagPlugin($this->tagManager); + $this->plugin->initialize($this->server); + } + + public function testGetProperties() { + $systemTag = new SystemTag(1, 'Test', true, true); + $requestedProperties = [ + self::ID_PROPERTYNAME, + self::DISPLAYNAME_PROPERTYNAME, + self::USERVISIBLE_PROPERTYNAME, + self::USERASSIGNABLE_PROPERTYNAME + ]; + $expectedProperties = [ + 200 => [ + self::ID_PROPERTYNAME => '1', + self::DISPLAYNAME_PROPERTYNAME => 'Test', + self::USERVISIBLE_PROPERTYNAME => 1, + self::USERASSIGNABLE_PROPERTYNAME => 1, + ] + ]; + + $node = $this->getMockBuilder('\OCA\DAV\SystemTag\SystemTagNode') + ->disableOriginalConstructor() + ->getMock(); + $node->expects($this->any()) + ->method('getSystemTag') + ->will($this->returnValue($systemTag)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/systemtag/1') + ->will($this->returnValue($node)); + + $propFind = new \Sabre\DAV\PropFind( + '/systemtag/1', + $requestedProperties, + 0 + ); + + $this->plugin->handleGetProperties( + $propFind, + $node + ); + + $result = $propFind->getResultForMultiStatus(); + + $this->assertEmpty($result[404]); + unset($result[404]); + $this->assertEquals($expectedProperties, $result); + } + + public function testUpdateProperties() { + $systemTag = new SystemTag(1, 'Test', true, false); + $node = $this->getMockBuilder('\OCA\DAV\SystemTag\SystemTagNode') + ->disableOriginalConstructor() + ->getMock(); + $node->expects($this->any()) + ->method('getSystemTag') + ->will($this->returnValue($systemTag)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/systemtag/1') + ->will($this->returnValue($node)); + + $node->expects($this->once()) + ->method('update') + ->with('Test changed', false, true); + + // properties to set + $propPatch = new \Sabre\DAV\PropPatch(array( + self::DISPLAYNAME_PROPERTYNAME => 'Test changed', + self::USERVISIBLE_PROPERTYNAME => 0, + self::USERASSIGNABLE_PROPERTYNAME => 1, + )); + + $this->plugin->handleUpdateProperties( + '/systemtag/1', + $propPatch + ); + + $propPatch->commit(); + + // all requested properties removed, as they were processed already + $this->assertEmpty($propPatch->getRemainingMutations()); + + $result = $propPatch->getResult(); + $this->assertEquals(200, $result[self::DISPLAYNAME_PROPERTYNAME]); + $this->assertEquals(200, $result[self::USERASSIGNABLE_PROPERTYNAME]); + $this->assertEquals(200, $result[self::USERVISIBLE_PROPERTYNAME]); + } + + public function testCreateTagInByIdCollection() { + $systemTag = new SystemTag(1, 'Test', true, false); + + $requestData = json_encode([ + 'name' => 'Test', + 'userVisible' => true, + 'userAssignable' => false, + ]); + + $node = $this->getMockBuilder('\OCA\DAV\SystemTag\SystemTagsByIdCollection') + ->disableOriginalConstructor() + ->getMock(); + $this->tagManager->expects($this->once()) + ->method('createTag') + ->with('Test', true, false) + ->will($this->returnValue($systemTag)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/systemtags') + ->will($this->returnValue($node)); + + $request = $this->getMockBuilder('Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $response = $this->getMockBuilder('Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('/systemtags')); + + $request->expects($this->once()) + ->method('getBodyAsString') + ->will($this->returnValue($requestData)); + + $request->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->will($this->returnValue('application/json')); + + $request->expects($this->once()) + ->method('getUrl') + ->will($this->returnValue('http://example.com/dav/systemtags')); + + $response->expects($this->once()) + ->method('setHeader') + ->with('Location', 'http://example.com/dav/systemtags/1'); + + $this->plugin->httpPost($request, $response); + } + + public function nodeClassProvider() { + return [ + ['\OCA\DAV\SystemTag\SystemTagsByIdCollection'], + ['\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection'], + ]; + } + + public function testCreateTagInMappingCollection() { + $systemTag = new SystemTag(1, 'Test', true, false); + + $requestData = json_encode([ + 'name' => 'Test', + 'userVisible' => true, + 'userAssignable' => false, + ]); + + $node = $this->getMockBuilder('\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection') + ->disableOriginalConstructor() + ->getMock(); + + $this->tagManager->expects($this->once()) + ->method('createTag') + ->with('Test', true, false) + ->will($this->returnValue($systemTag)); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/systemtags-relations/files/12') + ->will($this->returnValue($node)); + + $node->expects($this->once()) + ->method('createFile') + ->with(1); + + $request = $this->getMockBuilder('Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $response = $this->getMockBuilder('Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('/systemtags-relations/files/12')); + + $request->expects($this->once()) + ->method('getBodyAsString') + ->will($this->returnValue($requestData)); + + $request->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->will($this->returnValue('application/json')); + + $request->expects($this->once()) + ->method('getBaseUrl') + ->will($this->returnValue('http://example.com/dav/')); + + $response->expects($this->once()) + ->method('setHeader') + ->with('Location', 'http://example.com/dav/systemtags/1'); + + $this->plugin->httpPost($request, $response); + } + + /** + * @dataProvider nodeClassProvider + * @expectedException Sabre\DAV\Exception\Conflict + */ + public function testCreateTagConflict($nodeClass) { + $requestData = json_encode([ + 'name' => 'Test', + 'userVisible' => true, + 'userAssignable' => false, + ]); + + $node = $this->getMockBuilder($nodeClass) + ->disableOriginalConstructor() + ->getMock(); + $this->tagManager->expects($this->once()) + ->method('createTag') + ->with('Test', true, false) + ->will($this->throwException(new TagAlreadyExistsException('Tag already exists'))); + + $this->tree->expects($this->any()) + ->method('getNodeForPath') + ->with('/systemtags') + ->will($this->returnValue($node)); + + $request = $this->getMockBuilder('Sabre\HTTP\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + $response = $this->getMockBuilder('Sabre\HTTP\ResponseInterface') + ->disableOriginalConstructor() + ->getMock(); + + $request->expects($this->once()) + ->method('getPath') + ->will($this->returnValue('/systemtags')); + + $request->expects($this->once()) + ->method('getBodyAsString') + ->will($this->returnValue($requestData)); + + $request->expects($this->once()) + ->method('getHeader') + ->with('Content-Type') + ->will($this->returnValue('application/json')); + + $this->plugin->httpPost($request, $response); + } + +} diff --git a/apps/dav/tests/unit/systemtag/systemtagsbyidcollection.php b/apps/dav/tests/unit/systemtag/systemtagsbyidcollection.php new file mode 100644 index 00000000000..104ce366034 --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagsbyidcollection.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + + +use OC\SystemTag\SystemTag; +use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagAlreadyExistsException; + +class SystemTagsByIdCollection extends \Test\TestCase { + + /** + * @var \OCA\DAV\SystemTag\SystemTagsByIdCollection + */ + private $node; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + protected function setUp() { + parent::setUp(); + + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + + $this->node = new \OCA\DAV\SystemTag\SystemTagsByIdCollection($this->tagManager); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testForbiddenCreateFile() { + $this->node->createFile('555'); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testForbiddenCreateDirectory() { + $this->node->createDirectory('789'); + } + + public function testGetChild() { + $tag = new SystemTag(123, 'Test', true, false); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['123']) + ->will($this->returnValue([$tag])); + + $childNode = $this->node->getChild('123'); + + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagNode', $childNode); + $this->assertEquals('123', $childNode->getName()); + $this->assertEquals($tag, $childNode->getSystemTag()); + } + + /** + * @expectedException Sabre\DAV\Exception\BadRequest + */ + public function testGetChildInvalidName() { + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['invalid']) + ->will($this->throwException(new \InvalidArgumentException())); + + $this->node->getChild('invalid'); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testGetChildNotFound() { + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['444']) + ->will($this->throwException(new TagNotFoundException())); + + $this->node->getChild('444'); + } + + public function testGetChildren() { + $tag1 = new SystemTag(123, 'One', true, false); + $tag2 = new SystemTag(456, 'Two', true, true); + + $this->tagManager->expects($this->once()) + ->method('getAllTags') + ->with(true) + ->will($this->returnValue([$tag1, $tag2])); + + $children = $this->node->getChildren(); + + $this->assertCount(2, $children); + + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagNode', $children[0]); + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagNode', $children[1]); + $this->assertEquals($tag1, $children[0]->getSystemTag()); + $this->assertEquals($tag2, $children[1]->getSystemTag()); + } + + public function testGetChildrenEmpty() { + $this->tagManager->expects($this->once()) + ->method('getAllTags') + ->with(true) + ->will($this->returnValue([])); + $this->assertCount(0, $this->node->getChildren()); + } + + public function testChildExists() { + $tag = new SystemTag(123, 'One', true, false); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['123']) + ->will($this->returnValue([$tag])); + + $this->assertTrue($this->node->childExists('123')); + } + + public function testChildExistsNotFound() { + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['123']) + ->will($this->throwException(new TagNotFoundException())); + + $this->assertFalse($this->node->childExists('123')); + } + + /** + * @expectedException Sabre\DAV\Exception\BadRequest + */ + public function testChildExistsBadRequest() { + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['invalid']) + ->will($this->throwException(new \InvalidArgumentException())); + + $this->node->childExists('invalid'); + } +} diff --git a/apps/dav/tests/unit/systemtag/systemtagsobjectmappingcollection.php b/apps/dav/tests/unit/systemtag/systemtagsobjectmappingcollection.php new file mode 100644 index 00000000000..6e15bb78e7c --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagsobjectmappingcollection.php @@ -0,0 +1,215 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + + +use OC\SystemTag\SystemTag; +use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagAlreadyExistsException; + +class SystemTagsObjectMappingCollection extends \Test\TestCase { + + /** + * @var \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection + */ + private $node; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + /** + * @var \OCP\SystemTag\ISystemTagMapper + */ + private $tagMapper; + + protected function setUp() { + parent::setUp(); + + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + $this->tagMapper = $this->getMock('\OCP\SystemTag\ISystemTagObjectMapper'); + + $this->node = new \OCA\DAV\SystemTag\SystemTagsObjectMappingCollection ( + 111, + 'files', + $this->tagManager, + $this->tagMapper + ); + } + + public function testAssignTag() { + $this->tagMapper->expects($this->once()) + ->method('assignTags') + ->with(111, 'files', '555'); + + $this->node->createFile('555'); + } + + /** + * @expectedException Sabre\DAV\Exception\PreconditionFailed + */ + public function testAssignTagNotFound() { + $this->tagMapper->expects($this->once()) + ->method('assignTags') + ->with(111, 'files', '555') + ->will($this->throwException(new TagNotFoundException())); + + $this->node->createFile('555'); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testForbiddenCreateDirectory() { + $this->node->createDirectory('789'); + } + + public function testGetChild() { + $tag = new SystemTag(555, 'TheTag', true, false); + + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '555', true) + ->will($this->returnValue(true)); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['555']) + ->will($this->returnValue(['555' => $tag])); + + $childNode = $this->node->getChild('555'); + + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagNode', $childNode); + $this->assertEquals('555', $childNode->getName()); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testGetChildRelationNotFound() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '777') + ->will($this->returnValue(false)); + + $this->node->getChild('777'); + } + + /** + * @expectedException Sabre\DAV\Exception\BadRequest + */ + public function testGetChildInvalidId() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', 'badid') + ->will($this->throwException(new \InvalidArgumentException())); + + $this->node->getChild('badid'); + } + + /** + * @expectedException Sabre\DAV\Exception\NotFound + */ + public function testGetChildTagDoesNotExist() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '777') + ->will($this->throwException(new TagNotFoundException())); + + $this->node->getChild('777'); + } + + public function testGetChildren() { + $tag1 = new SystemTag(555, 'TagOne', true, false); + $tag2 = new SystemTag(556, 'TagTwo', true, true); + + $this->tagMapper->expects($this->once()) + ->method('getTagIdsForObjects') + ->with([111], 'files') + ->will($this->returnValue(['111' => ['555', '556']])); + + $this->tagManager->expects($this->once()) + ->method('getTagsByIds') + ->with(['555', '556']) + ->will($this->returnValue(['555' => $tag1, '666' => $tag2])); + + $children = $this->node->getChildren(); + + $this->assertCount(2, $children); + + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagMappingNode', $children[0]); + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagMappingNode', $children[1]); + + $this->assertEquals(111, $children[0]->getObjectId()); + $this->assertEquals('files', $children[0]->getObjectType()); + $this->assertEquals($tag1, $children[0]->getSystemTag()); + + $this->assertEquals(111, $children[1]->getObjectId()); + $this->assertEquals('files', $children[1]->getObjectType()); + $this->assertEquals($tag2, $children[1]->getSystemTag()); + } + + public function testChildExists() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '555') + ->will($this->returnValue(true)); + + $this->assertTrue($this->node->childExists('555')); + } + + public function testChildExistsNotFound() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '555') + ->will($this->returnValue(false)); + + $this->assertFalse($this->node->childExists('555')); + } + + public function testChildExistsTagNotFound() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '555') + ->will($this->throwException(new TagNotFoundException())); + + $this->assertFalse($this->node->childExists('555')); + } + + /** + * @expectedException Sabre\DAV\Exception\BadRequest + */ + public function testChildExistsInvalidId() { + $this->tagMapper->expects($this->once()) + ->method('haveTag') + ->with([111], 'files', '555') + ->will($this->throwException(new \InvalidArgumentException())); + + $this->node->childExists('555'); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testDelete() { + $this->node->delete(); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testSetName() { + $this->node->setName('somethingelse'); + } + + public function testGetName() { + $this->assertEquals('111', $this->node->getName()); + } +} diff --git a/apps/dav/tests/unit/systemtag/systemtagsobjecttypecollection.php b/apps/dav/tests/unit/systemtag/systemtagsobjecttypecollection.php new file mode 100644 index 00000000000..39223ff9122 --- /dev/null +++ b/apps/dav/tests/unit/systemtag/systemtagsobjecttypecollection.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright (c) 2015 Vincent Petry <pvince81@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\DAV\Tests\Unit\SystemTag; + +class SystemTagsObjectTypeCollection extends \Test\TestCase { + + /** + * @var \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection + */ + private $node; + + /** + * @var \OCP\SystemTag\ISystemTagManager + */ + private $tagManager; + + /** + * @var \OCP\SystemTag\ISystemTagMapper + */ + private $tagMapper; + + protected function setUp() { + parent::setUp(); + + $this->tagManager = $this->getMock('\OCP\SystemTag\ISystemTagManager'); + $this->tagMapper = $this->getMock('\OCP\SystemTag\ISystemTagObjectMapper'); + + $this->node = new \OCA\DAV\SystemTag\SystemTagsObjectTypeCollection( + 'files', + $this->tagManager, + $this->tagMapper + ); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testForbiddenCreateFile() { + $this->node->createFile('555'); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testForbiddenCreateDirectory() { + $this->node->createDirectory('789'); + } + + public function testGetChild() { + $childNode = $this->node->getChild('files'); + + $this->assertInstanceOf('\OCA\DAV\SystemTag\SystemTagsObjectMappingCollection', $childNode); + $this->assertEquals('files', $childNode->getName()); + } + + /** + * @expectedException Sabre\DAV\Exception\MethodNotAllowed + */ + public function testGetChildren() { + $this->node->getChildren(); + } + + public function testChildExists() { + $this->assertTrue($this->node->childExists('123')); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testDelete() { + $this->node->delete(); + } + + /** + * @expectedException Sabre\DAV\Exception\Forbidden + */ + public function testSetName() { + $this->node->setName('somethingelse'); + } + + public function testGetName() { + $this->assertEquals('files', $this->node->getName()); + } +} diff --git a/apps/files/l10n/mk.js b/apps/files/l10n/mk.js index 92616a372a3..7a387afee66 100644 --- a/apps/files/l10n/mk.js +++ b/apps/files/l10n/mk.js @@ -54,6 +54,7 @@ OC.L10N.register( "Settings" : "Подесувања", "WebDAV" : "WebDAV", "Cancel upload" : "Откажи прикачување", + "No entries found in this folder" : "Нема ништо во оваа папка", "Upload too large" : "Фајлот кој се вчитува е преголем", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Датотеките кои се обидувате да ги подигнете ја надминуваат максималната големина за подигнување датотеки на овој сервер.", "Files are being scanned, please wait." : "Се скенираат датотеки, ве молам почекајте.", diff --git a/apps/files/l10n/mk.json b/apps/files/l10n/mk.json index 147707256c6..acf8f546d73 100644 --- a/apps/files/l10n/mk.json +++ b/apps/files/l10n/mk.json @@ -52,6 +52,7 @@ "Settings" : "Подесувања", "WebDAV" : "WebDAV", "Cancel upload" : "Откажи прикачување", + "No entries found in this folder" : "Нема ништо во оваа папка", "Upload too large" : "Фајлот кој се вчитува е преголем", "The files you are trying to upload exceed the maximum size for file uploads on this server." : "Датотеките кои се обидувате да ги подигнете ја надминуваат максималната големина за подигнување датотеки на овој сервер.", "Files are being scanned, please wait." : "Се скенираат датотеки, ве молам почекајте.", diff --git a/apps/files_external/l10n/cs_CZ.js b/apps/files_external/l10n/cs_CZ.js index 94c8194e328..13ca22abcc9 100644 --- a/apps/files_external/l10n/cs_CZ.js +++ b/apps/files_external/l10n/cs_CZ.js @@ -36,6 +36,14 @@ OC.L10N.register( "(group)" : "(skupina)", "Admin defined" : "Nastaveno administrátorem", "Saved" : "Uloženo", + "Empty response from the server" : "Prázdná odpověď serveru", + "Couldn't access. Please logout and login to activate this mount point" : "Nelze připojit. Pro aktivaci tohoto přípojného bodu se prosím odhlašte a znovu přihlašte", + "Couldn't get the information from the ownCloud server: {code} {type}" : "Nelze obdržet informaci z ownCloud serveru: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "Nelze obdržet seznam vzdálených přípojných bodů: {type}", + "There was an error with message: " : "Došlo k chybě s tímto hlášením:", + "External mount error" : "Chyba vzdáleného úložiště", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "Nelze obdržet seznam síťových úložišť systému Windows: prázdná odpověď serveru", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Některá z nastavených vzdálených úložišť nejsou připojena. Pro více informací prosím klikněte na červenou šipku(y)", "Access key" : "Přístupový klíč", "Secret key" : "Tajný klíč", "Builtin" : "Zabudované", diff --git a/apps/files_external/l10n/cs_CZ.json b/apps/files_external/l10n/cs_CZ.json index 4adba2f4d04..bfcd3a30f46 100644 --- a/apps/files_external/l10n/cs_CZ.json +++ b/apps/files_external/l10n/cs_CZ.json @@ -34,6 +34,14 @@ "(group)" : "(skupina)", "Admin defined" : "Nastaveno administrátorem", "Saved" : "Uloženo", + "Empty response from the server" : "Prázdná odpověď serveru", + "Couldn't access. Please logout and login to activate this mount point" : "Nelze připojit. Pro aktivaci tohoto přípojného bodu se prosím odhlašte a znovu přihlašte", + "Couldn't get the information from the ownCloud server: {code} {type}" : "Nelze obdržet informaci z ownCloud serveru: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "Nelze obdržet seznam vzdálených přípojných bodů: {type}", + "There was an error with message: " : "Došlo k chybě s tímto hlášením:", + "External mount error" : "Chyba vzdáleného úložiště", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "Nelze obdržet seznam síťových úložišť systému Windows: prázdná odpověď serveru", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Některá z nastavených vzdálených úložišť nejsou připojena. Pro více informací prosím klikněte na červenou šipku(y)", "Access key" : "Přístupový klíč", "Secret key" : "Tajný klíč", "Builtin" : "Zabudované", diff --git a/apps/files_external/l10n/es.js b/apps/files_external/l10n/es.js index 1d49d7b13b8..6d8bf0d3139 100644 --- a/apps/files_external/l10n/es.js +++ b/apps/files_external/l10n/es.js @@ -1,13 +1,23 @@ OC.L10N.register( "files_external", { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "Fallo al acceder a los tokens solicitados. Verfique que su clave de app y la clave secreta son correctas.", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "Fallo al acceder a los tokens solicitados. Verfique que su clave de app y la clave secreta son correctas.", + "Please provide a valid app key and secret." : "Por favor facilite una clave de app y una clave secreta válidas.", "Step 1 failed. Exception: %s" : "El paso 1 falló. Excepción: %s", "Step 2 failed. Exception: %s" : "El paso 2 falló. Excepción: %s", "External storage" : "Almacenamiento externo", "Storage with id \"%i\" not found" : "No se ha encontrado almacenamiento con id \"%i\"", + "Invalid backend or authentication mechanism class" : "Sistema o mecanismo de autentificación inválido", "Invalid mount point" : "Punto de montaje no válido", + "Objectstore forbidden" : "Objeto de almacenaje prohibido", "Invalid storage backend \"%s\"" : "Motor de almacenamiento no válido «%s»", - "Not permitted to use authentication mechanism \"%s\"" : "No está permitido usar el mecanismo de autenticación \"%s\"", + "Not permitted to use backend \"%s\"" : "No se permite usar el mecanismo \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "No está permitido usar el mecanismo de autentificación \"%s\"", + "Unsatisfied backend parameters" : "Los parámetros del sistema no son válidos", + "Unsatisfied authentication mechanism parameters" : "Los parámetros del mecanismo de autentificación no son válidos", + "Insufficient data: %s" : "Datos insuficientes: %s", + "%s" : "%s", "Personal" : "Personal", "System" : "Sistema", "Grant access" : "Conceder acceso", @@ -84,7 +94,7 @@ OC.L10N.register( "Scope" : "Ámbito", "External Storage" : "Almacenamiento externo", "Folder name" : "Nombre de la carpeta", - "Authentication" : "Autenticación", + "Authentication" : "Autentificación", "Configuration" : "Configuración", "Available for" : "Disponible para", "Add storage" : "Añadir almacenamiento", diff --git a/apps/files_external/l10n/es.json b/apps/files_external/l10n/es.json index 1c60cd5fdea..bf0624e96db 100644 --- a/apps/files_external/l10n/es.json +++ b/apps/files_external/l10n/es.json @@ -1,11 +1,21 @@ { "translations": { + "Fetching request tokens failed. Verify that your app key and secret are correct." : "Fallo al acceder a los tokens solicitados. Verfique que su clave de app y la clave secreta son correctas.", + "Fetching access tokens failed. Verify that your app key and secret are correct." : "Fallo al acceder a los tokens solicitados. Verfique que su clave de app y la clave secreta son correctas.", + "Please provide a valid app key and secret." : "Por favor facilite una clave de app y una clave secreta válidas.", "Step 1 failed. Exception: %s" : "El paso 1 falló. Excepción: %s", "Step 2 failed. Exception: %s" : "El paso 2 falló. Excepción: %s", "External storage" : "Almacenamiento externo", "Storage with id \"%i\" not found" : "No se ha encontrado almacenamiento con id \"%i\"", + "Invalid backend or authentication mechanism class" : "Sistema o mecanismo de autentificación inválido", "Invalid mount point" : "Punto de montaje no válido", + "Objectstore forbidden" : "Objeto de almacenaje prohibido", "Invalid storage backend \"%s\"" : "Motor de almacenamiento no válido «%s»", - "Not permitted to use authentication mechanism \"%s\"" : "No está permitido usar el mecanismo de autenticación \"%s\"", + "Not permitted to use backend \"%s\"" : "No se permite usar el mecanismo \"%s\"", + "Not permitted to use authentication mechanism \"%s\"" : "No está permitido usar el mecanismo de autentificación \"%s\"", + "Unsatisfied backend parameters" : "Los parámetros del sistema no son válidos", + "Unsatisfied authentication mechanism parameters" : "Los parámetros del mecanismo de autentificación no son válidos", + "Insufficient data: %s" : "Datos insuficientes: %s", + "%s" : "%s", "Personal" : "Personal", "System" : "Sistema", "Grant access" : "Conceder acceso", @@ -82,7 +92,7 @@ "Scope" : "Ámbito", "External Storage" : "Almacenamiento externo", "Folder name" : "Nombre de la carpeta", - "Authentication" : "Autenticación", + "Authentication" : "Autentificación", "Configuration" : "Configuración", "Available for" : "Disponible para", "Add storage" : "Añadir almacenamiento", diff --git a/apps/files_external/l10n/fi_FI.js b/apps/files_external/l10n/fi_FI.js index b56ad195ce6..c358a2b3260 100644 --- a/apps/files_external/l10n/fi_FI.js +++ b/apps/files_external/l10n/fi_FI.js @@ -25,6 +25,8 @@ OC.L10N.register( "(group)" : "(ryhmä)", "Admin defined" : "Ylläpitäjän määrittämä", "Saved" : "Tallennettu", + "Empty response from the server" : "Tyhjä vastaus palvelimelta", + "There was an error with message: " : "Tapahtui virhe viestillä:", "Builtin" : "Sisäänrakennettu", "None" : "Ei mitään", "OAuth1" : "OAuth1", @@ -39,6 +41,7 @@ OC.L10N.register( "Rackspace" : "Rackspace", "API key" : "API-avain", "Username and password" : "Käyttäjätunnus ja salasana", + "Session credentials" : "Istunnon tunnistetiedot", "RSA public key" : "Julkinen RSA-avain", "Public key" : "Julkinen avain", "Amazon S3" : "Amazon S3", diff --git a/apps/files_external/l10n/fi_FI.json b/apps/files_external/l10n/fi_FI.json index 9ff2748b7f6..4e72d861d6f 100644 --- a/apps/files_external/l10n/fi_FI.json +++ b/apps/files_external/l10n/fi_FI.json @@ -23,6 +23,8 @@ "(group)" : "(ryhmä)", "Admin defined" : "Ylläpitäjän määrittämä", "Saved" : "Tallennettu", + "Empty response from the server" : "Tyhjä vastaus palvelimelta", + "There was an error with message: " : "Tapahtui virhe viestillä:", "Builtin" : "Sisäänrakennettu", "None" : "Ei mitään", "OAuth1" : "OAuth1", @@ -37,6 +39,7 @@ "Rackspace" : "Rackspace", "API key" : "API-avain", "Username and password" : "Käyttäjätunnus ja salasana", + "Session credentials" : "Istunnon tunnistetiedot", "RSA public key" : "Julkinen RSA-avain", "Public key" : "Julkinen avain", "Amazon S3" : "Amazon S3", diff --git a/apps/files_external/l10n/fr.js b/apps/files_external/l10n/fr.js index 8ff4fcdfdd9..8d5f7e911b7 100644 --- a/apps/files_external/l10n/fr.js +++ b/apps/files_external/l10n/fr.js @@ -17,6 +17,7 @@ OC.L10N.register( "Unsatisfied backend parameters" : "Paramètres manquants pour le service", "Unsatisfied authentication mechanism parameters" : "Paramètres manquants pour la méthode d'authentification", "Insufficient data: %s" : "Données insuffisantes : %s", + "%s" : "%s", "Personal" : "Personnel", "System" : "Système", "Grant access" : "Autoriser l'accès", diff --git a/apps/files_external/l10n/fr.json b/apps/files_external/l10n/fr.json index 9a610bd964b..cae66119a4f 100644 --- a/apps/files_external/l10n/fr.json +++ b/apps/files_external/l10n/fr.json @@ -15,6 +15,7 @@ "Unsatisfied backend parameters" : "Paramètres manquants pour le service", "Unsatisfied authentication mechanism parameters" : "Paramètres manquants pour la méthode d'authentification", "Insufficient data: %s" : "Données insuffisantes : %s", + "%s" : "%s", "Personal" : "Personnel", "System" : "Système", "Grant access" : "Autoriser l'accès", diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js index daca1d3a896..85fb70cf1a7 100644 --- a/apps/files_external/l10n/it.js +++ b/apps/files_external/l10n/it.js @@ -36,6 +36,15 @@ OC.L10N.register( "(group)" : "(gruppo)", "Admin defined" : "Definito dall'amministratore", "Saved" : "Salvato", + "Empty response from the server" : "Risposta vuota dal server", + "Couldn't access. Please logout and login to activate this mount point" : "Impossibile accedere. Termina la sessione e accedi nuovamente per attivare questo punto di mount", + "Couldn't get the information from the ownCloud server: {code} {type}" : "Impossibile ottenere le informazioni dal server ownCloud: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "Impossibile ottenere l'elenco dei punti di mount esterni: {type}", + "There was an error with message: " : "Si è verificato un errore con il messaggio:", + "External mount error" : "Errore di mount esterno", + "goto-external-storage" : "goto-external-storage", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossibile ottenere l'elenco dei punti di mount delle unità di rete Windows: risposta vuota dal server", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alcuni dei punti di mount esterni configurati non sono connessi. Fai clic sulle righe rosse per ulteriori informazioni", "Access key" : "Chiave di accesso", "Secret key" : "Chiave segreta", "Builtin" : "Integrata", diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json index 67f7fe3595b..08da52362d6 100644 --- a/apps/files_external/l10n/it.json +++ b/apps/files_external/l10n/it.json @@ -34,6 +34,15 @@ "(group)" : "(gruppo)", "Admin defined" : "Definito dall'amministratore", "Saved" : "Salvato", + "Empty response from the server" : "Risposta vuota dal server", + "Couldn't access. Please logout and login to activate this mount point" : "Impossibile accedere. Termina la sessione e accedi nuovamente per attivare questo punto di mount", + "Couldn't get the information from the ownCloud server: {code} {type}" : "Impossibile ottenere le informazioni dal server ownCloud: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "Impossibile ottenere l'elenco dei punti di mount esterni: {type}", + "There was an error with message: " : "Si è verificato un errore con il messaggio:", + "External mount error" : "Errore di mount esterno", + "goto-external-storage" : "goto-external-storage", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "Impossibile ottenere l'elenco dei punti di mount delle unità di rete Windows: risposta vuota dal server", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Alcuni dei punti di mount esterni configurati non sono connessi. Fai clic sulle righe rosse per ulteriori informazioni", "Access key" : "Chiave di accesso", "Secret key" : "Chiave segreta", "Builtin" : "Integrata", diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js index 05d1a3f6de5..5051689216f 100644 --- a/apps/files_external/l10n/nl.js +++ b/apps/files_external/l10n/nl.js @@ -17,6 +17,7 @@ OC.L10N.register( "Unsatisfied backend parameters" : "Onvoldoende backend parameters", "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters", "Insufficient data: %s" : "Onvoldoende gegevens: %s", + "%s" : "%s", "Personal" : "Persoonlijk", "System" : "Systeem", "Grant access" : "Sta toegang toe", diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json index e30870e4ae1..d8a254bad1b 100644 --- a/apps/files_external/l10n/nl.json +++ b/apps/files_external/l10n/nl.json @@ -15,6 +15,7 @@ "Unsatisfied backend parameters" : "Onvoldoende backend parameters", "Unsatisfied authentication mechanism parameters" : "Onvoldoende authenticatiemechanisme parameters", "Insufficient data: %s" : "Onvoldoende gegevens: %s", + "%s" : "%s", "Personal" : "Persoonlijk", "System" : "Systeem", "Grant access" : "Sta toegang toe", diff --git a/apps/files_external/l10n/sq.js b/apps/files_external/l10n/sq.js index a708bca92d0..3e2de744b15 100644 --- a/apps/files_external/l10n/sq.js +++ b/apps/files_external/l10n/sq.js @@ -36,6 +36,14 @@ OC.L10N.register( "(group)" : "(grup)", "Admin defined" : "Përcaktuar nga përgjegjësi", "Saved" : "U ruajt", + "Empty response from the server" : "Përgjigje e zbrazët prej shërbyesit", + "Couldn't access. Please logout and login to activate this mount point" : "S’fut dot. Ju lutemi, dilni dhe hyni që të aktivizohet kjo pikë montimi", + "Couldn't get the information from the ownCloud server: {code} {type}" : "S’u morën dot të dhëna nga shërbyesi ownCloud: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "S’u mor dot lista e pikave të jashtme të montimit: {type}", + "There was an error with message: " : "Pati një gabim me këtë mesazh:", + "External mount error" : "Gabim i jashtëm montimi", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "S’u mor dot lista e pikave të montimit Windows network drive: përgjigje e zbrazët nga shërbyesi", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Disa nga pikat e jashtme të formësuara të montimit s’janë të lidhura. Ju lutemi, klikoni në shigjetën(at) e kuqe për më tepër të dhëna", "Access key" : "Kyç hyrjesh", "Secret key" : "Kyç i fshehtë", "Builtin" : "I brendshëm", diff --git a/apps/files_external/l10n/sq.json b/apps/files_external/l10n/sq.json index 655a419c389..f184caf061e 100644 --- a/apps/files_external/l10n/sq.json +++ b/apps/files_external/l10n/sq.json @@ -34,6 +34,14 @@ "(group)" : "(grup)", "Admin defined" : "Përcaktuar nga përgjegjësi", "Saved" : "U ruajt", + "Empty response from the server" : "Përgjigje e zbrazët prej shërbyesit", + "Couldn't access. Please logout and login to activate this mount point" : "S’fut dot. Ju lutemi, dilni dhe hyni që të aktivizohet kjo pikë montimi", + "Couldn't get the information from the ownCloud server: {code} {type}" : "S’u morën dot të dhëna nga shërbyesi ownCloud: {code} {type}", + "Couldn't get the list of external mount points: {type}" : "S’u mor dot lista e pikave të jashtme të montimit: {type}", + "There was an error with message: " : "Pati një gabim me këtë mesazh:", + "External mount error" : "Gabim i jashtëm montimi", + "Couldn't get the list of Windows network drive mount points: empty response from the server" : "S’u mor dot lista e pikave të montimit Windows network drive: përgjigje e zbrazët nga shërbyesi", + "Some of the configured external mount points are not connected. Please click on the red row(s) for more information" : "Disa nga pikat e jashtme të formësuara të montimit s’janë të lidhura. Ju lutemi, klikoni në shigjetën(at) e kuqe për më tepër të dhëna", "Access key" : "Kyç hyrjesh", "Secret key" : "Kyç i fshehtë", "Builtin" : "I brendshëm", diff --git a/apps/files_external/l10n/th_TH.js b/apps/files_external/l10n/th_TH.js index 6c1efa5aacd..bb9c2dc909d 100644 --- a/apps/files_external/l10n/th_TH.js +++ b/apps/files_external/l10n/th_TH.js @@ -17,6 +17,7 @@ OC.L10N.register( "Unsatisfied backend parameters" : "พารามิเตอร์แบ็กเอนด์ไม่ได้รับอนุญาต", "Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ", "Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s", + "%s" : "%s", "Personal" : "ส่วนตัว", "System" : "ระบบ", "Grant access" : "อนุญาตให้เข้าถึงได้", diff --git a/apps/files_external/l10n/th_TH.json b/apps/files_external/l10n/th_TH.json index 3de48d733d3..f38d99ae88b 100644 --- a/apps/files_external/l10n/th_TH.json +++ b/apps/files_external/l10n/th_TH.json @@ -15,6 +15,7 @@ "Unsatisfied backend parameters" : "พารามิเตอร์แบ็กเอนด์ไม่ได้รับอนุญาต", "Unsatisfied authentication mechanism parameters" : "การรับรองความถูกต้องไม่เพียงพอ", "Insufficient data: %s" : "ข้อมูลไม่เพียงพอ: %s", + "%s" : "%s", "Personal" : "ส่วนตัว", "System" : "ระบบ", "Grant access" : "อนุญาตให้เข้าถึงได้", diff --git a/apps/files_external/lib/storageconfig.php b/apps/files_external/lib/storageconfig.php index 97e0386be73..49a40a9a5d7 100644 --- a/apps/files_external/lib/storageconfig.php +++ b/apps/files_external/lib/storageconfig.php @@ -163,7 +163,7 @@ class StorageConfig implements \JsonSerializable { } /** - * @param Backend + * @param Backend $backend */ public function setBackend(Backend $backend) { $this->backend= $backend; @@ -177,7 +177,7 @@ class StorageConfig implements \JsonSerializable { } /** - * @param AuthMechanism + * @param AuthMechanism $authMechanism */ public function setAuthMechanism(AuthMechanism $authMechanism) { $this->authMechanism = $authMechanism; diff --git a/apps/files_sharing/l10n/mk.js b/apps/files_sharing/l10n/mk.js index a5de7fb5c09..5be22894b99 100644 --- a/apps/files_sharing/l10n/mk.js +++ b/apps/files_sharing/l10n/mk.js @@ -1,20 +1,44 @@ OC.L10N.register( "files_sharing", { + "Server to server sharing is not enabled on this server" : "Не е овозможено споделувањето од сервер на сервер на вашиот сервер", + "Invalid or untrusted SSL certificate" : "SSL сертификат кој е невалиден или недоверлив", + "Could not authenticate to remote share, password might be wrong" : "Не можам да се автентицирам на оддалеченото споделевање, веројатно лозинката не е исправна", + "Storage not valid" : "Сториџот не е валиден", + "Couldn't add remote share" : "Не можам да додадам оддалечено споделување", "Shared with you" : "Споделено со тебе", "Shared with others" : "Сподели со останатите", "Shared by link" : "Споделено со врска", + "Nothing shared with you yet" : "Сеуште ништо не е споделено со вас", + "Nothing shared yet" : "Уште ништо не е споделено", + "No shared links" : "Нема споделени врски/линкови", + "Remote share" : "Оддалечено споделување", + "Remote share password" : "Лозинка за оддалечаното споделување", "Cancel" : "Откажи", + "Add remote share" : "Додади оддалечно споделување", + "You can upload into this folder" : "Можете да прикачите во оваа папка", + "Invalid ownCloud url" : "Неисправен ownCloud url", "Shared by" : "Споделено од", "Sharing" : "Споделување", "A file or folder has been <strong>shared</strong>" : "Датотека или фолдер беше <strong>споделен</strong>", "You shared %1$s with %2$s" : "Вие споделивте %1$s со %2$s", "You shared %1$s with group %2$s" : "Вие споделивте %1$s со групата %2$s", "%2$s shared %1$s with you" : "%2$s споделено %1$s со вас", + "Downloaded via public link" : "Преземи преку јавен линк", + "Shared with %2$s" : "Споделено со %2$s", + "Shared with group %2$s" : "Споделено со група %2$s", + "Shared with %3$s by %2$s" : "Споделено со %3$s од %2$s", + "Shared with group %3$s by %2$s" : "Споделено со група %3$s од %2$s", + "Shared via link by %2$s" : "Споделено со врска/линк од %2$s", + "Shared by %2$s" : "Споделено од %2$s", + "Shared via public link" : "Споделено со јавна врска/линк", "Shares" : "Споделувања", + "Accept" : "Прифати", + "Decline" : "Одбиј", "This share is password-protected" : "Ова споделување е заштитено со лозинка", "The password is wrong. Try again." : "Лозинката е грешна. Обиди се повторно.", "Password" : "Лозинка", + "No entries found in this folder" : "Нема ништо во оваа папка", "Name" : "Име", "Share time" : "Сподели време", "Sorry, this link doesn’t seem to work anymore." : "Извенете, но овој линк изгледа дека повеќе не функционира.", @@ -23,8 +47,17 @@ OC.L10N.register( "the link expired" : "времетраењето на линкот е изминато", "sharing is disabled" : "споделувањето не е дозволено", "For more info, please ask the person who sent this link." : "За повеќе информации, прашајте го лицето кое ви ја испратила врската.", + "Add to your ownCloud" : "Додади во вашиот ownCloud", "Download" : "Преземи", "Download %s" : "Преземи %s", - "Direct link" : "Директна врска" + "Direct link" : "Директна врска", + "Federated Cloud Sharing" : "Федерирано клауд споделување", + "Open documentation" : "Отвори ја документацијата", + "Federated Cloud" : "Федериран клауд", + "Your Federated Cloud ID:" : "Вашиот федериран Cloud ID:", + "Share it:" : "Сподели го:", + "Add to your website" : "Додади на твојот веб сајт", + "Share with me via ownCloud" : "Сподели со мене преку ownCloud", + "HTML Code:" : "HTML код:" }, "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"); diff --git a/apps/files_sharing/l10n/mk.json b/apps/files_sharing/l10n/mk.json index ad7eff6078b..40bcf9f8bde 100644 --- a/apps/files_sharing/l10n/mk.json +++ b/apps/files_sharing/l10n/mk.json @@ -1,18 +1,42 @@ { "translations": { + "Server to server sharing is not enabled on this server" : "Не е овозможено споделувањето од сервер на сервер на вашиот сервер", + "Invalid or untrusted SSL certificate" : "SSL сертификат кој е невалиден или недоверлив", + "Could not authenticate to remote share, password might be wrong" : "Не можам да се автентицирам на оддалеченото споделевање, веројатно лозинката не е исправна", + "Storage not valid" : "Сториџот не е валиден", + "Couldn't add remote share" : "Не можам да додадам оддалечено споделување", "Shared with you" : "Споделено со тебе", "Shared with others" : "Сподели со останатите", "Shared by link" : "Споделено со врска", + "Nothing shared with you yet" : "Сеуште ништо не е споделено со вас", + "Nothing shared yet" : "Уште ништо не е споделено", + "No shared links" : "Нема споделени врски/линкови", + "Remote share" : "Оддалечено споделување", + "Remote share password" : "Лозинка за оддалечаното споделување", "Cancel" : "Откажи", + "Add remote share" : "Додади оддалечно споделување", + "You can upload into this folder" : "Можете да прикачите во оваа папка", + "Invalid ownCloud url" : "Неисправен ownCloud url", "Shared by" : "Споделено од", "Sharing" : "Споделување", "A file or folder has been <strong>shared</strong>" : "Датотека или фолдер беше <strong>споделен</strong>", "You shared %1$s with %2$s" : "Вие споделивте %1$s со %2$s", "You shared %1$s with group %2$s" : "Вие споделивте %1$s со групата %2$s", "%2$s shared %1$s with you" : "%2$s споделено %1$s со вас", + "Downloaded via public link" : "Преземи преку јавен линк", + "Shared with %2$s" : "Споделено со %2$s", + "Shared with group %2$s" : "Споделено со група %2$s", + "Shared with %3$s by %2$s" : "Споделено со %3$s од %2$s", + "Shared with group %3$s by %2$s" : "Споделено со група %3$s од %2$s", + "Shared via link by %2$s" : "Споделено со врска/линк од %2$s", + "Shared by %2$s" : "Споделено од %2$s", + "Shared via public link" : "Споделено со јавна врска/линк", "Shares" : "Споделувања", + "Accept" : "Прифати", + "Decline" : "Одбиј", "This share is password-protected" : "Ова споделување е заштитено со лозинка", "The password is wrong. Try again." : "Лозинката е грешна. Обиди се повторно.", "Password" : "Лозинка", + "No entries found in this folder" : "Нема ништо во оваа папка", "Name" : "Име", "Share time" : "Сподели време", "Sorry, this link doesn’t seem to work anymore." : "Извенете, но овој линк изгледа дека повеќе не функционира.", @@ -21,8 +45,17 @@ "the link expired" : "времетраењето на линкот е изминато", "sharing is disabled" : "споделувањето не е дозволено", "For more info, please ask the person who sent this link." : "За повеќе информации, прашајте го лицето кое ви ја испратила врската.", + "Add to your ownCloud" : "Додади во вашиот ownCloud", "Download" : "Преземи", "Download %s" : "Преземи %s", - "Direct link" : "Директна врска" + "Direct link" : "Директна врска", + "Federated Cloud Sharing" : "Федерирано клауд споделување", + "Open documentation" : "Отвори ја документацијата", + "Federated Cloud" : "Федериран клауд", + "Your Federated Cloud ID:" : "Вашиот федериран Cloud ID:", + "Share it:" : "Сподели го:", + "Add to your website" : "Додади на твојот веб сајт", + "Share with me via ownCloud" : "Сподели со мене преку ownCloud", + "HTML Code:" : "HTML код:" },"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;" }
\ No newline at end of file diff --git a/apps/files_sharing/lib/sharedmount.php b/apps/files_sharing/lib/sharedmount.php index 275fea97c7f..f205b1e78a5 100644 --- a/apps/files_sharing/lib/sharedmount.php +++ b/apps/files_sharing/lib/sharedmount.php @@ -48,6 +48,12 @@ class SharedMount extends MountPoint implements MoveableMount { */ private $user; + /** + * @param string $storage + * @param string $mountpoint + * @param array|null $arguments + * @param \OCP\Files\Storage\IStorageFactory $loader + */ public function __construct($storage, $mountpoint, $arguments = null, $loader = null) { $this->user = $arguments['user']; $this->recipientView = new View('/' . $this->user . '/files'); @@ -59,6 +65,9 @@ class SharedMount extends MountPoint implements MoveableMount { /** * check if the parent folder exists otherwise move the mount point up + * + * @param array $share + * @return string */ private function verifyMountPoint(&$share) { @@ -121,6 +130,7 @@ class SharedMount extends MountPoint implements MoveableMount { * * @param string $path the absolute path * @return string e.g. turns '/admin/files/test.txt' into '/test.txt' + * @throws \OCA\Files_Sharing\Exceptions\BrokenPath */ protected function stripUserFilesPath($path) { $trimmed = ltrim($path, '/'); @@ -183,7 +193,7 @@ class SharedMount extends MountPoint implements MoveableMount { */ public function removeMount() { $mountManager = \OC\Files\Filesystem::getMountManager(); - /** @var \OC\Files\Storage\Shared */ + /** @var $storage \OC\Files\Storage\Shared */ $storage = $this->getStorage(); $result = $storage->unshareStorage(); $mountManager->removeMount($this->mountPoint); @@ -191,7 +201,12 @@ class SharedMount extends MountPoint implements MoveableMount { return $result; } + /** + * @return array + */ public function getShare() { - return $this->getStorage()->getShare(); + /** @var $storage \OC\Files\Storage\Shared */ + $storage = $this->getStorage(); + return $storage->getShare(); } } diff --git a/apps/files_sharing/tests/api/shareestest.php b/apps/files_sharing/tests/api/shareestest.php index a3e3a6dee6d..96ffe4682c0 100644 --- a/apps/files_sharing/tests/api/shareestest.php +++ b/apps/files_sharing/tests/api/shareestest.php @@ -88,6 +88,11 @@ class ShareesTest extends TestCase { ); } + /** + * @param string $uid + * @param string $displayName + * @return \OCP\IUser|\PHPUnit_Framework_MockObject_MockObject + */ protected function getUserMock($uid, $displayName) { $user = $this->getMockBuilder('OCP\IUser') ->disableOriginalConstructor() @@ -104,6 +109,10 @@ class ShareesTest extends TestCase { return $user; } + /** + * @param string $gid + * @return \OCP\IGroup|\PHPUnit_Framework_MockObject_MockObject + */ protected function getGroupMock($gid) { $group = $this->getMockBuilder('OCP\IGroup') ->disableOriginalConstructor() diff --git a/apps/files_sharing/tests/share.php b/apps/files_sharing/tests/share.php index b5ba0e3ad51..05013ad2e00 100644 --- a/apps/files_sharing/tests/share.php +++ b/apps/files_sharing/tests/share.php @@ -220,6 +220,10 @@ class Test_Files_Sharing extends OCA\Files_sharing\Tests\TestCase { } + /** + * @param OC\Files\FileInfo[] $content + * @param string[] $expected + */ public function verifyDirContent($content, $expected) { foreach ($content as $c) { if (!in_array($c['name'], $expected)) { diff --git a/apps/files_trashbin/l10n/mk.js b/apps/files_trashbin/l10n/mk.js index 6acb933aa80..8a4b16c52d8 100644 --- a/apps/files_trashbin/l10n/mk.js +++ b/apps/files_trashbin/l10n/mk.js @@ -9,6 +9,7 @@ OC.L10N.register( "Delete permanently" : "Трајно избришани", "Error" : "Грешка", "restored" : "повратени", + "No entries found in this folder" : "Нема ништо во оваа папка", "Name" : "Име", "Deleted" : "Избришан" }, diff --git a/apps/files_trashbin/l10n/mk.json b/apps/files_trashbin/l10n/mk.json index a9948f49ff6..2ec0b3c9500 100644 --- a/apps/files_trashbin/l10n/mk.json +++ b/apps/files_trashbin/l10n/mk.json @@ -7,6 +7,7 @@ "Delete permanently" : "Трајно избришани", "Error" : "Грешка", "restored" : "повратени", + "No entries found in this folder" : "Нема ништо во оваа папка", "Name" : "Име", "Deleted" : "Избришан" },"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;" diff --git a/apps/files_trashbin/lib/trashbin.php b/apps/files_trashbin/lib/trashbin.php index 676252e1634..bd6798f0eff 100644 --- a/apps/files_trashbin/lib/trashbin.php +++ b/apps/files_trashbin/lib/trashbin.php @@ -147,7 +147,7 @@ class Trashbin { * * @param string $sourcePath * @param string $owner - * @param $targetPath + * @param string $targetPath * @param $user * @param integer $timestamp */ @@ -410,7 +410,7 @@ class Trashbin { * @param string $uniqueFilename new file name to restore the file without overwriting existing files * @param string $location location if file * @param int $timestamp deletion time - * @return bool + * @return false|null */ private static function restoreVersions(\OC\Files\View $view, $file, $filename, $uniqueFilename, $location, $timestamp) { @@ -500,9 +500,10 @@ class Trashbin { /** * @param \OC\Files\View $view - * @param $file - * @param $filename - * @param $timestamp + * @param string $file + * @param string $filename + * @param integer|null $timestamp + * @param string $user * @return int */ private static function deleteVersions(\OC\Files\View $view, $file, $filename, $timestamp, $user) { @@ -684,7 +685,7 @@ class Trashbin { * * @param array $files list of files sorted by mtime * @param string $user - * @return array size of deleted files and number of deleted files + * @return integer[] size of deleted files and number of deleted files */ public static function deleteExpiredFiles($files, $user) { $application = new Application(); diff --git a/apps/files_trashbin/tests/trashbin.php b/apps/files_trashbin/tests/trashbin.php index c53ed8d8a9b..db7e7e6e840 100644 --- a/apps/files_trashbin/tests/trashbin.php +++ b/apps/files_trashbin/tests/trashbin.php @@ -248,8 +248,8 @@ class Test_Trashbin extends \Test\TestCase { /** * verify that the array contains the expected results - * @param array $result - * @param array $expected + * @param OCP\Files\FileInfo[] $result + * @param string[] $expected */ private function verifyArray($result, $expected) { $this->assertSame(count($expected), count($result)); @@ -268,6 +268,11 @@ class Test_Trashbin extends \Test\TestCase { } } + /** + * @param OCP\Files\FileInfo[] $files + * @param string $trashRoot + * @param integer $expireDate + */ private function manipulateDeleteTime($files, $trashRoot, $expireDate) { $counter = 0; foreach ($files as &$file) { @@ -627,7 +632,6 @@ class Test_Trashbin extends \Test\TestCase { /** * @param string $user * @param bool $create - * @param bool $password */ public static function loginHelper($user, $create = false) { if ($create) { @@ -650,11 +654,20 @@ class Test_Trashbin extends \Test\TestCase { // just a dummy class to make protected methods available for testing class TrashbinForTesting extends Files_Trashbin\Trashbin { + + /** + * @param OCP\Files\FileInfo[] $files + * @param integer $limit + */ public function dummyDeleteExpiredFiles($files, $limit) { // dummy value for $retention_obligation because it is not needed here return parent::deleteExpiredFiles($files, \Test_Trashbin::TEST_TRASHBIN_USER1, $limit, 0); } + /** + * @param OCP\Files\FileInfo[] $files + * @param integer $availableSpace + */ public function dummyDeleteFiles($files, $availableSpace) { return parent::deleteFiles($files, \Test_Trashbin::TEST_TRASHBIN_USER1, $availableSpace); } diff --git a/apps/files_versions/lib/storage.php b/apps/files_versions/lib/storage.php index 6737bf20f90..29876b3e38a 100644 --- a/apps/files_versions/lib/storage.php +++ b/apps/files_versions/lib/storage.php @@ -649,7 +649,7 @@ class Storage { /** * Expire versions which exceed the quota * - * @param $filename + * @param string $filename * @param int|null $versionsSize * @param int $offset * @return bool|int|null diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php index d37f4412e20..f4f3b194944 100644 --- a/apps/provisioning_api/tests/groupstest.php +++ b/apps/provisioning_api/tests/groupstest.php @@ -30,13 +30,13 @@ use OCP\IUserSession; use OCP\IRequest; class GroupsTest extends \Test\TestCase { - /** @var IGroupManager */ + /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ protected $groupManager; - /** @var IUserSession */ + /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */ protected $userSession; - /** @var IRequest */ + /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */ protected $request; - /** @var \OC\SubAdmin */ + /** @var \OC\SubAdmin|\PHPUnit_Framework_MockObject_MockObject */ protected $subAdminManager; /** @var \OCA\Provisioning_API\Groups */ protected $api; @@ -58,6 +58,10 @@ class GroupsTest extends \Test\TestCase { ); } + /** + * @param string $gid + * @return \OCP\IGroup|\PHPUnit_Framework_MockObject_MockObject + */ private function createGroup($gid) { $group = $this->getMock('OCP\IGroup'); $group @@ -66,6 +70,10 @@ class GroupsTest extends \Test\TestCase { return $group; } + /** + * @param string $uid + * @return \OCP\IUser|\PHPUnit_Framework_MockObject_MockObject + */ private function createUser($uid) { $user = $this->getMock('OCP\IUser'); $user diff --git a/apps/user_ldap/ajax/testConfiguration.php b/apps/user_ldap/ajax/testConfiguration.php index f5fd5f23b87..47fc776983a 100644 --- a/apps/user_ldap/ajax/testConfiguration.php +++ b/apps/user_ldap/ajax/testConfiguration.php @@ -49,7 +49,7 @@ try { * pass (like e.g. expected syntax error). */ try { - $ldapWrapper->read($connection->getConnectionResource(), 'neverwhere', 'objectClass=*', array('dn')); + $ldapWrapper->read($connection->getConnectionResource(), '', 'objectClass=*', array('dn')); } catch (\Exception $e) { if($e->getCode() === 1) { OCP\JSON::error(array('message' => $l->t('The configuration is invalid: anonymous bind is not allowed.'))); diff --git a/build/integration/run.sh b/build/integration/run.sh index 76c01068deb..5a222bda3e3 100755 --- a/build/integration/run.sh +++ b/build/integration/run.sh @@ -2,6 +2,9 @@ composer install +SCENARIO_TO_RUN=$1 +HIDE_OC_LOGS=$2 + # avoid port collision on jenkins - use $EXECUTOR_NUMBER if [ -z "$EXECUTOR_NUMBER" ]; then EXECUTOR_NUMBER=0 @@ -21,13 +24,15 @@ echo $PHPPID_FED export TEST_SERVER_URL="http://localhost:$PORT/ocs/" export TEST_SERVER_FED_URL="http://localhost:$PORT_FED/ocs/" -vendor/bin/behat -f junit -f pretty $1 +vendor/bin/behat -f junit -f pretty $SCENARIO_TO_RUN RESULT=$? kill $PHPPID kill $PHPPID_FED -tail "../../data/owncloud.log" +if [ -z $HIDE_OC_LOGS ]; then + tail "../../data/owncloud.log" +fi exit $RESULT diff --git a/config/config.sample.php b/config/config.sample.php index 034a1ebddbf..c3abe3a2b87 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -214,6 +214,14 @@ $CONFIG = array( ), /** + * If your user backend does not allow to reset the password (e.g. when it's a + * read-only user backend like LDAP), you can specify a custom link, where the + * user is redirected to, when clicking the "reset password" link after a failed + * login-attempt. + */ +'lost_password_link' => 'https://example.org/link/to/password/reset', + +/** * Mail Parameters * * These configure the email settings for ownCloud notifications and password diff --git a/core/js/config.php b/core/js/config.php index 8956689e74e..e51ae903729 100644 --- a/core/js/config.php +++ b/core/js/config.php @@ -141,6 +141,7 @@ $array = array( 'version' => implode('.', OC_Util::getVersion()), 'versionstring' => OC_Util::getVersionString(), 'enable_avatars' => \OC::$server->getConfig()->getSystemValue('enable_avatars', true), + 'lost_password_link'=> \OC::$server->getConfig()->getSystemValue('lost_password_link', null), 'modRewriteWorking' => (getenv('front_controller_active') === 'true'), ) ), diff --git a/core/js/lostpassword.js b/core/js/lostpassword.js index 294a9d8c1cf..df28c2308cb 100644 --- a/core/js/lostpassword.js +++ b/core/js/lostpassword.js @@ -13,22 +13,26 @@ OC.Lostpassword = { resetErrorMsg : t('core', 'Password can not be changed. Please contact your administrator.'), init : function() { - $('#lost-password').click(OC.Lostpassword.sendLink); + $('#lost-password').click(OC.Lostpassword.resetLink); $('#reset-password #submit').click(OC.Lostpassword.resetPassword); }, - sendLink : function(event){ + resetLink : function(event){ event.preventDefault(); if (!$('#user').val().length){ $('#submit').trigger('click'); } else { - $.post( + if (OC.config['lost_password_link']) { + window.location = OC.config['lost_password_link']; + } else { + $.post( OC.generateUrl('/lostpassword/email'), { user : $('#user').val() }, OC.Lostpassword.sendLinkDone - ); + ); + } } }, diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js index dfe5789e774..daed8a439bb 100644 --- a/core/js/sharedialogshareelistview.js +++ b/core/js/sharedialogshareelistview.js @@ -245,12 +245,14 @@ onUnshare: function(event) { var $element = $(event.target); - console.log($element); + if (!$element.is('a')) { + $element = $element.closest('a'); + } - var $loading = $element.siblings('.icon-loading-small').eq(0); + var $loading = $element.find('.icon-loading-small').eq(0); if(!$loading.hasClass('hidden')) { // in process - return; + return false; } $loading.removeClass('hidden'); diff --git a/core/js/update.js b/core/js/update.js index 090f8fa5d23..1626b6f2c49 100644 --- a/core/js/update.js +++ b/core/js/update.js @@ -84,7 +84,7 @@ .append(t('core', 'The update was successful. Redirecting you to ownCloud now.')) .appendTo($el); setTimeout(function () { - OC.redirect(OC.webroot); + OC.redirect(OC.webroot + '/'); }, 3000); } }); diff --git a/core/l10n/cs_CZ.js b/core/l10n/cs_CZ.js index 94fe0489390..c9c8ca08ebe 100644 --- a/core/l10n/cs_CZ.js +++ b/core/l10n/cs_CZ.js @@ -266,6 +266,7 @@ OC.L10N.register( "Please try again or contact your administrator." : "Prosím zkuste to znovu nebo kontaktujte vašeho správce.", "Log in" : "Přihlásit", "Wrong password. Reset it?" : "Nesprávné heslo. Resetovat?", + "Wrong password." : "Chybné heslo.", "Stay logged in" : "Neodhlašovat", "Alternative Logins" : "Alternativní přihlášení", "This ownCloud instance is currently in single user mode." : "Tato instalace ownCloudu je momentálně v jednouživatelském módu.", diff --git a/core/l10n/cs_CZ.json b/core/l10n/cs_CZ.json index 08c93b63888..4fa79ebec9c 100644 --- a/core/l10n/cs_CZ.json +++ b/core/l10n/cs_CZ.json @@ -264,6 +264,7 @@ "Please try again or contact your administrator." : "Prosím zkuste to znovu nebo kontaktujte vašeho správce.", "Log in" : "Přihlásit", "Wrong password. Reset it?" : "Nesprávné heslo. Resetovat?", + "Wrong password." : "Chybné heslo.", "Stay logged in" : "Neodhlašovat", "Alternative Logins" : "Alternativní přihlášení", "This ownCloud instance is currently in single user mode." : "Tato instalace ownCloudu je momentálně v jednouživatelském módu.", diff --git a/core/l10n/fi_FI.js b/core/l10n/fi_FI.js index f167292ec13..5291a0d1c2a 100644 --- a/core/l10n/fi_FI.js +++ b/core/l10n/fi_FI.js @@ -266,6 +266,7 @@ OC.L10N.register( "Please try again or contact your administrator." : "Yritä uudestaan tai ota yhteys ylläpitäjään.", "Log in" : "Kirjaudu sisään", "Wrong password. Reset it?" : "Väärä salasana. Haluatko palauttaa salasanan?", + "Wrong password." : "Väärä salasana.", "Stay logged in" : "Pysy sisäänkirjautuneena", "Alternative Logins" : "Vaihtoehtoiset kirjautumiset", "This ownCloud instance is currently in single user mode." : "Tämä ownCloud-asennus on parhaillaan single user -tilassa.", diff --git a/core/l10n/fi_FI.json b/core/l10n/fi_FI.json index d98473c9f59..b5312561062 100644 --- a/core/l10n/fi_FI.json +++ b/core/l10n/fi_FI.json @@ -264,6 +264,7 @@ "Please try again or contact your administrator." : "Yritä uudestaan tai ota yhteys ylläpitäjään.", "Log in" : "Kirjaudu sisään", "Wrong password. Reset it?" : "Väärä salasana. Haluatko palauttaa salasanan?", + "Wrong password." : "Väärä salasana.", "Stay logged in" : "Pysy sisäänkirjautuneena", "Alternative Logins" : "Vaihtoehtoiset kirjautumiset", "This ownCloud instance is currently in single user mode." : "Tämä ownCloud-asennus on parhaillaan single user -tilassa.", diff --git a/core/l10n/it.js b/core/l10n/it.js index c6cfb7d78d2..dd472ea6418 100644 --- a/core/l10n/it.js +++ b/core/l10n/it.js @@ -266,6 +266,7 @@ OC.L10N.register( "Please try again or contact your administrator." : "Prova ancora o contatta il tuo amministratore.", "Log in" : "Accedi", "Wrong password. Reset it?" : "Password errata. Vuoi reimpostarla?", + "Wrong password." : "Password errata.", "Stay logged in" : "Rimani collegato", "Alternative Logins" : "Accessi alternativi", "This ownCloud instance is currently in single user mode." : "Questa istanza di ownCloud è in modalità utente singolo.", diff --git a/core/l10n/it.json b/core/l10n/it.json index 4f3bc172318..37d17409e91 100644 --- a/core/l10n/it.json +++ b/core/l10n/it.json @@ -264,6 +264,7 @@ "Please try again or contact your administrator." : "Prova ancora o contatta il tuo amministratore.", "Log in" : "Accedi", "Wrong password. Reset it?" : "Password errata. Vuoi reimpostarla?", + "Wrong password." : "Password errata.", "Stay logged in" : "Rimani collegato", "Alternative Logins" : "Accessi alternativi", "This ownCloud instance is currently in single user mode." : "Questa istanza di ownCloud è in modalità utente singolo.", diff --git a/core/l10n/nl.js b/core/l10n/nl.js index ffff693e95c..9e2bc2d345e 100644 --- a/core/l10n/nl.js +++ b/core/l10n/nl.js @@ -18,6 +18,8 @@ OC.L10N.register( "Repair error: " : "Reparatiefout:", "Set log level to debug - current level: \"%s\"" : "Instellen logniveau op debug - huidige niveau: \"%s\"", "Reset log level to \"%s\"" : "Terugzetten logniveau op \"#%s\"", + "Starting code integrity check" : "Starten code betrouwbaarheidscontrole", + "Finished code integrity check" : "Gereed met code betrouwbaarheidscontrole", "%s (3rdparty)" : "%s (3rdparty)", "%s (incompatible)" : "%s (incompatibel)", "Following apps have been disabled: %s" : "De volgende apps zijn gedeactiveerd: %s", @@ -77,6 +79,7 @@ OC.L10N.register( "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dec.", + "<a href=\"{docUrl}\">There were problems with the code integrity check. More information…</a>" : "<a href=\"{docUrl}\">Er traden problemen op tijdens de code betrouwbaarheidscontrole. Meer informatie…</a>", "Settings" : "Instellingen", "Saving..." : "Opslaan", "seconds ago" : "seconden geleden", @@ -116,6 +119,7 @@ OC.L10N.register( "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "UwPHP versie ({version}) wordt niet langer <a href=\"{phpLink}\">ondersteund door PHP</a>. We adviseren u om uw PHP versie te upgraden voor betere prestaties en security updates geleverd door PHP.", "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "De reverse proxy headerconfiguratie is onjuist, of u hebt toegang tot ownCloud via een vertrouwde proxy. Als u ownCloud niet via een vertrouwde proxy benadert, dan levert dan een beveiligingsrisico op, waardoor een aanvaller het IP-adres dat ownCloud ziet kan spoofen. Meer informatie is te vinden in onze <a href=\"{docLink}\">documentatie</a>.", "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached is geconfigureerd als gedistribueerde cache, maar de verkeerde PHP module \"memcache\" is geïnstalleerd. \\OC\\Memcache\\Memcached ondersteunt alleen \"memcached\" en niet \"memcache\". Zie de <a href=\"{wikiLink}\">memcached wiki over beide modules</a>.", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Sommige bestanden kwamen niet door de code betrouwbaarheidscontrole. Meer informatie over het oplossen van dit probleem kan worden gevonden in onze <a href=\"{docLink}\">documentatie</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">Lijst met ongeldige bestanden…</a> / <a href=\"{rescanEndpoint}\">Opnieuw…</a>)", "Error occurred while checking server setup" : "Een fout trad op bij checken serverconfiguratie", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "De \"{header}\" HTTP header is niet overeenkomstig met \"{expected}\" geconfigureerd. Dit is een potentieel security of privacy risico en we adviseren om deze instelling te wijzigen.", "The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "De \"Strict-Transport-Security\" HTTP header is niet geconfigureerd als minimaal \"{seconds}\" seconden. Voor verbeterde beveiliging adviseren we HSTS in te schakelen zoals beschreven in onze <a href=\"{docUrl}\">security tips</a>.", @@ -187,6 +191,7 @@ OC.L10N.register( "Couldn't reset password because the token is invalid" : "Kon het wachtwoord niet herstellen, omdat het token ongeldig is", "Couldn't reset password because the token is expired" : "Kon het wachtwoord niet herstellen, omdat het token verlopen is", "Couldn't send reset email. Please make sure your username is correct." : "Kon e-mail niet versturen. Verifieer of uw gebruikersnaam correct is.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Kon geen herstel e-mail versturen, omdat er geen e-mailadres bekend is bij deze gebruikersnaam. Neem contact op met uw beheerder.", "%s password reset" : "%s wachtwoord reset", "Use the following link to reset your password: {link}" : "Gebruik de volgende link om uw wachtwoord te resetten: {link}", "New password" : "Nieuw wachtwoord", diff --git a/core/l10n/nl.json b/core/l10n/nl.json index a387d496092..d565545ce38 100644 --- a/core/l10n/nl.json +++ b/core/l10n/nl.json @@ -16,6 +16,8 @@ "Repair error: " : "Reparatiefout:", "Set log level to debug - current level: \"%s\"" : "Instellen logniveau op debug - huidige niveau: \"%s\"", "Reset log level to \"%s\"" : "Terugzetten logniveau op \"#%s\"", + "Starting code integrity check" : "Starten code betrouwbaarheidscontrole", + "Finished code integrity check" : "Gereed met code betrouwbaarheidscontrole", "%s (3rdparty)" : "%s (3rdparty)", "%s (incompatible)" : "%s (incompatibel)", "Following apps have been disabled: %s" : "De volgende apps zijn gedeactiveerd: %s", @@ -75,6 +77,7 @@ "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dec.", + "<a href=\"{docUrl}\">There were problems with the code integrity check. More information…</a>" : "<a href=\"{docUrl}\">Er traden problemen op tijdens de code betrouwbaarheidscontrole. Meer informatie…</a>", "Settings" : "Instellingen", "Saving..." : "Opslaan", "seconds ago" : "seconden geleden", @@ -114,6 +117,7 @@ "Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "UwPHP versie ({version}) wordt niet langer <a href=\"{phpLink}\">ondersteund door PHP</a>. We adviseren u om uw PHP versie te upgraden voor betere prestaties en security updates geleverd door PHP.", "The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "De reverse proxy headerconfiguratie is onjuist, of u hebt toegang tot ownCloud via een vertrouwde proxy. Als u ownCloud niet via een vertrouwde proxy benadert, dan levert dan een beveiligingsrisico op, waardoor een aanvaller het IP-adres dat ownCloud ziet kan spoofen. Meer informatie is te vinden in onze <a href=\"{docLink}\">documentatie</a>.", "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached is geconfigureerd als gedistribueerde cache, maar de verkeerde PHP module \"memcache\" is geïnstalleerd. \\OC\\Memcache\\Memcached ondersteunt alleen \"memcached\" en niet \"memcache\". Zie de <a href=\"{wikiLink}\">memcached wiki over beide modules</a>.", + "Some files have not passed the integrity check. Further information on how to resolve this issue can be found in our <a href=\"{docLink}\">documentation</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">List of invalid files…</a> / <a href=\"{rescanEndpoint}\">Rescan…</a>)" : "Sommige bestanden kwamen niet door de code betrouwbaarheidscontrole. Meer informatie over het oplossen van dit probleem kan worden gevonden in onze <a href=\"{docLink}\">documentatie</a>. (<a href=\"{codeIntegrityDownloadEndpoint}\">Lijst met ongeldige bestanden…</a> / <a href=\"{rescanEndpoint}\">Opnieuw…</a>)", "Error occurred while checking server setup" : "Een fout trad op bij checken serverconfiguratie", "The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "De \"{header}\" HTTP header is niet overeenkomstig met \"{expected}\" geconfigureerd. Dit is een potentieel security of privacy risico en we adviseren om deze instelling te wijzigen.", "The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "De \"Strict-Transport-Security\" HTTP header is niet geconfigureerd als minimaal \"{seconds}\" seconden. Voor verbeterde beveiliging adviseren we HSTS in te schakelen zoals beschreven in onze <a href=\"{docUrl}\">security tips</a>.", @@ -185,6 +189,7 @@ "Couldn't reset password because the token is invalid" : "Kon het wachtwoord niet herstellen, omdat het token ongeldig is", "Couldn't reset password because the token is expired" : "Kon het wachtwoord niet herstellen, omdat het token verlopen is", "Couldn't send reset email. Please make sure your username is correct." : "Kon e-mail niet versturen. Verifieer of uw gebruikersnaam correct is.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Kon geen herstel e-mail versturen, omdat er geen e-mailadres bekend is bij deze gebruikersnaam. Neem contact op met uw beheerder.", "%s password reset" : "%s wachtwoord reset", "Use the following link to reset your password: {link}" : "Gebruik de volgende link om uw wachtwoord te resetten: {link}", "New password" : "Nieuw wachtwoord", diff --git a/core/l10n/pt_BR.js b/core/l10n/pt_BR.js index 23963477f55..a1f0e287b7d 100644 --- a/core/l10n/pt_BR.js +++ b/core/l10n/pt_BR.js @@ -191,6 +191,7 @@ OC.L10N.register( "Couldn't reset password because the token is invalid" : "Não foi possível redefinir a senha porque o token é inválido", "Couldn't reset password because the token is expired" : "Não foi possível redefinir a senha porque o token expirou", "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar e-mail de redefinição. Verifique se o seu nome de usuário está correto.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar email de redefinição porque não há nenhum endereço de e-mail para este nome de usuário. Entre em contato com o administrador.", "%s password reset" : "%s redefinir senha", "Use the following link to reset your password: {link}" : "Use o seguinte link para redefinir sua senha: {link}", "New password" : "Nova senha", @@ -265,6 +266,7 @@ OC.L10N.register( "Please try again or contact your administrator." : "Por favor tente novamente ou faça contato com o seu administrador.", "Log in" : "Entrar", "Wrong password. Reset it?" : "Senha incorreta. Redefini-la?", + "Wrong password." : "Senha errada", "Stay logged in" : "Permaneça logado", "Alternative Logins" : "Logins Alternativos", "This ownCloud instance is currently in single user mode." : "Nesta instância ownCloud está em modo de usuário único.", diff --git a/core/l10n/pt_BR.json b/core/l10n/pt_BR.json index 966ec449947..fd3c4f6ac2d 100644 --- a/core/l10n/pt_BR.json +++ b/core/l10n/pt_BR.json @@ -189,6 +189,7 @@ "Couldn't reset password because the token is invalid" : "Não foi possível redefinir a senha porque o token é inválido", "Couldn't reset password because the token is expired" : "Não foi possível redefinir a senha porque o token expirou", "Couldn't send reset email. Please make sure your username is correct." : "Não foi possível enviar e-mail de redefinição. Verifique se o seu nome de usuário está correto.", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "Não foi possível enviar email de redefinição porque não há nenhum endereço de e-mail para este nome de usuário. Entre em contato com o administrador.", "%s password reset" : "%s redefinir senha", "Use the following link to reset your password: {link}" : "Use o seguinte link para redefinir sua senha: {link}", "New password" : "Nova senha", @@ -263,6 +264,7 @@ "Please try again or contact your administrator." : "Por favor tente novamente ou faça contato com o seu administrador.", "Log in" : "Entrar", "Wrong password. Reset it?" : "Senha incorreta. Redefini-la?", + "Wrong password." : "Senha errada", "Stay logged in" : "Permaneça logado", "Alternative Logins" : "Logins Alternativos", "This ownCloud instance is currently in single user mode." : "Nesta instância ownCloud está em modo de usuário único.", diff --git a/core/l10n/sq.js b/core/l10n/sq.js index 4f88093c46d..7a0175d6baf 100644 --- a/core/l10n/sq.js +++ b/core/l10n/sq.js @@ -266,6 +266,7 @@ OC.L10N.register( "Please try again or contact your administrator." : "Ju lutemi, riprovoni ose lidhuni me përgjegjësin tuaj.", "Log in" : "Hyni", "Wrong password. Reset it?" : "Fjalëkalim i gabuar. Të ricaktohet?", + "Wrong password." : "Fjalëkalim i gabuar.", "Stay logged in" : "Qëndro i futur", "Alternative Logins" : "Hyrje Alternative", "This ownCloud instance is currently in single user mode." : "Kjo instancë ownCloud është aktualisht në gjendje me përdorues të vetëm.", diff --git a/core/l10n/sq.json b/core/l10n/sq.json index 748e0221e90..ebe75040d54 100644 --- a/core/l10n/sq.json +++ b/core/l10n/sq.json @@ -264,6 +264,7 @@ "Please try again or contact your administrator." : "Ju lutemi, riprovoni ose lidhuni me përgjegjësin tuaj.", "Log in" : "Hyni", "Wrong password. Reset it?" : "Fjalëkalim i gabuar. Të ricaktohet?", + "Wrong password." : "Fjalëkalim i gabuar.", "Stay logged in" : "Qëndro i futur", "Alternative Logins" : "Hyrje Alternative", "This ownCloud instance is currently in single user mode." : "Kjo instancë ownCloud është aktualisht në gjendje me përdorues të vetëm.", diff --git a/core/l10n/th_TH.js b/core/l10n/th_TH.js index 33816cc7075..cdf411f24d5 100644 --- a/core/l10n/th_TH.js +++ b/core/l10n/th_TH.js @@ -191,6 +191,7 @@ OC.L10N.register( "Couldn't reset password because the token is invalid" : "ไม่สามารถตั้งรหัสผ่านใหม่เพราะโทเค็นไม่ถูกต้อง", "Couldn't reset password because the token is expired" : "ไม่สามารถตั้งค่ารหัสผ่านเพราะโทเค็นหมดอายุ", "Couldn't send reset email. Please make sure your username is correct." : "ไม่สามารถส่งการตั้งค่าอีเมลใหม่ กรุณาตรวจสอบชื่อผู้ใช้ของคุณให้ถูกต้อง", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "ไม่ควร", "%s password reset" : "%s ตั้งรหัสผ่านใหม่", "Use the following link to reset your password: {link}" : "ใช้ลิงค์ต่อไปนี้เพื่อเปลี่ยนรหัสผ่านของคุณใหม่: {link}", "New password" : "รหัสผ่านใหม่", diff --git a/core/l10n/th_TH.json b/core/l10n/th_TH.json index aa2dbc993de..2564a58ff8c 100644 --- a/core/l10n/th_TH.json +++ b/core/l10n/th_TH.json @@ -189,6 +189,7 @@ "Couldn't reset password because the token is invalid" : "ไม่สามารถตั้งรหัสผ่านใหม่เพราะโทเค็นไม่ถูกต้อง", "Couldn't reset password because the token is expired" : "ไม่สามารถตั้งค่ารหัสผ่านเพราะโทเค็นหมดอายุ", "Couldn't send reset email. Please make sure your username is correct." : "ไม่สามารถส่งการตั้งค่าอีเมลใหม่ กรุณาตรวจสอบชื่อผู้ใช้ของคุณให้ถูกต้อง", + "Could not send reset email because there is no email address for this username. Please contact your administrator." : "ไม่ควร", "%s password reset" : "%s ตั้งรหัสผ่านใหม่", "Use the following link to reset your password: {link}" : "ใช้ลิงค์ต่อไปนี้เพื่อเปลี่ยนรหัสผ่านของคุณใหม่: {link}", "New password" : "รหัสผ่านใหม่", diff --git a/core/templates/login.php b/core/templates/login.php index 03be6258fdf..e87b871c67e 100644 --- a/core/templates/login.php +++ b/core/templates/login.php @@ -12,7 +12,7 @@ script('core', [ <form method="post" name="login"> <fieldset> <?php if (!empty($_['redirect_url'])) { - print_unescaped('<input type="hidden" name="redirect_url" value="' . OC_Util::sanitizeHTML($_['redirect_url']) . '">'); + print_unescaped('<input type="hidden" name="redirect_url" value="' . \OCP\Util::sanitizeHTML($_['redirect_url']) . '">'); } ?> <?php if (isset($_['apacheauthfailed']) && ($_['apacheauthfailed'])): ?> <div class="warning"> @@ -56,11 +56,15 @@ script('core', [ <input type="submit" id="submit" class="login primary icon-confirm svg" title="<?php p($l->t('Log in')); ?>" value="" disabled="disabled"/> </p> - <?php if (isset($_['invalidpassword']) && ($_['invalidpassword'])): ?> + <?php if (!empty($_['invalidpassword']) && !empty($_['canResetPassword'])) { ?> <a id="lost-password" class="warning" href=""> <?php p($l->t('Wrong password. Reset it?')); ?> </a> - <?php endif; ?> + <?php } else if (!empty($_['invalidpassword'])) { ?> + <p class="warning"> + <?php p($l->t('Wrong password.')); ?> + </p> + <?php } ?> <?php if ($_['rememberLoginAllowed'] === true) : ?> <div class="remember-login-container"> <input type="checkbox" name="remember_login" value="1" id="remember_login" class="checkbox checkbox--white"> diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index e9b4b52f51f..014b6c24e59 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -149,6 +149,7 @@ OC.L10N.register( "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", - "Storage not available" : "Support de stockage non disponible" + "Storage not available" : "Support de stockage non disponible", + "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s" }, "nplurals=2; plural=(n > 1);"); diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index 7da5eaedd75..feaae43bf41 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -147,6 +147,7 @@ "Storage unauthorized. %s" : "Espace de stockage non autorisé. %s", "Storage incomplete configuration. %s" : "Configuration de l'espace de stockage incomplète. %s", "Storage connection error. %s" : "Erreur de connexion à l'espace stockage. %s", - "Storage not available" : "Support de stockage non disponible" + "Storage not available" : "Support de stockage non disponible", + "Storage connection timeout. %s" : "Le délai d'attente pour la connexion à l'espace de stockage a été dépassé. %s" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js index 24e087a50f5..f4201778f7e 100644 --- a/lib/l10n/nl.js +++ b/lib/l10n/nl.js @@ -147,6 +147,10 @@ OC.L10N.register( "Data directory (%s) is invalid" : "Data directory (%s) is ongeldig", "Please check that the data directory contains a file \".ocdata\" in its root." : "Verifieer dat de data directory een bestand \".ocdata\" in de hoofdmap heeft.", "Could not obtain lock type %d on \"%s\"." : "Kon geen lock type %d krijgen op \"%s\".", - "Storage not available" : "Opslag niet beschikbaar" + "Storage unauthorized. %s" : "Opslag niet toegestaan. %s", + "Storage incomplete configuration. %s" : "Incomplete opslagconfiguratie. %s", + "Storage connection error. %s" : "Opslagverbindingsfout. %s", + "Storage not available" : "Opslag niet beschikbaar", + "Storage connection timeout. %s" : "Opslagverbinding time-out. %s" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json index 691f3e08240..c8981f8fd4c 100644 --- a/lib/l10n/nl.json +++ b/lib/l10n/nl.json @@ -145,6 +145,10 @@ "Data directory (%s) is invalid" : "Data directory (%s) is ongeldig", "Please check that the data directory contains a file \".ocdata\" in its root." : "Verifieer dat de data directory een bestand \".ocdata\" in de hoofdmap heeft.", "Could not obtain lock type %d on \"%s\"." : "Kon geen lock type %d krijgen op \"%s\".", - "Storage not available" : "Opslag niet beschikbaar" + "Storage unauthorized. %s" : "Opslag niet toegestaan. %s", + "Storage incomplete configuration. %s" : "Incomplete opslagconfiguratie. %s", + "Storage connection error. %s" : "Opslagverbindingsfout. %s", + "Storage not available" : "Opslag niet beschikbaar", + "Storage connection timeout. %s" : "Opslagverbinding time-out. %s" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/th_TH.js b/lib/l10n/th_TH.js index 4da409b7d88..da84e9758c3 100644 --- a/lib/l10n/th_TH.js +++ b/lib/l10n/th_TH.js @@ -147,6 +147,8 @@ OC.L10N.register( "Data directory (%s) is invalid" : "ไดเรกทอรีข้อมูล (%s) ไม่ถูกต้อง", "Please check that the data directory contains a file \".ocdata\" in its root." : "กรุณาตรวจสอบว่าไดเรกทอรีข้อมูลมีแฟ้ม \".ocdata\" อยู่ในราก", "Could not obtain lock type %d on \"%s\"." : "ไม่สามารถรับล็อคชนิด %d บน \"%s\"", + "Storage unauthorized. %s" : "การจัดเก็บข้อมูลไม่ได้รับอนุญาต %s", + "Storage incomplete configuration. %s" : "การตั้งค่าการจัดเก็บข้อมูลไม่สำเร็จ %s", "Storage not available" : "ไม่สามารถใช้พื้นที่จัดเก็บข้อมูลได้" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/th_TH.json b/lib/l10n/th_TH.json index a21802be63a..8a951a1468d 100644 --- a/lib/l10n/th_TH.json +++ b/lib/l10n/th_TH.json @@ -145,6 +145,8 @@ "Data directory (%s) is invalid" : "ไดเรกทอรีข้อมูล (%s) ไม่ถูกต้อง", "Please check that the data directory contains a file \".ocdata\" in its root." : "กรุณาตรวจสอบว่าไดเรกทอรีข้อมูลมีแฟ้ม \".ocdata\" อยู่ในราก", "Could not obtain lock type %d on \"%s\"." : "ไม่สามารถรับล็อคชนิด %d บน \"%s\"", + "Storage unauthorized. %s" : "การจัดเก็บข้อมูลไม่ได้รับอนุญาต %s", + "Storage incomplete configuration. %s" : "การตั้งค่าการจัดเก็บข้อมูลไม่สำเร็จ %s", "Storage not available" : "ไม่สามารถใช้พื้นที่จัดเก็บข้อมูลได้" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/private/app.php b/lib/private/app.php index 145517e218a..abf12264c58 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -474,9 +474,13 @@ class OC_App { * search for an app in all app-directories * * @param string $appId - * @return mixed (bool|string) + * @return false|string */ protected static function findAppInDirectories($appId) { + $sanitizedAppId = self::cleanAppId($appId); + if($sanitizedAppId !== $appId) { + return false; + } static $app_dir = array(); if (isset($app_dir[$appId])) { diff --git a/lib/private/appframework/app.php b/lib/private/appframework/app.php index 0188d221be1..5cad32bbd09 100644 --- a/lib/private/appframework/app.php +++ b/lib/private/appframework/app.php @@ -26,6 +26,7 @@ namespace OC\AppFramework; +use OC\AppFramework\Http\Dispatcher; use OC_App; use OC\AppFramework\DependencyInjection\DIContainer; use OCP\AppFramework\QueryException; @@ -97,6 +98,7 @@ class App { } // initialize the dispatcher and run all the middleware before the controller + /** @var Dispatcher $dispatcher */ $dispatcher = $container['Dispatcher']; list( diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php index 02d8ee4344d..741da4efc27 100644 --- a/lib/private/db/querybuilder/querybuilder.php +++ b/lib/private/db/querybuilder/querybuilder.php @@ -325,6 +325,28 @@ class QueryBuilder implements IQueryBuilder { } /** + * Specifies an item that is to be returned uniquely in the query result. + * + * <code> + * $qb = $conn->getQueryBuilder() + * ->selectDistinct('type') + * ->from('users'); + * </code> + * + * @param mixed $select The selection expressions. + * + * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance. + */ + public function selectDistinct($select) { + + $this->queryBuilder->addSelect( + 'DISTINCT ' . $this->helper->quoteColumnName($select) + ); + + return $this; + } + + /** * Adds an item that is to be returned in the query result. * * <code> @@ -1024,14 +1046,46 @@ class QueryBuilder implements IQueryBuilder { } /** + * Used to get the id of the last inserted element + * @return int + * @throws \BadMethodCallException When being called before an insert query has been run. + */ + public function getLastInsertId() { + $from = $this->getQueryPart('from'); + + if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && !empty($from)) { + return (int) $this->connection->lastInsertId($from['table']); + } + + throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.'); + } + + /** + * Returns the table name quoted and with database prefix as needed by the implementation + * * @param string $table * @return string */ - private function getTableName($table) { + public function getTableName($table) { if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) { return $this->helper->quoteColumnName($table); } return $this->helper->quoteColumnName('*PREFIX*' . $table); } + + /** + * Returns the column name quoted and with table alias prefix as needed by the implementation + * + * @param string $column + * @param string $tableAlias + * @return string + */ + public function getColumnName($column, $tableAlias = '') { + if ($tableAlias !== '') { + $tableAlias .= '.'; + } + + return $this->helper->quoteColumnName($tableAlias . $column); + } } diff --git a/lib/private/db/querybuilder/quotehelper.php b/lib/private/db/querybuilder/quotehelper.php index 4b62fee6a6c..5ceb76bbf93 100644 --- a/lib/private/db/querybuilder/quotehelper.php +++ b/lib/private/db/querybuilder/quotehelper.php @@ -61,7 +61,7 @@ class QuoteHelper { } if (substr_count($string, '.')) { - list($alias, $columnName) = explode('.', $string); + list($alias, $columnName) = explode('.', $string, 2); if ($columnName === '*') { return $string; diff --git a/lib/private/repair.php b/lib/private/repair.php index f6ac7ebe65b..d870b472c4f 100644 --- a/lib/private/repair.php +++ b/lib/private/repair.php @@ -40,7 +40,6 @@ use OC\Repair\SqliteAutoincrement; use OC\Repair\DropOldTables; use OC\Repair\FillETags; use OC\Repair\InnoDB; -use OC\Repair\RepairConfig; use OC\Repair\RepairLegacyStorages; use OC\Repair\RepairMimeTypes; use OC\Repair\SearchLuceneTables; @@ -107,7 +106,6 @@ class Repair extends BasicEmitter { return [ new RepairMimeTypes(\OC::$server->getConfig()), new RepairLegacyStorages(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()), - new RepairConfig(), new AssetCache(), new FillETags(\OC::$server->getDatabaseConnection()), new CleanTags(\OC::$server->getDatabaseConnection()), @@ -138,13 +136,12 @@ class Repair extends BasicEmitter { * @return array of RepairStep instances */ public static function getBeforeUpgradeRepairSteps() { - $steps = array( + $steps = [ new InnoDB(), new Collation(\OC::$server->getConfig(), \OC_DB::getConnection()), new SqliteAutoincrement(\OC_DB::getConnection()), new SearchLuceneTables(), - new RepairConfig() - ); + ]; //There is no need to delete all previews on every single update //only 7.0.0 through 7.0.2 generated broken previews diff --git a/lib/private/security/trusteddomainhelper.php b/lib/private/security/trusteddomainhelper.php index 6dbaadfdb60..c1a397dd52d 100644 --- a/lib/private/security/trusteddomainhelper.php +++ b/lib/private/security/trusteddomainhelper.php @@ -74,16 +74,11 @@ class TrustedDomainHelper { return false; } - // TODO: Workaround for older instances still with port applied. Remove for ownCloud 9. - if(in_array($domainWithPort, $trustedList)) { - return true; - } - // Always allow access from localhost if (preg_match(Request::REGEX_LOCALHOST, $domain) === 1) { return true; } - return in_array($domain, $trustedList); + return in_array($domain, $trustedList, true); } } diff --git a/lib/private/systemtag/systemtagmanager.php b/lib/private/systemtag/systemtagmanager.php index 8caf10d69da..7f239dc84cf 100644 --- a/lib/private/systemtag/systemtagmanager.php +++ b/lib/private/systemtag/systemtagmanager.php @@ -63,7 +63,7 @@ class SystemTagManager implements ISystemTagManager { /** * {@inheritdoc} */ - public function getTagsById($tagIds) { + public function getTagsByIds($tagIds) { if (!is_array($tagIds)) { $tagIds = [$tagIds]; } @@ -242,7 +242,7 @@ class SystemTagManager implements ISystemTagManager { $tagNotFoundException = null; try { - $this->getTagsById($tagIds); + $this->getTagsByIds($tagIds); } catch (TagNotFoundException $e) { $tagNotFoundException = $e; } diff --git a/lib/private/systemtag/systemtagobjectmapper.php b/lib/private/systemtag/systemtagobjectmapper.php index 75f2631a010..988fa66d77e 100644 --- a/lib/private/systemtag/systemtagobjectmapper.php +++ b/lib/private/systemtag/systemtagobjectmapper.php @@ -171,6 +171,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { public function haveTag($objIds, $objectType, $tagId, $all = true) { $this->assertTagsExist([$tagId]); + if (!is_array($objIds)) { + $objIds = [$objIds]; + } + $query = $this->connection->getQueryBuilder(); if (!$all) { @@ -209,7 +213,7 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { * @throws \OCP\SystemTag\TagNotFoundException if at least one tag did not exist */ private function assertTagsExist($tagIds) { - $tags = $this->tagManager->getTagsById($tagIds); + $tags = $this->tagManager->getTagsByIds($tagIds); if (count($tags) !== count($tagIds)) { // at least one tag missing, bail out $foundTagIds = array_map( diff --git a/lib/private/template.php b/lib/private/template.php index 1476a964ef3..d794dacac23 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -226,12 +226,12 @@ class OC_Template extends \OC\Template\Base { // Add custom headers $headers = ''; foreach(OC_Util::$headers as $header) { - $headers .= '<'.OC_Util::sanitizeHTML($header['tag']); + $headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']); foreach($header['attributes'] as $name=>$value) { - $headers .= ' '.OC_Util::sanitizeHTML($name).'="'.OC_Util::sanitizeHTML($value).'"'; + $headers .= ' '.\OCP\Util::sanitizeHTML($name).'="'.\OCP\Util::sanitizeHTML($value).'"'; } if ($header['text'] !== null) { - $headers .= '>'.OC_Util::sanitizeHTML($header['text']).'</'.OC_Util::sanitizeHTML($header['tag']).'>'; + $headers .= '>'.\OCP\Util::sanitizeHTML($header['text']).'</'.\OCP\Util::sanitizeHTML($header['tag']).'>'; } else { $headers .= '/>'; } diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php index 79d18632d2f..d156d26f9ce 100644 --- a/lib/private/template/functions.php +++ b/lib/private/template/functions.php @@ -33,7 +33,7 @@ * @param string $string the string which will be escaped and printed */ function p($string) { - print(OC_Util::sanitizeHTML($string)); + print(\OCP\Util::sanitizeHTML($string)); } /** @@ -262,7 +262,7 @@ function html_select_options($options, $selected, $params=array()) { $label = $label[$label_name]; } $select = in_array($value, $selected) ? ' selected="selected"' : ''; - $html .= '<option value="' . OC_Util::sanitizeHTML($value) . '"' . $select . '>' . OC_Util::sanitizeHTML($label) . '</option>'."\n"; + $html .= '<option value="' . \OCP\Util::sanitizeHTML($value) . '"' . $select . '>' . \OCP\Util::sanitizeHTML($label) . '</option>'."\n"; } return $html; } diff --git a/lib/private/util.php b/lib/private/util.php index 9929b7d5b1c..eb188b649e8 100644 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -947,6 +947,14 @@ class OC_Util { $parameters['redirect_url'] = $_REQUEST['redirect_url']; } + $parameters['canResetPassword'] = true; + if (!\OC::$server->getSystemConfig()->getValue('lost_password_link')) { + $user = \OC::$server->getUserManager()->get($_REQUEST['user']); + if ($user instanceof IUser) { + $parameters['canResetPassword'] = $user->canChangePassword(); + } + } + $parameters['alt_login'] = OC_App::getAlternativeLogIns(); $parameters['rememberLoginAllowed'] = self::rememberLoginAllowed(); \OC_Hook::emit('OC_Util', 'pre_displayLoginPage', array('parameters' => $parameters)); @@ -1169,14 +1177,16 @@ class OC_Util { * This function is used to sanitize HTML and should be applied on any * string or array of strings before displaying it on a web page. * - * @param string|array &$value + * @param string|array $value * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter. */ - public static function sanitizeHTML(&$value) { + public static function sanitizeHTML($value) { if (is_array($value)) { - array_walk_recursive($value, 'OC_Util::sanitizeHTML'); + $value = array_map(function($value) { + return self::sanitizeHTML($value); + }, $value); } else { - //Specify encoding for PHP<5.4 + // Specify encoding for PHP<5.4 $value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); } return $value; diff --git a/lib/public/db/querybuilder/iquerybuilder.php b/lib/public/db/querybuilder/iquerybuilder.php index beb922b7feb..dd3ee7da5f5 100644 --- a/lib/public/db/querybuilder/iquerybuilder.php +++ b/lib/public/db/querybuilder/iquerybuilder.php @@ -257,6 +257,22 @@ interface IQueryBuilder { public function selectAlias($select, $alias); /** + * Specifies an item that is to be returned uniquely in the query result. + * + * <code> + * $qb = $conn->getQueryBuilder() + * ->selectDistinct('type') + * ->from('users'); + * </code> + * + * @param mixed $select The selection expressions. + * + * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance. + * @since 9.0.0 + */ + public function selectDistinct($select); + + /** * Adds an item that is to be returned in the query result. * * <code> @@ -796,4 +812,31 @@ interface IQueryBuilder { * @since 8.2.0 */ public function createFunction($call); + + /** + * Used to get the id of the last inserted element + * @return int + * @throws \BadMethodCallException When being called before an insert query has been run. + * @since 9.0.0 + */ + public function getLastInsertId(); + + /** + * Returns the table name quoted and with database prefix as needed by the implementation + * + * @param string $table + * @return string + * @since 9.0.0 + */ + public function getTableName($table); + + /** + * Returns the column name quoted and with table alias prefix as needed by the implementation + * + * @param string $column + * @param string $tableAlias + * @return string + * @since 9.0.0 + */ + public function getColumnName($column, $tableAlias = ''); } diff --git a/lib/public/systemtag/isystemtagmanager.php b/lib/public/systemtag/isystemtagmanager.php index 4e3b263e56c..6e8fed36dce 100644 --- a/lib/public/systemtag/isystemtagmanager.php +++ b/lib/public/systemtag/isystemtagmanager.php @@ -41,7 +41,7 @@ interface ISystemTagManager { * * @since 9.0.0 */ - public function getTagsById($tagIds); + public function getTagsByIds($tagIds); /** * Returns the tag object matching the given attributes. diff --git a/lib/public/util.php b/lib/public/util.php index 110028368d0..4e783b764ed 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -497,11 +497,11 @@ class Util { * string or array of strings before displaying it on a web page. * * @param string|array $value - * @return string|array an array of sanitized strings or a single sinitized string, depends on the input parameter. + * @return string|array an array of sanitized strings or a single sanitized string, depends on the input parameter. * @since 4.5.0 */ - public static function sanitizeHTML( $value ) { - return(\OC_Util::sanitizeHTML($value)); + public static function sanitizeHTML($value) { + return \OC_Util::sanitizeHTML($value); } /** diff --git a/lib/repair/repairconfig.php b/lib/repair/repairconfig.php deleted file mode 100644 index 66fdd47269e..00000000000 --- a/lib/repair/repairconfig.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -/** - * @author Lukas Reschke <lukas@owncloud.com> - * @author Morris Jobke <hey@morrisjobke.de> - * - * @copyright Copyright (c) 2015, ownCloud, Inc. - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OC\Repair; - -use OC\Hooks\BasicEmitter; -use OC\RepairStep; -use Sabre\DAV\Exception; - -/** - * Class RepairConfig - * - * @package OC\Repair - */ -class RepairConfig extends BasicEmitter implements RepairStep { - - /** - * @return string - */ - public function getName() { - return 'Repair config'; - } - - /** - * Updates the configuration after running an update - */ - public function run() { - $this->addSecret(); - $this->removePortsFromTrustedDomains(); - } - - /** - * Adds a secret to config.php - */ - private function addSecret() { - if(\OC::$server->getConfig()->getSystemValue('secret', null) === null) { - $secret = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(48); - \OC::$server->getConfig()->setSystemValue('secret', $secret); - } - } - - - /** - * Remove ports from existing trusted domains in config.php - */ - private function removePortsFromTrustedDomains() { - $trustedDomains = \OC::$server->getConfig()->getSystemValue('trusted_domains', array()); - $newTrustedDomains = array(); - foreach($trustedDomains as $domain) { - $pos = strrpos($domain, ':'); - if ($pos !== false) { - $port = substr($domain, $pos + 1); - if (is_numeric($port)) { - $domain = substr($domain, 0, $pos); - } - } - $newTrustedDomains[] = $domain; - } - \OC::$server->getConfig()->setSystemValue('trusted_domains', $newTrustedDomains); - } -} diff --git a/settings/l10n/mk.js b/settings/l10n/mk.js index 65e9d4c09a8..29d21c8f40e 100644 --- a/settings/l10n/mk.js +++ b/settings/l10n/mk.js @@ -10,12 +10,10 @@ OC.L10N.register( "Log" : "Записник", "Tips & tricks" : "Совети и трикови", "Updates" : "Ажурирања", - "Authentication error" : "Грешка во автентикација", - "Your full name has been changed." : "Вашето целосно име е променето.", - "Unable to change full name" : "Не можам да го променам целото име", "Couldn't remove app." : "Не можам да ја отстранам апликацијата.", "Language changed" : "Јазикот е сменет", "Invalid request" : "Неправилно барање", + "Authentication error" : "Грешка во автентикација", "Admins can't remove themself from the admin group" : "Администраторите неможе да се избришат себеси од админ групата", "Unable to add user to group %s" : "Неможе да додадам корисник во група %s", "Unable to remove user from group %s" : "Неможе да избришам корисник од група %s", @@ -28,6 +26,7 @@ OC.L10N.register( "Unable to change password" : "Вашата лозинка неможе да се смени", "Enabled" : "Овозможен", "Not enabled" : "Не е овозможено", + "Federated Cloud Sharing" : "Федерирано клауд споделување", "A problem occurred, please check your log files (Error: %s)" : "Се случи грешка, ве молам проверете ги вашите датотеки за логови (Грешка: %s)", "Migration Completed" : "Миграцијата заврши", "Group already exists." : "Групата веќе постои.", @@ -38,9 +37,24 @@ OC.L10N.register( "test email settings" : "провери ги нагодувањата за електронска пошта", "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Се случи грешка при праќање на порака. Ве молам проверете ги вашите подесувања. (Error: %s)", "Email sent" : "Е-порака пратена", + "Invalid mail address" : "Неправилна електронска адреса/пошта", + "A user with that name already exists." : "Корисник со ова име веќе постои.", + "Unable to create user." : "Неможе да додадам корисник.", + "Your %s account was created" : "Вашата %s сметка е креирана", + "Unable to delete user." : "Неможам да избришам корисник", + "Forbidden" : "Забрането", + "Invalid user" : "Неправилен корисник", + "Unable to change mail address" : "Не можам да ја променам електронската адреса/пошта", "Email saved" : "Електронската пошта е снимена", + "Your full name has been changed." : "Вашето целосно име е променето.", + "Unable to change full name" : "Не можам да го променам целото име", + "Migration started …" : "Миграцијата е започнаа ...", "Sending..." : "Испраќам...", + "Official" : "Официјален", + "Approved" : "Одобрен", + "Experimental" : "Експериментален", "All" : "Сите", + "No apps found for your version" : "За вашата верзија не се пронајдени апликации", "Please wait...." : "Ве молам почекајте ...", "Error while disabling app" : "Грешка при исклучувањето на апликацијата", "Disable" : "Оневозможи", @@ -49,23 +63,34 @@ OC.L10N.register( "Updating...." : "Надградувам ...", "Error while updating app" : "Грешка додека ја надградувам апликацијата", "Updated" : "Надграден", + "Uninstalling ...." : "Деинсталирам ...", + "Error while uninstalling app" : "Грешка при деинсталација на апликацијата", + "Uninstall" : "Деинсталирај", + "App update" : "Надградба на апликацијата", + "An error occurred: {message}" : "Се случи грешка: {message}", "Select a profile picture" : "Одбери фотографија за профилот", "Very weak password" : "Многу слаба лозинка", "Weak password" : "Слаба лозинка", "So-so password" : "Така така лозинка", "Good password" : "Добра лозинка", "Strong password" : "Јака лозинка", + "Valid until {date}" : "Валидно до {date}", "Delete" : "Избриши", "Groups" : "Групи", + "Unable to delete {objName}" : "Не можам да избришам {objName}", "Error creating group" : "Грешка при креирање на група", "A valid group name must be provided" : "Мора да се обезбеди валидно име на група", "undo" : "врати", + "no group" : "нема група", "never" : "никогаш", + "deleted {userName}" : "избришан {userName}", "add group" : "додади група", "A valid username must be provided" : "Мора да се обезбеди валидно корисничко име ", "Error creating user" : "Грешка при креирање на корисникот", "A valid password must be provided" : "Мора да се обезбеди валидна лозинка", "__language_name__" : "__language_name__", + "Sync clients" : "Клиенти за синхронизација", + "Personal info" : "Лични податоци", "SSL root certificates" : "SSL root сертификати", "Info, warnings, errors and fatal issues" : "Информации, предупредувања, грешки и фатални работи", "Warnings, errors and fatal issues" : "Предупредувања, грешки и фатални работи", @@ -77,6 +102,7 @@ OC.L10N.register( "NT LAN Manager" : "NT LAN Менаџер", "SSL" : "SSL", "TLS" : "TLS", + "Open documentation" : "Отвори ја документацијата", "Allow apps to use the Share API" : "Дозволете апликациите да го користат API-то за споделување", "Allow users to share via link" : "Допушти корисниците да споделуваат со линкови", "Enforce password protection" : "Наметни заштита на лозинка", diff --git a/settings/l10n/mk.json b/settings/l10n/mk.json index 607808c7367..b3dc7a8ceef 100644 --- a/settings/l10n/mk.json +++ b/settings/l10n/mk.json @@ -8,12 +8,10 @@ "Log" : "Записник", "Tips & tricks" : "Совети и трикови", "Updates" : "Ажурирања", - "Authentication error" : "Грешка во автентикација", - "Your full name has been changed." : "Вашето целосно име е променето.", - "Unable to change full name" : "Не можам да го променам целото име", "Couldn't remove app." : "Не можам да ја отстранам апликацијата.", "Language changed" : "Јазикот е сменет", "Invalid request" : "Неправилно барање", + "Authentication error" : "Грешка во автентикација", "Admins can't remove themself from the admin group" : "Администраторите неможе да се избришат себеси од админ групата", "Unable to add user to group %s" : "Неможе да додадам корисник во група %s", "Unable to remove user from group %s" : "Неможе да избришам корисник од група %s", @@ -26,6 +24,7 @@ "Unable to change password" : "Вашата лозинка неможе да се смени", "Enabled" : "Овозможен", "Not enabled" : "Не е овозможено", + "Federated Cloud Sharing" : "Федерирано клауд споделување", "A problem occurred, please check your log files (Error: %s)" : "Се случи грешка, ве молам проверете ги вашите датотеки за логови (Грешка: %s)", "Migration Completed" : "Миграцијата заврши", "Group already exists." : "Групата веќе постои.", @@ -36,9 +35,24 @@ "test email settings" : "провери ги нагодувањата за електронска пошта", "A problem occurred while sending the email. Please revise your settings. (Error: %s)" : "Се случи грешка при праќање на порака. Ве молам проверете ги вашите подесувања. (Error: %s)", "Email sent" : "Е-порака пратена", + "Invalid mail address" : "Неправилна електронска адреса/пошта", + "A user with that name already exists." : "Корисник со ова име веќе постои.", + "Unable to create user." : "Неможе да додадам корисник.", + "Your %s account was created" : "Вашата %s сметка е креирана", + "Unable to delete user." : "Неможам да избришам корисник", + "Forbidden" : "Забрането", + "Invalid user" : "Неправилен корисник", + "Unable to change mail address" : "Не можам да ја променам електронската адреса/пошта", "Email saved" : "Електронската пошта е снимена", + "Your full name has been changed." : "Вашето целосно име е променето.", + "Unable to change full name" : "Не можам да го променам целото име", + "Migration started …" : "Миграцијата е започнаа ...", "Sending..." : "Испраќам...", + "Official" : "Официјален", + "Approved" : "Одобрен", + "Experimental" : "Експериментален", "All" : "Сите", + "No apps found for your version" : "За вашата верзија не се пронајдени апликации", "Please wait...." : "Ве молам почекајте ...", "Error while disabling app" : "Грешка при исклучувањето на апликацијата", "Disable" : "Оневозможи", @@ -47,23 +61,34 @@ "Updating...." : "Надградувам ...", "Error while updating app" : "Грешка додека ја надградувам апликацијата", "Updated" : "Надграден", + "Uninstalling ...." : "Деинсталирам ...", + "Error while uninstalling app" : "Грешка при деинсталација на апликацијата", + "Uninstall" : "Деинсталирај", + "App update" : "Надградба на апликацијата", + "An error occurred: {message}" : "Се случи грешка: {message}", "Select a profile picture" : "Одбери фотографија за профилот", "Very weak password" : "Многу слаба лозинка", "Weak password" : "Слаба лозинка", "So-so password" : "Така така лозинка", "Good password" : "Добра лозинка", "Strong password" : "Јака лозинка", + "Valid until {date}" : "Валидно до {date}", "Delete" : "Избриши", "Groups" : "Групи", + "Unable to delete {objName}" : "Не можам да избришам {objName}", "Error creating group" : "Грешка при креирање на група", "A valid group name must be provided" : "Мора да се обезбеди валидно име на група", "undo" : "врати", + "no group" : "нема група", "never" : "никогаш", + "deleted {userName}" : "избришан {userName}", "add group" : "додади група", "A valid username must be provided" : "Мора да се обезбеди валидно корисничко име ", "Error creating user" : "Грешка при креирање на корисникот", "A valid password must be provided" : "Мора да се обезбеди валидна лозинка", "__language_name__" : "__language_name__", + "Sync clients" : "Клиенти за синхронизација", + "Personal info" : "Лични податоци", "SSL root certificates" : "SSL root сертификати", "Info, warnings, errors and fatal issues" : "Информации, предупредувања, грешки и фатални работи", "Warnings, errors and fatal issues" : "Предупредувања, грешки и фатални работи", @@ -75,6 +100,7 @@ "NT LAN Manager" : "NT LAN Менаџер", "SSL" : "SSL", "TLS" : "TLS", + "Open documentation" : "Отвори ја документацијата", "Allow apps to use the Share API" : "Дозволете апликациите да го користат API-то за споделување", "Allow users to share via link" : "Допушти корисниците да споделуваат со линкови", "Enforce password protection" : "Наметни заштита на лозинка", diff --git a/settings/personal.php b/settings/personal.php index 6c2ac351456..9a714393585 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -165,6 +165,7 @@ $l = \OC::$server->getL10N('settings'); $formsAndMore = []; $formsAndMore[]= ['anchor' => 'clientsbox', 'section-name' => $l->t('Sync clients')]; $formsAndMore[]= ['anchor' => 'passwordform', 'section-name' => $l->t('Personal info')]; +$formsAndMore[]= ['anchor' => 'groups', 'section-name' => $l->t('Groups')]; $forms=OC_App::getForms('personal'); diff --git a/settings/templates/admin.php b/settings/templates/admin.php index 0721c0e0afb..f3de51a23c3 100644 --- a/settings/templates/admin.php +++ b/settings/templates/admin.php @@ -56,7 +56,7 @@ if ($_['mail_smtpmode'] == 'qmail') { if (isset($form['anchor'])) { $anchor = '#' . $form['anchor']; $sectionName = $form['section-name']; - print_unescaped(sprintf("<li><a href='%s'>%s</a></li>", OC_Util::sanitizeHTML($anchor), OC_Util::sanitizeHTML($sectionName))); + print_unescaped(sprintf("<li><a href='%s'>%s</a></li>", \OCP\Util::sanitizeHTML($anchor), \OCP\Util::sanitizeHTML($sectionName))); } }?> </ul> diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 0eba71d77d1..09194ea3e39 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -14,7 +14,7 @@ if (isset($form['anchor'])) { $anchor = '#' . $form['anchor']; $sectionName = $form['section-name']; - print_unescaped(sprintf("<li><a href='%s'>%s</a></li>", OC_Util::sanitizeHTML($anchor), OC_Util::sanitizeHTML($sectionName))); + print_unescaped(sprintf("<li><a href='%s'>%s</a></li>", \OCP\Util::sanitizeHTML($anchor), \OCP\Util::sanitizeHTML($sectionName))); } }?> </ul> diff --git a/tests/lib/db/querybuilder/querybuildertest.php b/tests/lib/db/querybuilder/querybuildertest.php index ca3901ad049..c8e029d9e40 100644 --- a/tests/lib/db/querybuilder/querybuildertest.php +++ b/tests/lib/db/querybuilder/querybuildertest.php @@ -48,12 +48,12 @@ class QueryBuilderTest extends \Test\TestCase { $this->queryBuilder = new QueryBuilder($this->connection); } - protected function createTestingRows() { + protected function createTestingRows($appId = 'testFirstResult') { $qB = $this->connection->getQueryBuilder(); for ($i = 1; $i < 10; $i++) { $qB->insert('*PREFIX*appconfig') ->values([ - 'appid' => $qB->expr()->literal('testFirstResult'), + 'appid' => $qB->expr()->literal($appId), 'configkey' => $qB->expr()->literal('testing' . $i), 'configvalue' => $qB->expr()->literal(100 - $i), ]) @@ -80,11 +80,11 @@ class QueryBuilderTest extends \Test\TestCase { return $rows; } - protected function deleteTestingRows() { + protected function deleteTestingRows($appId = 'testFirstResult') { $qB = $this->connection->getQueryBuilder(); $qB->delete('*PREFIX*appconfig') - ->where($qB->expr()->eq('appid', $qB->expr()->literal('testFirstResult'))) + ->where($qB->expr()->eq('appid', $qB->expr()->literal($appId))) ->execute(); } @@ -272,6 +272,34 @@ class QueryBuilderTest extends \Test\TestCase { $this->deleteTestingRows(); } + public function testSelectDistinct() { + $this->deleteTestingRows('testFirstResult1'); + $this->deleteTestingRows('testFirstResult2'); + $this->createTestingRows('testFirstResult1'); + $this->createTestingRows('testFirstResult2'); + + $this->queryBuilder->selectDistinct('appid'); + + $this->queryBuilder->from('*PREFIX*appconfig') + ->where($this->queryBuilder->expr()->in( + 'appid', + [$this->queryBuilder->expr()->literal('testFirstResult1'), $this->queryBuilder->expr()->literal('testFirstResult2')] + )) + ->orderBy('appid', 'DESC'); + + $query = $this->queryBuilder->execute(); + $rows = $query->fetchAll(); + $query->closeCursor(); + + $this->assertEquals( + [['appid' => 'testFirstResult2'], ['appid' => 'testFirstResult1']], + $rows + ); + + $this->deleteTestingRows('testFirstResult1'); + $this->deleteTestingRows('testFirstResult2'); + } + public function dataAddSelect() { $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection()); return [ @@ -1086,6 +1114,31 @@ class QueryBuilderTest extends \Test\TestCase { ); } + public function testGetLastInsertId() { + $qB = $this->connection->getQueryBuilder(); + + try { + $qB->getLastInsertId(); + $this->fail('getLastInsertId() should throw an exception, when being called before insert()'); + } catch (\BadMethodCallException $e) { + $this->assertTrue(true); + } + + $qB->insert('appconfig') + ->values([ + 'appid' => $qB->expr()->literal('testFirstResult'), + 'configkey' => $qB->expr()->literal('testing' . 50), + 'configvalue' => $qB->expr()->literal(100 - 50), + ]) + ->execute(); + + $actual = $qB->getLastInsertId(); + + $this->assertNotNull($actual); + $this->assertInternalType('int', $actual); + $this->assertEquals($this->connection->lastInsertId('*PREFIX*appconfig'), $actual); + } + public function dataGetTableName() { return [ ['*PREFIX*table', null, '`*PREFIX*table`'], @@ -1112,7 +1165,27 @@ class QueryBuilderTest extends \Test\TestCase { $this->assertSame( $expected, - $this->invokePrivate($this->queryBuilder, 'getTableName', [$tableName]) + $this->queryBuilder->getTableName($tableName) + ); + } + + public function dataGetColumnName() { + return [ + ['column', '', '`column`'], + ['column', 'a', 'a.`column`'], + ]; + } + + /** + * @dataProvider dataGetColumnName + * @param string $column + * @param string $prefix + * @param string $expected + */ + public function testGetColumnName($column, $prefix, $expected) { + $this->assertSame( + $expected, + $this->queryBuilder->getColumnName($column, $prefix) ); } } diff --git a/tests/lib/security/trusteddomainhelper.php b/tests/lib/security/trusteddomainhelper.php index c8d5ffa587b..52a8f1be630 100644 --- a/tests/lib/security/trusteddomainhelper.php +++ b/tests/lib/security/trusteddomainhelper.php @@ -64,6 +64,8 @@ class TrustedDomainHelperTest extends \Test\TestCase { // do not trust invalid localhosts [$trustedHostTestList, 'localhost:1:2', false], [$trustedHostTestList, 'localhost: evil.host', false], + // do not trust casting + [[1], '1', false], ]; } diff --git a/tests/lib/systemtag/systemtagmanagertest.php b/tests/lib/systemtag/systemtagmanagertest.php index 8498b85519f..97c072f33f6 100644 --- a/tests/lib/systemtag/systemtagmanagertest.php +++ b/tests/lib/systemtag/systemtagmanagertest.php @@ -250,7 +250,7 @@ class SystemTagManagerTest extends TestCase { $tag1 = $this->tagManager->createTag('one', true, false); $tag2 = $this->tagManager->createTag('two', false, true); - $tagList = $this->tagManager->getTagsById([$tag1->getId(), $tag2->getId()]); + $tagList = $this->tagManager->getTagsByIds([$tag1->getId(), $tag2->getId()]); $this->assertCount(2, $tagList); @@ -270,7 +270,7 @@ class SystemTagManagerTest extends TestCase { */ public function testGetNonExistingTagsById() { $tag1 = $this->tagManager->createTag('one', true, false); - $this->tagManager->getTagsById([$tag1->getId(), 100, 101]); + $this->tagManager->getTagsByIds([$tag1->getId(), 100, 101]); } /** @@ -278,7 +278,7 @@ class SystemTagManagerTest extends TestCase { */ public function testGetInvalidTagIdFormat() { $tag1 = $this->tagManager->createTag('one', true, false); - $this->tagManager->getTagsById([$tag1->getId() . 'suffix']); + $this->tagManager->getTagsByIds([$tag1->getId() . 'suffix']); } public function updateTagProvider() { diff --git a/tests/lib/systemtag/systemtagobjectmappertest.php b/tests/lib/systemtag/systemtagobjectmappertest.php index 43d0b8c6960..4ea80c216ed 100644 --- a/tests/lib/systemtag/systemtagobjectmappertest.php +++ b/tests/lib/systemtag/systemtagobjectmappertest.php @@ -74,7 +74,7 @@ class SystemTagObjectMapperTest extends TestCase { $this->tag3 = new SystemTag(3, 'testtag3', false, false); $this->tagManager->expects($this->any()) - ->method('getTagsById') + ->method('getTagsByIds') ->will($this->returnCallback(function($tagIds) { $result = []; if (in_array(1, $tagIds)) { diff --git a/tests/lib/util.php b/tests/lib/util.php index 9b82be36955..fa559c17c80 100644 --- a/tests/lib/util.php +++ b/tests/lib/util.php @@ -95,16 +95,22 @@ class Test_Util extends \Test\TestCase { } function testSanitizeHTML() { - $badArray = array( + $badArray = [ 'While it is unusual to pass an array', 'this function actually <blink>supports</blink> it.', - 'And therefore there needs to be a <script>alert("Unit"+\'test\')</script> for it!' - ); - $goodArray = array( + 'And therefore there needs to be a <script>alert("Unit"+\'test\')</script> for it!', + [ + 'And It Even May <strong>Nest</strong>', + ], + ]; + $goodArray = [ 'While it is unusual to pass an array', 'this function actually <blink>supports</blink> it.', - 'And therefore there needs to be a <script>alert("Unit"+'test')</script> for it!' - ); + 'And therefore there needs to be a <script>alert("Unit"+'test')</script> for it!', + [ + 'And It Even May <strong>Nest</strong>' + ], + ]; $result = OC_Util::sanitizeHTML($badArray); $this->assertEquals($goodArray, $result); |