diff options
author | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2016-06-11 15:34:43 +0200 |
---|---|---|
committer | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2016-06-11 15:34:43 +0200 |
commit | 42c66efea5ef512d3a3442112f820168e6499265 (patch) | |
tree | 97ef44632d653656608e71e096fd537bbd609936 /apps | |
parent | 75f37f550bb7895757325d3f9a3215bcc4471065 (diff) | |
parent | 52a0c939ab8674857bbfe9a9fb0ee7308eee960e (diff) | |
download | nextcloud-server-42c66efea5ef512d3a3442112f820168e6499265.tar.gz nextcloud-server-42c66efea5ef512d3a3442112f820168e6499265.zip |
Merge branch 'master' of https://github.com/owncloud/core into downstream-160611
Diffstat (limited to 'apps')
65 files changed, 1122 insertions, 196 deletions
diff --git a/apps/comments/l10n/bg_BG.js b/apps/comments/l10n/bg_BG.js index e63aedf80db..c5fbba69f7b 100644 --- a/apps/comments/l10n/bg_BG.js +++ b/apps/comments/l10n/bg_BG.js @@ -1,8 +1,19 @@ OC.L10N.register( "comments", { + "Type in a new comment..." : "Напиши нов коментар...", + "Delete comment" : "Изтрий коментар", "Cancel" : "Отказ", + "Edit comment" : "Редактирай коментра", + "[Deleted user]" : "[Изтрит потребител]", + "Comments" : "Коментари", + "No other comments available" : "Няма други коментари", + "More comments..." : "Още коментари...", "Save" : "Запазване", - "Comment" : "Коментар" + "Allowed characters {count} of {max}" : "Позволени символи {count} от {max}", + "{count} unread comments" : "{count} нечетени коментари", + "Comment" : "Коментар", + "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Коментари</strong> на файлове <em>(винаги изписвани в stream-а)</em>", + "You commented" : "Вие коментирахте" }, "nplurals=2; plural=(n != 1);"); diff --git a/apps/comments/l10n/bg_BG.json b/apps/comments/l10n/bg_BG.json index 78ad0b57d4c..64f516861ca 100644 --- a/apps/comments/l10n/bg_BG.json +++ b/apps/comments/l10n/bg_BG.json @@ -1,6 +1,17 @@ { "translations": { + "Type in a new comment..." : "Напиши нов коментар...", + "Delete comment" : "Изтрий коментар", "Cancel" : "Отказ", + "Edit comment" : "Редактирай коментра", + "[Deleted user]" : "[Изтрит потребител]", + "Comments" : "Коментари", + "No other comments available" : "Няма други коментари", + "More comments..." : "Още коментари...", "Save" : "Запазване", - "Comment" : "Коментар" + "Allowed characters {count} of {max}" : "Позволени символи {count} от {max}", + "{count} unread comments" : "{count} нечетени коментари", + "Comment" : "Коментар", + "<strong>Comments</strong> for files <em>(always listed in stream)</em>" : "<strong>Коментари</strong> на файлове <em>(винаги изписвани в stream-а)</em>", + "You commented" : "Вие коментирахте" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/apps/dav/appinfo/database.xml b/apps/dav/appinfo/database.xml index f79ea07ae76..9578526a705 100644 --- a/apps/dav/appinfo/database.xml +++ b/apps/dav/appinfo/database.xml @@ -272,6 +272,12 @@ CREATE TABLE calendarobjects ( <type>text</type> <length>255</length> </field> + <field> + <comments>0 - public, 1 - private, 2 - confidential</comments> + <name>classification</name> + <type>integer</type> + <default>0</default> + </field> <index> <name>calobjects_index</name> <unique>true</unique> diff --git a/apps/dav/appinfo/info.xml b/apps/dav/appinfo/info.xml index ca456b03089..26e37e6bb86 100644 --- a/apps/dav/appinfo/info.xml +++ b/apps/dav/appinfo/info.xml @@ -5,7 +5,7 @@ <description>ownCloud WebDAV endpoint</description> <licence>AGPL</licence> <author>owncloud.org</author> - <version>0.2.4</version> + <version>0.2.5</version> <default_enable/> <types> <filesystem/> @@ -20,4 +20,9 @@ <background-jobs> <job>OCA\DAV\CardDAV\Sync\SyncJob</job> </background-jobs> + <repair-steps> + <post-migration> + <job>OCA\DAV\Migration\Classification</job> + </post-migration> + </repair-steps> </info> diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php index c6c319aa36d..261a4d4b96d 100644 --- a/apps/dav/appinfo/v1/publicwebdav.php +++ b/apps/dav/appinfo/v1/publicwebdav.php @@ -66,7 +66,6 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, func $share = $authBackend->getShare(); $owner = $share->getShareOwner(); - $isWritable = $share->getPermissions() & (\OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_CREATE); $isReadable = $share->getPermissions() & \OCP\Constants::PERMISSION_READ; $fileId = $share->getNodeId(); @@ -74,11 +73,9 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authBackend, func return false; } - if (!$isWritable) { - \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, $storage) { - return new \OC\Files\Storage\Wrapper\PermissionsMask(array('storage' => $storage, 'mask' => \OCP\Constants::PERMISSION_READ + \OCP\Constants::PERMISSION_SHARE)); - }); - } + \OC\Files\Filesystem::addStorageWrapper('sharePermissions', function ($mountPoint, $storage) use ($share) { + return new \OC\Files\Storage\Wrapper\PermissionsMask(array('storage' => $storage, 'mask' => $share->getPermissions() | \OCP\Constants::PERMISSION_SHARE)); + }); OC_Util::setupFS($owner); $ownerView = \OC\Files\Filesystem::getView(); diff --git a/apps/dav/lib/AppInfo/Application.php b/apps/dav/lib/AppInfo/Application.php index ba0ef421f97..9e0d2da4e17 100644 --- a/apps/dav/lib/AppInfo/Application.php +++ b/apps/dav/lib/AppInfo/Application.php @@ -31,10 +31,12 @@ use OCA\DAV\CardDAV\SyncService; use OCA\DAV\Connector\Sabre\Principal; use OCA\DAV\DAV\GroupPrincipalBackend; use OCA\DAV\HookManager; +use OCA\DAV\Migration\Classification; use \OCP\AppFramework\App; use OCP\AppFramework\IAppContainer; use OCP\Contacts\IManager; use OCP\IUser; +use Sabre\VObject\Reader; use Symfony\Component\EventDispatcher\GenericEvent; class Application extends App { @@ -106,6 +108,14 @@ class Application extends App { $g ); }); + + $container->registerService('OCA\DAV\Migration\Classification', function ($c) { + /** @var IAppContainer $c */ + return new Classification( + $c->query('CalDavBackend'), + $c->getServer()->getUserManager() + ); + }); } /** diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index 64fdf0f7ebe..ce494082976 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -37,10 +37,11 @@ use Sabre\CalDAV\Xml\Property\ScheduleCalendarTransp; use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet; use Sabre\DAV; use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\PropPatch; use Sabre\HTTP\URLUtil; use Sabre\VObject\DateTimeParser; use Sabre\VObject\Reader; -use Sabre\VObject\RecurrenceIterator; +use Sabre\VObject\Recur\EventIterator; /** * Class CalDavBackend @@ -61,6 +62,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription */ const MAX_DATE = '2038-01-01'; + const CLASSIFICATION_PUBLIC = 0; + const CLASSIFICATION_PRIVATE = 1; + const CLASSIFICATION_CONFIDENTIAL = 2; + /** * List of CalDAV properties, and how they map to database field names * Add your own properties by simply adding on to this array. @@ -395,10 +400,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * * Read the PropPatch documentation for more info and examples. * - * @param \Sabre\DAV\PropPatch $propPatch + * @param PropPatch $propPatch * @return void */ - function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) { + function updateCalendar($calendarId, PropPatch $propPatch) { $supportedProperties = array_keys($this->propertyMap); $supportedProperties[] = '{' . Plugin::NS_CALDAV . '}schedule-calendar-transp'; @@ -484,7 +489,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription */ function getCalendarObjects($calendarId) { $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'componenttype']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'componenttype', 'classification']) ->from('calendarobjects') ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))); $stmt = $query->execute(); @@ -499,6 +504,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'calendarid' => $row['calendarid'], 'size' => (int)$row['size'], 'component' => strtolower($row['componenttype']), + 'classification'=> (int)$row['classification'] ]; } @@ -524,7 +530,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription function getCalendarObject($calendarId, $objectUri) { $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification']) ->from('calendarobjects') ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))); @@ -542,6 +548,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'size' => (int)$row['size'], 'calendardata' => $this->readBlob($row['calendardata']), 'component' => strtolower($row['componenttype']), + 'classification'=> (int)$row['classification'] ]; } @@ -559,7 +566,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription */ function getMultipleCalendarObjects($calendarId, array $uris) { $query = $this->db->getQueryBuilder(); - $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype']) + $query->select(['id', 'uri', 'lastmodified', 'etag', 'calendarid', 'size', 'calendardata', 'componenttype', 'classification']) ->from('calendarobjects') ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) ->andWhere($query->expr()->in('uri', $query->createParameter('uri'))) @@ -579,6 +586,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'size' => (int)$row['size'], 'calendardata' => $this->readBlob($row['calendardata']), 'component' => strtolower($row['componenttype']), + 'classification' => (int)$row['classification'] ]; } @@ -618,6 +626,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription 'componenttype' => $query->createNamedParameter($extraData['componentType']), 'firstoccurence' => $query->createNamedParameter($extraData['firstOccurence']), 'lastoccurence' => $query->createNamedParameter($extraData['lastOccurence']), + 'classification' => $query->createNamedParameter($extraData['classification']), 'uid' => $query->createNamedParameter($extraData['uid']), ]) ->execute(); @@ -657,6 +666,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription ->set('componenttype', $query->createNamedParameter($extraData['componentType'])) ->set('firstoccurence', $query->createNamedParameter($extraData['firstOccurence'])) ->set('lastoccurence', $query->createNamedParameter($extraData['lastOccurence'])) + ->set('classification', $query->createNamedParameter($extraData['classification'])) ->set('uid', $query->createNamedParameter($extraData['uid'])) ->where($query->expr()->eq('calendarid', $query->createNamedParameter($calendarId))) ->andWhere($query->expr()->eq('uri', $query->createNamedParameter($objectUri))) @@ -668,6 +678,23 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } /** + * @param int $calendarObjectId + * @param int $classification + */ + public function setClassification($calendarObjectId, $classification) { + if (!in_array($classification, [ + self::CLASSIFICATION_PUBLIC, self::CLASSIFICATION_PRIVATE, self::CLASSIFICATION_CONFIDENTIAL + ])) { + throw new \InvalidArgumentException(); + } + $query = $this->db->getQueryBuilder(); + $query->update('calendarobjects') + ->set('classification', $query->createNamedParameter($classification)) + ->where($query->expr()->eq('id', $query->createNamedParameter($calendarObjectId))) + ->execute(); + } + + /** * Deletes an existing calendar object. * * The object uri is only the basename, or filename and not a full path. @@ -1086,10 +1113,10 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * Read the PropPatch documentation for more info and examples. * * @param mixed $subscriptionId - * @param \Sabre\DAV\PropPatch $propPatch + * @param PropPatch $propPatch * @return void */ - function updateSubscription($subscriptionId, DAV\PropPatch $propPatch) { + function updateSubscription($subscriptionId, PropPatch $propPatch) { $supportedProperties = array_keys($this->subscriptionPropertyMap); $supportedProperties[] = '{http://calendarserver.org/ns/}source'; @@ -1280,14 +1307,15 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription * @param string $calendarData * @return array */ - protected function getDenormalizedData($calendarData) { + public function getDenormalizedData($calendarData) { $vObject = Reader::read($calendarData); $componentType = null; $component = null; - $firstOccurence = null; - $lastOccurence = null; + $firstOccurrence = null; + $lastOccurrence = null; $uid = null; + $classification = self::CLASSIFICATION_PUBLIC; foreach($vObject->getComponents() as $component) { if ($component->name!=='VTIMEZONE') { $componentType = $component->name; @@ -1299,27 +1327,27 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription throw new \Sabre\DAV\Exception\BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component'); } if ($componentType === 'VEVENT' && $component->DTSTART) { - $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp(); + $firstOccurrence = $component->DTSTART->getDateTime()->getTimeStamp(); // Finding the last occurrence is a bit harder if (!isset($component->RRULE)) { if (isset($component->DTEND)) { - $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp(); + $lastOccurrence = $component->DTEND->getDateTime()->getTimeStamp(); } elseif (isset($component->DURATION)) { $endDate = clone $component->DTSTART->getDateTime(); $endDate->add(DateTimeParser::parse($component->DURATION->getValue())); - $lastOccurence = $endDate->getTimeStamp(); + $lastOccurrence = $endDate->getTimeStamp(); } elseif (!$component->DTSTART->hasTime()) { $endDate = clone $component->DTSTART->getDateTime(); $endDate->modify('+1 day'); - $lastOccurence = $endDate->getTimeStamp(); + $lastOccurrence = $endDate->getTimeStamp(); } else { - $lastOccurence = $firstOccurence; + $lastOccurrence = $firstOccurrence; } } else { - $it = new RecurrenceIterator($vObject, (string)$component->UID); + $it = new EventIterator($vObject, (string)$component->UID); $maxDate = new \DateTime(self::MAX_DATE); if ($it->isInfinite()) { - $lastOccurence = $maxDate->getTimeStamp(); + $lastOccurrence = $maxDate->getTimeStamp(); } else { $end = $it->getDtEnd(); while($it->valid() && $end < $maxDate) { @@ -1327,19 +1355,31 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $it->next(); } - $lastOccurence = $end->getTimeStamp(); + $lastOccurrence = $end->getTimeStamp(); } } } + if ($component->CLASS) { + $classification = CalDavBackend::CLASSIFICATION_PRIVATE; + switch ($component->CLASS->getValue()) { + case 'PUBLIC': + $classification = CalDavBackend::CLASSIFICATION_PUBLIC; + break; + case 'CONFIDENTIAL': + $classification = CalDavBackend::CLASSIFICATION_CONFIDENTIAL; + break; + } + } return [ - 'etag' => md5($calendarData), - 'size' => strlen($calendarData), - 'componentType' => $componentType, - 'firstOccurence' => is_null($firstOccurence) ? null : max(0, $firstOccurence), - 'lastOccurence' => $lastOccurence, - 'uid' => $uid, + 'etag' => md5($calendarData), + 'size' => strlen($calendarData), + 'componentType' => $componentType, + 'firstOccurence' => is_null($firstOccurrence) ? null : max(0, $firstOccurrence), + 'lastOccurence' => $lastOccurrence, + 'uid' => $uid, + 'classification' => $classification ]; } diff --git a/apps/dav/lib/CalDAV/Calendar.php b/apps/dav/lib/CalDAV/Calendar.php index 73b3957a9b0..785bb5699e2 100644 --- a/apps/dav/lib/CalDAV/Calendar.php +++ b/apps/dav/lib/CalDAV/Calendar.php @@ -26,6 +26,7 @@ use OCA\DAV\DAV\Sharing\IShareable; use OCP\IL10N; use Sabre\CalDAV\Backend\BackendInterface; use Sabre\DAV\Exception\Forbidden; +use Sabre\DAV\Exception\NotFound; use Sabre\DAV\PropPatch; class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { @@ -162,6 +163,78 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { parent::propPatch($propPatch); } + function getChild($name) { + + $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); + + if (!$obj) { + throw new NotFound('Calendar object not found'); + } + + if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) { + throw new NotFound('Calendar object not found'); + } + + $obj['acl'] = $this->getChildACL(); + + return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); + + } + + function getChildren() { + + $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']); + $children = []; + foreach ($objs as $obj) { + if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) { + continue; + } + $obj['acl'] = $this->getChildACL(); + $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); + } + return $children; + + } + + function getMultipleChildren(array $paths) { + + $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths); + $children = []; + foreach ($objs as $obj) { + if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) { + continue; + } + $obj['acl'] = $this->getChildACL(); + $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj); + } + return $children; + + } + + function childExists($name) { + $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name); + if (!$obj) { + return false; + } + if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) { + return false; + } + + return true; + } + + function calendarQuery(array $filters) { + + $uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters); + if ($this->isShared()) { + return array_filter($uris, function ($uri) { + return $this->childExists($uri); + }); + } + + return $uris; + } + private function canWrite() { if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) { return !$this->calendarInfo['{http://owncloud.org/ns}read-only']; @@ -169,4 +242,8 @@ class Calendar extends \Sabre\CalDAV\Calendar implements IShareable { return true; } + private function isShared() { + return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']); + } + } diff --git a/apps/dav/lib/CalDAV/CalendarObject.php b/apps/dav/lib/CalDAV/CalendarObject.php new file mode 100644 index 00000000000..b4a58b52093 --- /dev/null +++ b/apps/dav/lib/CalDAV/CalendarObject.php @@ -0,0 +1,92 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, 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\CalDAV; + + +use Sabre\VObject\Component; +use Sabre\VObject\Property; +use Sabre\VObject\Reader; + +class CalendarObject extends \Sabre\CalDAV\CalendarObject { + + /** + * @inheritdoc + */ + function get() { + $data = parent::get(); + if ($this->isShared() && $this->objectData['classification'] === CalDavBackend::CLASSIFICATION_CONFIDENTIAL) { + return $this->createConfidentialObject($data); + } + return $data; + } + + private function isShared() { + return isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']); + } + + /** + * @param string $calData + * @return string + */ + private static function createConfidentialObject($calData) { + + $vObject = Reader::read($calData); + + /** @var Component $vElement */ + $vElement = null; + if(isset($vObject->VEVENT)) { + $vElement = $vObject->VEVENT; + } + if(isset($vObject->VJOURNAL)) { + $vElement = $vObject->VJOURNAL; + } + if(isset($vObject->VTODO)) { + $vElement = $vObject->VTODO; + } + if(!is_null($vElement)) { + foreach ($vElement->children as &$property) { + /** @var Property $property */ + switch($property->name) { + case 'CREATED': + case 'DTSTART': + case 'RRULE': + case 'DURATION': + case 'DTEND': + case 'CLASS': + case 'UID': + break; + case 'SUMMARY': + $property->setValue('Busy'); + break; + default: + $vElement->__unset($property->name); + unset($property); + break; + } + } + } + + return $vObject->serialize(); + } + +} diff --git a/apps/dav/lib/Connector/PublicAuth.php b/apps/dav/lib/Connector/PublicAuth.php index 2716ca29107..4e63ca1d29e 100644 --- a/apps/dav/lib/Connector/PublicAuth.php +++ b/apps/dav/lib/Connector/PublicAuth.php @@ -31,13 +31,14 @@ use OCP\IRequest; use OCP\ISession; use OCP\Share\Exceptions\ShareNotFound; use OCP\Share\IManager; +use Sabre\DAV\Auth\Backend\AbstractBasic; /** * Class PublicAuth * * @package OCA\DAV\Connector */ -class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic { +class PublicAuth extends AbstractBasic { /** @var \OCP\Share\IShare */ private $share; @@ -62,6 +63,10 @@ class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic { $this->request = $request; $this->shareManager = $shareManager; $this->session = $session; + + // setup realm + $defaults = new \OC_Defaults(); + $this->realm = $defaults->getName(); } /** @@ -99,7 +104,7 @@ class PublicAuth extends \Sabre\DAV\Auth\Backend\AbstractBasic { if (in_array('XMLHttpRequest', explode(',', $this->request->getHeader('X-Requested-With')))) { // do not re-authenticate over ajax, use dummy auth name to prevent browser popup http_response_code(401); - header('WWW-Authenticate', 'DummyBasic real="ownCloud"'); + header('WWW-Authenticate','DummyBasic realm="' . $this->realm . '"'); throw new \Sabre\DAV\Exception\NotAuthenticated('Cannot authenticate over ajax calls'); } return false; diff --git a/apps/dav/lib/Connector/Sabre/Auth.php b/apps/dav/lib/Connector/Sabre/Auth.php index 27900cc1cad..653da10bc3c 100644 --- a/apps/dav/lib/Connector/Sabre/Auth.php +++ b/apps/dav/lib/Connector/Sabre/Auth.php @@ -74,6 +74,10 @@ class Auth extends AbstractBasic { $this->twoFactorManager = $twoFactorManager; $this->request = $request; $this->principalPrefix = $principalPrefix; + + // setup realm + $defaults = new \OC_Defaults(); + $this->realm = $defaults->getName(); } /** diff --git a/apps/dav/lib/Connector/Sabre/FilesPlugin.php b/apps/dav/lib/Connector/Sabre/FilesPlugin.php index dc47416cca8..0a2e6713cb4 100644 --- a/apps/dav/lib/Connector/Sabre/FilesPlugin.php +++ b/apps/dav/lib/Connector/Sabre/FilesPlugin.php @@ -42,6 +42,7 @@ use \Sabre\HTTP\RequestInterface; use \Sabre\HTTP\ResponseInterface; use OCP\Files\StorageNotAvailableException; use OCP\IConfig; +use OCP\IRequest; class FilesPlugin extends ServerPlugin { @@ -96,19 +97,28 @@ class FilesPlugin extends ServerPlugin { private $config; /** + * @var IRequest + */ + private $request; + + /** * @param Tree $tree * @param View $view + * @param IConfig $config + * @param IRequest $request * @param bool $isPublic * @param bool $downloadAttachment */ public function __construct(Tree $tree, View $view, IConfig $config, + IRequest $request, $isPublic = false, $downloadAttachment = true) { $this->tree = $tree; $this->fileView = $view; $this->config = $config; + $this->request = $request; $this->isPublic = $isPublic; $this->downloadAttachment = $downloadAttachment; } @@ -225,7 +235,18 @@ class FilesPlugin extends ServerPlugin { // adds a 'Content-Disposition: attachment' header if ($this->downloadAttachment) { - $response->addHeader('Content-Disposition', 'attachment'); + $filename = $node->getName(); + if ($this->request->isUserAgent( + [ + \OC\AppFramework\Http\Request::USER_AGENT_IE, + \OC\AppFramework\Http\Request::USER_AGENT_ANDROID_MOBILE_CHROME, + \OC\AppFramework\Http\Request::USER_AGENT_FREEBOX, + ])) { + $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"'); + } else { + $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename) + . '; filename="' . rawurlencode($filename) . '"'); + } } if ($node instanceof \OCA\DAV\Connector\Sabre\File) { diff --git a/apps/dav/lib/Connector/Sabre/ServerFactory.php b/apps/dav/lib/Connector/Sabre/ServerFactory.php index b193bfc76c7..c5b4f6a9352 100644 --- a/apps/dav/lib/Connector/Sabre/ServerFactory.php +++ b/apps/dav/lib/Connector/Sabre/ServerFactory.php @@ -100,10 +100,9 @@ class ServerFactory { $server->setBaseUri($baseUri); // Load plugins - $defaults = new \OC_Defaults(); $server->addPlugin(new \OCA\DAV\Connector\Sabre\MaintenancePlugin($this->config)); $server->addPlugin(new \OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin($this->config)); - $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend, $defaults->getName())); + $server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend)); // FIXME: The following line is a workaround for legacy components relying on being able to send a GET to / $server->addPlugin(new \OCA\DAV\Connector\Sabre\DummyGetResponsePlugin()); $server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $this->logger)); @@ -144,6 +143,7 @@ class ServerFactory { $objectTree, $view, $this->config, + $this->request, false, !$this->config->getSystemValue('debug', false) ) diff --git a/apps/dav/lib/Migration/Classification.php b/apps/dav/lib/Migration/Classification.php new file mode 100644 index 00000000000..b793f790af5 --- /dev/null +++ b/apps/dav/lib/Migration/Classification.php @@ -0,0 +1,93 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, 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\Migration; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class Classification implements IRepairStep { + + /** @var CalDavBackend */ + private $calDavBackend; + + /** @var IUserManager */ + private $userManager; + + /** + * Classification constructor. + * + * @param CalDavBackend $calDavBackend + */ + public function __construct(CalDavBackend $calDavBackend, IUserManager $userManager) { + $this->calDavBackend = $calDavBackend; + $this->userManager = $userManager; + } + + /** + * @param IUser $user + */ + public function runForUser($user) { + $principal = 'principals/users/' . $user->getUID(); + $calendars = $this->calDavBackend->getCalendarsForUser($principal); + foreach ($calendars as $calendar) { + $objects = $this->calDavBackend->getCalendarObjects($calendar['id']); + foreach ($objects as $object) { + $calObject = $this->calDavBackend->getCalendarObject($calendar['id'], $object['uri']); + $classification = $this->extractClassification($calObject['calendardata']); + $this->calDavBackend->setClassification($object['id'], $classification); + } + } + } + + /** + * @param $calendarData + * @return integer + * @throws \Sabre\DAV\Exception\BadRequest + */ + protected function extractClassification($calendarData) { + return $this->calDavBackend->getDenormalizedData($calendarData)['classification']; + } + + /** + * @inheritdoc + */ + public function getName() { + return 'Fix classification for calendar objects'; + } + + /** + * @inheritdoc + */ + public function run(IOutput $output) { + $output->startProgress(); + $this->userManager->callForAllUsers(function($user) use ($output) { + /** @var IUser $user */ + $output->advance(1, $user->getDisplayName()); + $this->runForUser($user); + }); + $output->finishProgress(); + } +} diff --git a/apps/dav/lib/Server.php b/apps/dav/lib/Server.php index 179558e97ae..e150f441b82 100644 --- a/apps/dav/lib/Server.php +++ b/apps/dav/lib/Server.php @@ -141,6 +141,7 @@ class Server { $this->server->tree, $view, \OC::$server->getConfig(), + $this->request, false, !\OC::$server->getConfig()->getSystemValue('debug', false) ) diff --git a/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php new file mode 100644 index 00000000000..49e5e5a2bcc --- /dev/null +++ b/apps/dav/tests/unit/CalDAV/AbstractCalDavBackendTest.php @@ -0,0 +1,163 @@ +<?php +/** + * @author Joas Schilling <nickvergessen@owncloud.com> + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, 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\Tests\unit\CalDAV; + +use DateTime; +use DateTimeZone; +use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\CalDAV\Calendar; +use OCA\DAV\Connector\Sabre\Principal; +use OCP\IL10N; +use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet; +use Sabre\DAV\PropPatch; +use Sabre\DAV\Xml\Property\Href; +use Sabre\DAVACL\IACL; +use Test\TestCase; + +/** + * Class CalDavBackendTest + * + * @group DB + * + * @package OCA\DAV\Tests\unit\CalDAV + */ +abstract class AbstractCalDavBackendTest extends TestCase { + + /** @var CalDavBackend */ + protected $backend; + + /** @var Principal | \PHPUnit_Framework_MockObject_MockObject */ + protected $principal; + + const UNIT_TEST_USER = 'principals/users/caldav-unit-test'; + const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1'; + const UNIT_TEST_GROUP = 'principals/groups/caldav-unit-test-group'; + + public function setUp() { + parent::setUp(); + + $this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') + ->disableOriginalConstructor() + ->setMethods(['getPrincipalByPath', 'getGroupMembership']) + ->getMock(); + $this->principal->expects($this->any())->method('getPrincipalByPath') + ->willReturn([ + 'uri' => 'principals/best-friend' + ]); + $this->principal->expects($this->any())->method('getGroupMembership') + ->withAnyParameters() + ->willReturn([self::UNIT_TEST_GROUP]); + + $db = \OC::$server->getDatabaseConnection(); + $this->backend = new CalDavBackend($db, $this->principal); + + $this->tearDown(); + } + + public function tearDown() { + parent::tearDown(); + + if (is_null($this->backend)) { + return; + } + $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + foreach ($books as $book) { + $this->backend->deleteCalendar($book['id']); + } + $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); + foreach ($subscriptions as $subscription) { + $this->backend->deleteSubscription($subscription['id']); + } + } + + protected function createTestCalendar() { + $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', [ + '{http://apple.com/ns/ical/}calendar-color' => '#1C4587FF' + ]); + $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); + $this->assertEquals(1, count($calendars)); + $this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']); + /** @var SupportedCalendarComponentSet $components */ + $components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; + $this->assertEquals(['VEVENT','VTODO'], $components->getValue()); + $color = $calendars[0]['{http://apple.com/ns/ical/}calendar-color']; + $this->assertEquals('#1C4587FF', $color); + $this->assertEquals('Example', $calendars[0]['uri']); + $this->assertEquals('Example', $calendars[0]['{DAV:}displayname']); + $calendarId = $calendars[0]['id']; + + return $calendarId; + } + + protected function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { + + $calData = <<<EOD +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:ownCloud Calendar +BEGIN:VEVENT +CREATED;VALUE=DATE-TIME:20130910T125139Z +UID:47d15e3ec8 +LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z +DTSTAMP;VALUE=DATE-TIME:20130910T125139Z +SUMMARY:Test Event +DTSTART;VALUE=DATE-TIME:$start +DTEND;VALUE=DATE-TIME:$end +CLASS:PUBLIC +END:VEVENT +END:VCALENDAR +EOD; + $uri0 = $this->getUniqueID('event'); + $this->backend->createCalendarObject($calendarId, $uri0, $calData); + + return $uri0; + } + + protected function assertAcl($principal, $privilege, $acl) { + foreach($acl as $a) { + if ($a['principal'] === $principal && $a['privilege'] === $privilege) { + $this->assertTrue(true); + return; + } + } + $this->fail("ACL does not contain $principal / $privilege"); + } + + protected function assertNotAcl($principal, $privilege, $acl) { + foreach($acl as $a) { + if ($a['principal'] === $principal && $a['privilege'] === $privilege) { + $this->fail("ACL contains $principal / $privilege"); + return; + } + } + $this->assertTrue(true); + } + + protected function assertAccess($shouldHaveAcl, $principal, $privilege, $acl) { + if ($shouldHaveAcl) { + $this->assertAcl($principal, $privilege, $acl); + } else { + $this->assertNotAcl($principal, $privilege, $acl); + } + } +} diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php index c3e32e436d9..977bdf15c8e 100644 --- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php +++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php @@ -26,13 +26,10 @@ use DateTime; use DateTimeZone; use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\Calendar; -use OCA\DAV\Connector\Sabre\Principal; use OCP\IL10N; -use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet; use Sabre\DAV\PropPatch; use Sabre\DAV\Xml\Property\Href; use Sabre\DAVACL\IACL; -use Test\TestCase; /** * Class CalDavBackendTest @@ -41,54 +38,7 @@ use Test\TestCase; * * @package OCA\DAV\Tests\unit\CalDAV */ -class CalDavBackendTest extends TestCase { - - /** @var CalDavBackend */ - private $backend; - - /** @var Principal | \PHPUnit_Framework_MockObject_MockObject */ - private $principal; - - const UNIT_TEST_USER = 'principals/users/caldav-unit-test'; - const UNIT_TEST_USER1 = 'principals/users/caldav-unit-test1'; - const UNIT_TEST_GROUP = 'principals/groups/caldav-unit-test-group'; - - public function setUp() { - parent::setUp(); - - $this->principal = $this->getMockBuilder('OCA\DAV\Connector\Sabre\Principal') - ->disableOriginalConstructor() - ->setMethods(['getPrincipalByPath', 'getGroupMembership']) - ->getMock(); - $this->principal->expects($this->any())->method('getPrincipalByPath') - ->willReturn([ - 'uri' => 'principals/best-friend' - ]); - $this->principal->expects($this->any())->method('getGroupMembership') - ->withAnyParameters() - ->willReturn([self::UNIT_TEST_GROUP]); - - $db = \OC::$server->getDatabaseConnection(); - $this->backend = new CalDavBackend($db, $this->principal); - - $this->tearDown(); - } - - public function tearDown() { - parent::tearDown(); - - if (is_null($this->backend)) { - return; - } - $books = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); - foreach ($books as $book) { - $this->backend->deleteCalendar($book['id']); - } - $subscriptions = $this->backend->getSubscriptionsForUser(self::UNIT_TEST_USER); - foreach ($subscriptions as $subscription) { - $this->backend->deleteSubscription($subscription['id']); - } - } +class CalDavBackendTest extends AbstractCalDavBackendTest { public function testCalendarOperations() { @@ -232,6 +182,7 @@ EOD; $calendarObjects = $this->backend->getCalendarObjects($calendarId); $this->assertEquals(1, count($calendarObjects)); $this->assertEquals($calendarId, $calendarObjects[0]['calendarid']); + $this->assertArrayHasKey('classification', $calendarObjects[0]); // get the cards $calendarObject = $this->backend->getCalendarObject($calendarId, $uri); @@ -241,6 +192,7 @@ EOD; $this->assertArrayHasKey('lastmodified', $calendarObject); $this->assertArrayHasKey('etag', $calendarObject); $this->assertArrayHasKey('size', $calendarObject); + $this->assertArrayHasKey('classification', $calendarObject); $this->assertEquals($calData, $calendarObject['calendardata']); // update the card @@ -310,6 +262,7 @@ EOD; $this->assertArrayHasKey('lastmodified', $card); $this->assertArrayHasKey('etag', $card); $this->assertArrayHasKey('size', $card); + $this->assertArrayHasKey('classification', $card); $this->assertEquals($calData, $card['calendardata']); } @@ -363,49 +316,6 @@ EOD; ]; } - private function createTestCalendar() { - $this->backend->createCalendar(self::UNIT_TEST_USER, 'Example', [ - '{http://apple.com/ns/ical/}calendar-color' => '#1C4587FF' - ]); - $calendars = $this->backend->getCalendarsForUser(self::UNIT_TEST_USER); - $this->assertEquals(1, count($calendars)); - $this->assertEquals(self::UNIT_TEST_USER, $calendars[0]['principaluri']); - /** @var SupportedCalendarComponentSet $components */ - $components = $calendars[0]['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']; - $this->assertEquals(['VEVENT','VTODO'], $components->getValue()); - $color = $calendars[0]['{http://apple.com/ns/ical/}calendar-color']; - $this->assertEquals('#1C4587FF', $color); - $this->assertEquals('Example', $calendars[0]['uri']); - $this->assertEquals('Example', $calendars[0]['{DAV:}displayname']); - $calendarId = $calendars[0]['id']; - - return $calendarId; - } - - private function createEvent($calendarId, $start = '20130912T130000Z', $end = '20130912T140000Z') { - - $calData = <<<EOD -BEGIN:VCALENDAR -VERSION:2.0 -PRODID:ownCloud Calendar -BEGIN:VEVENT -CREATED;VALUE=DATE-TIME:20130910T125139Z -UID:47d15e3ec8 -LAST-MODIFIED;VALUE=DATE-TIME:20130910T125139Z -DTSTAMP;VALUE=DATE-TIME:20130910T125139Z -SUMMARY:Test Event -DTSTART;VALUE=DATE-TIME:$start -DTEND;VALUE=DATE-TIME:$end -CLASS:PUBLIC -END:VEVENT -END:VCALENDAR -EOD; - $uri0 = $this->getUniqueID('event'); - $this->backend->createCalendarObject($calendarId, $uri0, $calData); - - return $uri0; - } - public function testSyncSupport() { $calendarId = $this->createTestCalendar(); @@ -464,43 +374,20 @@ EOD; /** * @dataProvider providesCalDataForGetDenormalizedData */ - public function testGetDenormalizedData($expectedFirstOccurance, $calData) { - $actual = $this->invokePrivate($this->backend, 'getDenormalizedData', [$calData]); - $this->assertEquals($expectedFirstOccurance, $actual['firstOccurence']); + public function testGetDenormalizedData($expected, $key, $calData) { + $actual = $this->backend->getDenormalizedData($calData); + $this->assertEquals($expected, $actual[$key]); } public function providesCalDataForGetDenormalizedData() { return [ - [0, "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nDTSTART;VALUE=DATE:16040222\r\nDTEND;VALUE=DATE:16040223\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], - [null, "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"] + 'first occurrence before unix epoch starts' => [0, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nDTSTART;VALUE=DATE:16040222\r\nDTEND;VALUE=DATE:16040223\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], + 'no first occurrence because yearly' => [null, 'firstOccurence', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Sabre//Sabre VObject 3.5.0//EN\r\nCALSCALE:GREGORIAN\r\nBEGIN:VEVENT\r\nUID:413F269B-B51B-46B1-AFB6-40055C53A4DC\r\nDTSTAMP:20160309T095056Z\r\nRRULE:FREQ=YEARLY\r\nSUMMARY:SUMMARY\r\nTRANSP:TRANSPARENT\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n"], + 'CLASS:PRIVATE' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:PRIVATE\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"], + 'CLASS:PUBLIC' => [CalDavBackend::CLASSIFICATION_PUBLIC, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:PUBLIC\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"], + 'CLASS:CONFIDENTIAL' => [CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:CONFIDENTIAL\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"], + 'no class set -> public' => [CalDavBackend::CLASSIFICATION_PUBLIC, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nTRANSP:OPAQUE\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"], + 'unknown class -> private' => [CalDavBackend::CLASSIFICATION_PRIVATE, 'classification', "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//dmfs.org//mimedir.icalendar//EN\r\nBEGIN:VTIMEZONE\r\nTZID:Europe/Berlin\r\nX-LIC-LOCATION:Europe/Berlin\r\nBEGIN:DAYLIGHT\r\nTZOFFSETFROM:+0100\r\nTZOFFSETTO:+0200\r\nTZNAME:CEST\r\nDTSTART:19700329T020000\r\nRRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\r\nEND:DAYLIGHT\r\nBEGIN:STANDARD\r\nTZOFFSETFROM:+0200\r\nTZOFFSETTO:+0100\r\nTZNAME:CET\r\nDTSTART:19701025T030000\r\nRRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\r\nEND:STANDARD\r\nEND:VTIMEZONE\r\nBEGIN:VEVENT\r\nDTSTART;TZID=Europe/Berlin:20160419T130000\r\nSUMMARY:Test\r\nCLASS:VERTRAULICH\r\nTRANSP:OPAQUE\r\nSTATUS:CONFIRMED\r\nDTEND;TZID=Europe/Berlin:20160419T140000\r\nLAST-MODIFIED:20160419T074202Z\r\nDTSTAMP:20160419T074202Z\r\nCREATED:20160419T074202Z\r\nUID:2e468c48-7860-492e-bc52-92fa0daeeccf.1461051722310\r\nEND:VEVENT\r\nEND:VCALENDAR"], ]; } - - private function assertAcl($principal, $privilege, $acl) { - foreach($acl as $a) { - if ($a['principal'] === $principal && $a['privilege'] === $privilege) { - $this->assertTrue(true); - return; - } - } - $this->fail("ACL does not contain $principal / $privilege"); - } - - private function assertNotAcl($principal, $privilege, $acl) { - foreach($acl as $a) { - if ($a['principal'] === $principal && $a['privilege'] === $privilege) { - $this->fail("ACL contains $principal / $privilege"); - return; - } - } - $this->assertTrue(true); - } - - private function assertAccess($shouldHaveAcl, $principal, $privilege, $acl) { - if ($shouldHaveAcl) { - $this->assertAcl($principal, $privilege, $acl); - } else { - $this->assertNotAcl($principal, $privilege, $acl); - } - } } diff --git a/apps/dav/tests/unit/CalDAV/CalendarTest.php b/apps/dav/tests/unit/CalDAV/CalendarTest.php index 73d85e82bbc..56a2d4fcba7 100644 --- a/apps/dav/tests/unit/CalDAV/CalendarTest.php +++ b/apps/dav/tests/unit/CalDAV/CalendarTest.php @@ -27,6 +27,7 @@ use OCA\DAV\CalDAV\CalDavBackend; use OCA\DAV\CalDAV\Calendar; use OCP\IL10N; use Sabre\DAV\PropPatch; +use Sabre\VObject\Reader; use Test\TestCase; class CalendarTest extends TestCase { @@ -189,4 +190,153 @@ class CalendarTest extends TestCase { 'birthday calendar' => [false, false, false, BirthdayService::BIRTHDAY_CALENDAR_URI] ]; } + + /** + * @dataProvider providesConfidentialClassificationData + * @param $expectedChildren + * @param $isShared + */ + public function testPrivateClassification($expectedChildren, $isShared) { + + $calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC]; + $calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL]; + $calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE]; + + /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->any())->method('getCalendarObjects')->willReturn([ + $calObject0, $calObject1, $calObject2 + ]); + $backend->expects($this->any())->method('getMultipleCalendarObjects') + ->with(666, ['event-0', 'event-1', 'event-2']) + ->willReturn([ + $calObject0, $calObject1, $calObject2 + ]); + $backend->expects($this->any())->method('getCalendarObject') + ->willReturn($calObject2)->with(666, 'event-2'); + + $calendarInfo = [ + 'principaluri' => 'user2', + 'id' => 666, + 'uri' => 'cal', + ]; + + if ($isShared) { + $calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1'; + + } + $c = new Calendar($backend, $calendarInfo, $this->l10n); + $children = $c->getChildren(); + $this->assertEquals($expectedChildren, count($children)); + $children = $c->getMultipleChildren(['event-0', 'event-1', 'event-2']); + $this->assertEquals($expectedChildren, count($children)); + + $this->assertEquals(!$isShared, $c->childExists('event-2')); + } + + /** + * @dataProvider providesConfidentialClassificationData + * @param $expectedChildren + * @param $isShared + */ + public function testConfidentialClassification($expectedChildren, $isShared) { + $start = '20160609'; + $end = '20160610'; + + $calData = <<<EOD +BEGIN:VCALENDAR +PRODID:-//ownCloud calendar v1.2.2 +BEGIN:VEVENT +CREATED:20160602T133732 +DTSTAMP:20160602T133732 +LAST-MODIFIED:20160602T133732 +UID:wej2z68l9h +SUMMARY:Test Event +LOCATION:Somewhere ... +ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;CN=de + epdiver:MAILTO:thomas.mueller@tmit.eu +ORGANIZER;CN=deepdiver:MAILTO:thomas.mueller@tmit.eu +DESCRIPTION:maybe .... +DTSTART;TZID=Europe/Berlin;VALUE=DATE:$start +DTEND;TZID=Europe/Berlin;VALUE=DATE:$end +RRULE:FREQ=DAILY +BEGIN:VALARM +ACTION:AUDIO +TRIGGER:-PT15M +END:VALARM +END:VEVENT +BEGIN:VTIMEZONE +TZID:Europe/Berlin +BEGIN:DAYLIGHT +DTSTART:19810329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +TZNAME:MESZ +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +END:DAYLIGHT +BEGIN:STANDARD +DTSTART:19961027T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +TZNAME:MEZ +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +END:STANDARD +END:VTIMEZONE +END:VCALENDAR +EOD; + + $calObject0 = ['uri' => 'event-0', 'classification' => CalDavBackend::CLASSIFICATION_PUBLIC]; + $calObject1 = ['uri' => 'event-1', 'classification' => CalDavBackend::CLASSIFICATION_CONFIDENTIAL, 'calendardata' => $calData]; + $calObject2 = ['uri' => 'event-2', 'classification' => CalDavBackend::CLASSIFICATION_PRIVATE]; + + /** @var \PHPUnit_Framework_MockObject_MockObject | CalDavBackend $backend */ + $backend = $this->getMockBuilder('OCA\DAV\CalDAV\CalDavBackend')->disableOriginalConstructor()->getMock(); + $backend->expects($this->any())->method('getCalendarObjects')->willReturn([ + $calObject0, $calObject1, $calObject2 + ]); + $backend->expects($this->any())->method('getMultipleCalendarObjects') + ->with(666, ['event-0', 'event-1', 'event-2']) + ->willReturn([ + $calObject0, $calObject1, $calObject2 + ]); + $backend->expects($this->any())->method('getCalendarObject') + ->willReturn($calObject1)->with(666, 'event-1'); + + $calendarInfo = [ + 'principaluri' => 'user2', + 'id' => 666, + 'uri' => 'cal', + ]; + + if ($isShared) { + $calendarInfo['{http://owncloud.org/ns}owner-principal'] = 'user1'; + + } + $c = new Calendar($backend, $calendarInfo, $this->l10n); + + // test private event + $privateEvent = $c->getChild('event-1'); + $calData = $privateEvent->get(); + $event = Reader::read($calData); + + $this->assertEquals($start, $event->VEVENT->DTSTART->getValue()); + $this->assertEquals($end, $event->VEVENT->DTEND->getValue()); + + if ($isShared) { + $this->assertEquals('Busy', $event->VEVENT->SUMMARY->getValue()); + $this->assertArrayNotHasKey('ATTENDEE', $event->VEVENT); + $this->assertArrayNotHasKey('LOCATION', $event->VEVENT); + $this->assertArrayNotHasKey('DESCRIPTION', $event->VEVENT); + $this->assertArrayNotHasKey('ORGANIZER', $event->VEVENT); + } else { + $this->assertEquals('Test Event', $event->VEVENT->SUMMARY->getValue()); + } + } + + public function providesConfidentialClassificationData() { + return [ + [3, false], + [2, true] + ]; + } } diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php index 80f284e470e..2b3f3e15d1a 100644 --- a/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/FilesPluginTest.php @@ -73,6 +73,11 @@ class FilesPluginTest extends TestCase { */ private $config; + /** + * @var \OCP\IRequest | \PHPUnit_Framework_MockObject_MockObject + */ + private $request; + public function setUp() { parent::setUp(); $this->server = $this->getMockBuilder('\Sabre\DAV\Server') @@ -88,11 +93,13 @@ class FilesPluginTest extends TestCase { $this->config->expects($this->any())->method('getSystemValue') ->with($this->equalTo('data-fingerprint'), $this->equalTo('')) ->willReturn('my_fingerprint'); + $this->request = $this->getMock('\OCP\IRequest'); $this->plugin = new FilesPlugin( $this->tree, $this->view, - $this->config + $this->config, + $this->request ); $this->plugin->initialize($this->server); } @@ -268,6 +275,7 @@ class FilesPluginTest extends TestCase { $this->tree, $this->view, $this->config, + $this->getMock('\OCP\IRequest'), true); $this->plugin->initialize($this->server); @@ -484,4 +492,60 @@ class FilesPluginTest extends TestCase { $this->plugin->checkMove('FolderA/test.txt', 'test.txt'); } + + public function downloadHeadersProvider() { + return [ + [ + false, + 'attachment; filename*=UTF-8\'\'somefile.xml; filename="somefile.xml"' + ], + [ + true, + 'attachment; filename="somefile.xml"' + ], + ]; + } + + /** + * @dataProvider downloadHeadersProvider + */ + public function testDownloadHeaders($isClumsyAgent, $contentDispositionHeader) { + $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('test/somefile.xml')); + + $node = $this->getMockBuilder('\OCA\DAV\Connector\Sabre\File') + ->disableOriginalConstructor() + ->getMock(); + $node + ->expects($this->once()) + ->method('getName') + ->will($this->returnValue('somefile.xml')); + + $this->tree + ->expects($this->once()) + ->method('getNodeForPath') + ->with('test/somefile.xml') + ->will($this->returnValue($node)); + + $this->request + ->expects($this->once()) + ->method('isUserAgent') + ->will($this->returnValue($isClumsyAgent)); + + $response + ->expects($this->once()) + ->method('addHeader') + ->with('Content-Disposition', $contentDispositionHeader); + + $this->plugin->httpGet($request, $response); + } } diff --git a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php index 41d44efd89c..baf4259b215 100644 --- a/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/FilesReportPluginTest.php @@ -343,7 +343,8 @@ class FilesReportPluginTest extends \Test\TestCase { new \OCA\DAV\Connector\Sabre\FilesPlugin( $this->tree, $this->view, - $config + $config, + $this->getMock('\OCP\IRequest') ) ); $this->plugin->initialize($this->server); diff --git a/apps/dav/tests/unit/Migration/ClassificationTest.php b/apps/dav/tests/unit/Migration/ClassificationTest.php new file mode 100644 index 00000000000..5c7fa627226 --- /dev/null +++ b/apps/dav/tests/unit/Migration/ClassificationTest.php @@ -0,0 +1,75 @@ +<?php +/** + * @author Thomas Müller <thomas.mueller@tmit.eu> + * + * @copyright Copyright (c) 2016, 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\Tests\unit\DAV\Migration; + +use OCA\DAV\CalDAV\CalDavBackend; +use OCA\DAV\Migration\Classification; +use OCA\DAV\Tests\unit\CalDAV\AbstractCalDavBackendTest; +use OCP\IUser; + +/** + * Class ClassificationTest + * + * @group DB + * + * @package OCA\DAV\Tests\unit\DAV + */ +class ClassificationTest extends AbstractCalDavBackendTest { + + /** @var \PHPUnit_Framework_MockObject_MockObject | \OCP\IUserManager */ + private $userManager; + + public function setUp() { + parent::setUp(); + + $this->userManager = $this->getMockBuilder('OCP\IUserManager') + ->disableOriginalConstructor()->getMock(); + } + + public function test() { + // setup data + $calendarId = $this->createTestCalendar(); + $eventUri = $this->createEvent($calendarId, '20130912T130000Z', '20130912T140000Z'); + $object = $this->backend->getCalendarObject($calendarId, $eventUri); + + // assert proper classification + $this->assertEquals(CalDavBackend::CLASSIFICATION_PUBLIC, $object['classification']); + $this->backend->setClassification($object['id'], CalDavBackend::CLASSIFICATION_CONFIDENTIAL); + $object = $this->backend->getCalendarObject($calendarId, $eventUri); + $this->assertEquals(CalDavBackend::CLASSIFICATION_CONFIDENTIAL, $object['classification']); + + // run migration + $c = new Classification($this->backend, $this->userManager); + + /** @var IUser | \PHPUnit_Framework_MockObject_MockObject $user */ + $user = $this->getMockBuilder('OCP\IUser') + ->disableOriginalConstructor() + ->getMock(); + $user->expects($this->once())->method('getUID')->willReturn('caldav-unit-test'); + + $c->runForUser($user); + + // assert classification after migration + $object = $this->backend->getCalendarObject($calendarId, $eventUri); + $this->assertEquals(CalDavBackend::CLASSIFICATION_PUBLIC, $object['classification']); + } +} diff --git a/apps/encryption/l10n/pl.js b/apps/encryption/l10n/pl.js index 164a4a36d57..17f73e4fdb7 100644 --- a/apps/encryption/l10n/pl.js +++ b/apps/encryption/l10n/pl.js @@ -27,6 +27,8 @@ OC.L10N.register( "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Nie można odszyfrować tego pliku, prawdopodobnie jest to plik udostępniony. Poproś właściciela pliku o ponowne udostępnianie pliku Tobie.", "The share will expire on %s." : "Ten zasób wygaśnie %s", "Cheers!" : "Dzięki!", + "Enable recovery key" : "Włącz klucz odzyskiwania", + "Disable recovery key" : "Wyłącz klucz odzyskiwania", "Recovery key password" : "Hasło klucza odzyskiwania", "Repeat recovery key password" : "Powtórz hasło klucza odzyskiwania", "Change recovery key password:" : "Zmień hasło klucza odzyskiwania", diff --git a/apps/encryption/l10n/pl.json b/apps/encryption/l10n/pl.json index 2bd108ba4c6..f1ef3faf44d 100644 --- a/apps/encryption/l10n/pl.json +++ b/apps/encryption/l10n/pl.json @@ -25,6 +25,8 @@ "Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you." : "Nie można odszyfrować tego pliku, prawdopodobnie jest to plik udostępniony. Poproś właściciela pliku o ponowne udostępnianie pliku Tobie.", "The share will expire on %s." : "Ten zasób wygaśnie %s", "Cheers!" : "Dzięki!", + "Enable recovery key" : "Włącz klucz odzyskiwania", + "Disable recovery key" : "Wyłącz klucz odzyskiwania", "Recovery key password" : "Hasło klucza odzyskiwania", "Repeat recovery key password" : "Powtórz hasło klucza odzyskiwania", "Change recovery key password:" : "Zmień hasło klucza odzyskiwania", diff --git a/apps/federatedfilesharing/l10n/hu_HU.js b/apps/federatedfilesharing/l10n/hu_HU.js index 0f0ffdd1295..0a4f26cb20d 100644 --- a/apps/federatedfilesharing/l10n/hu_HU.js +++ b/apps/federatedfilesharing/l10n/hu_HU.js @@ -1,10 +1,14 @@ OC.L10N.register( "federatedfilesharing", { + "Federated sharing" : "Egyesített megosztás", "Invalid Federated Cloud ID" : "Érvénytelen Egyesített Felhő Azonosító", "Sharing %s failed, because this item is already shared with %s" : "%s megosztása nem sikerült, mert ez már meg van osztva vele: %s", "Not allowed to create a federated share with the same user" : "Azonos felhasználóval nem lehet létrehozni egyesített megosztást", + "File is already shared with %s" : "Fájl már megosztva vele: %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s megosztása sikertelen, mert %s nem található; talán a szerver jelenleg nem elérhető.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Kapott egy távoli megosztást: \"/%3$s\", innen: %1$s (%2$s nevében)", + "You received \"/%3$s\" as a remote share from %1$s" : "Kapott egy távoli megosztást: \"/%3$s\", innen: %1$s", "Accept" : "Elfogadás", "Decline" : "Elutasítás", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Ossza meg velem az #ownCloud Egyesített Felhő Azonosító segítségével, lásd %s", diff --git a/apps/federatedfilesharing/l10n/hu_HU.json b/apps/federatedfilesharing/l10n/hu_HU.json index 24e25b6aa4c..77a12ece1a8 100644 --- a/apps/federatedfilesharing/l10n/hu_HU.json +++ b/apps/federatedfilesharing/l10n/hu_HU.json @@ -1,8 +1,12 @@ { "translations": { + "Federated sharing" : "Egyesített megosztás", "Invalid Federated Cloud ID" : "Érvénytelen Egyesített Felhő Azonosító", "Sharing %s failed, because this item is already shared with %s" : "%s megosztása nem sikerült, mert ez már meg van osztva vele: %s", "Not allowed to create a federated share with the same user" : "Azonos felhasználóval nem lehet létrehozni egyesített megosztást", + "File is already shared with %s" : "Fájl már megosztva vele: %s", "Sharing %s failed, could not find %s, maybe the server is currently unreachable." : "%s megosztása sikertelen, mert %s nem található; talán a szerver jelenleg nem elérhető.", + "You received \"/%3$s\" as a remote share from %1$s (on behalf of %2$s)" : "Kapott egy távoli megosztást: \"/%3$s\", innen: %1$s (%2$s nevében)", + "You received \"/%3$s\" as a remote share from %1$s" : "Kapott egy távoli megosztást: \"/%3$s\", innen: %1$s", "Accept" : "Elfogadás", "Decline" : "Elutasítás", "Share with me through my #ownCloud Federated Cloud ID, see %s" : "Ossza meg velem az #ownCloud Egyesített Felhő Azonosító segítségével, lásd %s", diff --git a/apps/federation/l10n/pt_PT.js b/apps/federation/l10n/pt_PT.js index 38ec142b689..c227ab490b7 100644 --- a/apps/federation/l10n/pt_PT.js +++ b/apps/federation/l10n/pt_PT.js @@ -6,7 +6,7 @@ OC.L10N.register( "No ownCloud server found" : "Nenhum servidor ownCloud encontrado", "Could not add server" : "Não foi possível adicionar servidor", "Federation" : "Federação", - "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federação ownCloud permite-lhe conectar-se com outros ownClouds de confiança para partilhar directórios. Por exemplo, isto será utilizado para auto-completar utilizadores externos para partilhas federadas.", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "A Federação ownCloud permite-lhe conectar-se com outras ownClouds de confiança para partilhar directorias. Por exemplo, isto será utilizado para auto-completar utilizadores externos para partilhas federadas.", "Add server automatically once a federated share was created successfully" : "Adicionar o servidor automaticamente assim que uma partilha federada tenha sido criada com sucesso", "Trusted ownCloud Servers" : "Servidores ownCloud de confiança", "+ Add ownCloud server" : "+ Adicionar servidor ownCloud", diff --git a/apps/federation/l10n/pt_PT.json b/apps/federation/l10n/pt_PT.json index 796a2127170..2316af9c253 100644 --- a/apps/federation/l10n/pt_PT.json +++ b/apps/federation/l10n/pt_PT.json @@ -4,7 +4,7 @@ "No ownCloud server found" : "Nenhum servidor ownCloud encontrado", "Could not add server" : "Não foi possível adicionar servidor", "Federation" : "Federação", - "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federação ownCloud permite-lhe conectar-se com outros ownClouds de confiança para partilhar directórios. Por exemplo, isto será utilizado para auto-completar utilizadores externos para partilhas federadas.", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "A Federação ownCloud permite-lhe conectar-se com outras ownClouds de confiança para partilhar directorias. Por exemplo, isto será utilizado para auto-completar utilizadores externos para partilhas federadas.", "Add server automatically once a federated share was created successfully" : "Adicionar o servidor automaticamente assim que uma partilha federada tenha sido criada com sucesso", "Trusted ownCloud Servers" : "Servidores ownCloud de confiança", "+ Add ownCloud server" : "+ Adicionar servidor ownCloud", diff --git a/apps/federation/l10n/ro.js b/apps/federation/l10n/ro.js index e3035955143..19f37f329a1 100644 --- a/apps/federation/l10n/ro.js +++ b/apps/federation/l10n/ro.js @@ -4,6 +4,12 @@ OC.L10N.register( "Server added to the list of trusted ownClouds" : "Server adăugat la lista serverelor ownCloud de încredere", "Server is already in the list of trusted servers." : "Serverul este deja pe lista celor de încredere.", "No ownCloud server found" : "Nu s-a găsit niciun server ownCloud", - "Could not add server" : "Nu s-a putut adăuga serverul" + "Could not add server" : "Nu s-a putut adăuga serverul", + "Federation" : "Federare", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federarea ownCloud îți permite să te conectezi la alte servere ownCloud de încredere pentru a partaja baza de utilizatori. De exemplu, va permite completarea automată a numelor utilizatorilor externi pentru partajarea federată.", + "Add server automatically once a federated share was created successfully" : "Adaugă serverul automat odată ce elementul partajat federat a fost creat cu succes", + "Trusted ownCloud Servers" : "Servere ownCloud de încredere", + "+ Add ownCloud server" : "+ Adaugă server ownCloud", + "ownCloud Server" : "Server ownCloud" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/apps/federation/l10n/ro.json b/apps/federation/l10n/ro.json index 75c514fd8c8..0acb4ebd962 100644 --- a/apps/federation/l10n/ro.json +++ b/apps/federation/l10n/ro.json @@ -2,6 +2,12 @@ "Server added to the list of trusted ownClouds" : "Server adăugat la lista serverelor ownCloud de încredere", "Server is already in the list of trusted servers." : "Serverul este deja pe lista celor de încredere.", "No ownCloud server found" : "Nu s-a găsit niciun server ownCloud", - "Could not add server" : "Nu s-a putut adăuga serverul" + "Could not add server" : "Nu s-a putut adăuga serverul", + "Federation" : "Federare", + "ownCloud Federation allows you to connect with other trusted ownClouds to exchange the user directory. For example this will be used to auto-complete external users for federated sharing." : "Federarea ownCloud îți permite să te conectezi la alte servere ownCloud de încredere pentru a partaja baza de utilizatori. De exemplu, va permite completarea automată a numelor utilizatorilor externi pentru partajarea federată.", + "Add server automatically once a federated share was created successfully" : "Adaugă serverul automat odată ce elementul partajat federat a fost creat cu succes", + "Trusted ownCloud Servers" : "Servere ownCloud de încredere", + "+ Add ownCloud server" : "+ Adaugă server ownCloud", + "ownCloud Server" : "Server ownCloud" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/apps/federation/lib/DAV/FedAuth.php b/apps/federation/lib/DAV/FedAuth.php index bb1041adcdf..21c0d61487c 100644 --- a/apps/federation/lib/DAV/FedAuth.php +++ b/apps/federation/lib/DAV/FedAuth.php @@ -36,6 +36,10 @@ class FedAuth extends AbstractBasic { public function __construct(DbHandler $db) { $this->db = $db; $this->principalPrefix = 'principals/system/'; + + // setup realm + $defaults = new \OC_Defaults(); + $this->realm = $defaults->getName(); } /** diff --git a/apps/files/l10n/ar.js b/apps/files/l10n/ar.js index a9093c45a96..ae180fca235 100644 --- a/apps/files/l10n/ar.js +++ b/apps/files/l10n/ar.js @@ -41,6 +41,12 @@ OC.L10N.register( "Pending" : "قيد الانتظار", "Unable to determine date" : "تعذر تحديد التاريخ", "This operation is forbidden" : "هذة العملية ممنوعة ", + "Could not rename \"{fileName}\"" : "إعادة تسمية الملف \"{fileName}\" لم تنجح", + "Could not create file \"{file}\"" : "لا يمكن إنشاء الملف\"{file}\"", + "Could not create file \"{file}\" because it already exists" : "لا يمكن إنشاء الملف \"{file}\" فهو موجود بالفعل", + "Could not create folder \"{dir}\"" : "لا يمكن إنشاء المجلد \"{dir}\"", + "Could not create folder \"{dir}\" because it already exists" : "لا يمكن إنشاء المجلد \"{dir}\" فهو موجود بالفعل", + "Error deleting file \"{fileName}\"." : "خطأ أثناء حذف الملف \"{fileName}\".", "No entries in this folder match '{filter}'" : "لا يوجد مدخلات في هذا المجلد تتوافق مع '{filter}'", "Name" : "اسم", "Size" : "حجم", diff --git a/apps/files/l10n/ar.json b/apps/files/l10n/ar.json index fe07f30c033..257aa4f1bb4 100644 --- a/apps/files/l10n/ar.json +++ b/apps/files/l10n/ar.json @@ -39,6 +39,12 @@ "Pending" : "قيد الانتظار", "Unable to determine date" : "تعذر تحديد التاريخ", "This operation is forbidden" : "هذة العملية ممنوعة ", + "Could not rename \"{fileName}\"" : "إعادة تسمية الملف \"{fileName}\" لم تنجح", + "Could not create file \"{file}\"" : "لا يمكن إنشاء الملف\"{file}\"", + "Could not create file \"{file}\" because it already exists" : "لا يمكن إنشاء الملف \"{file}\" فهو موجود بالفعل", + "Could not create folder \"{dir}\"" : "لا يمكن إنشاء المجلد \"{dir}\"", + "Could not create folder \"{dir}\" because it already exists" : "لا يمكن إنشاء المجلد \"{dir}\" فهو موجود بالفعل", + "Error deleting file \"{fileName}\"." : "خطأ أثناء حذف الملف \"{fileName}\".", "No entries in this folder match '{filter}'" : "لا يوجد مدخلات في هذا المجلد تتوافق مع '{filter}'", "Name" : "اسم", "Size" : "حجم", diff --git a/apps/files/l10n/de.js b/apps/files/l10n/de.js index 068cbe85376..0866279a435 100644 --- a/apps/files/l10n/de.js +++ b/apps/files/l10n/de.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Ungültiges Verzeichnis.", "Files" : "Dateien", "All files" : "Alle Dateien", + "File could not be found" : "Datei konnte nicht gefunden werden", "Home" : "Home", "Close" : "Schließen", "Favorites" : "Favoriten", diff --git a/apps/files/l10n/de.json b/apps/files/l10n/de.json index 2169d228295..0f2939217d9 100644 --- a/apps/files/l10n/de.json +++ b/apps/files/l10n/de.json @@ -19,6 +19,7 @@ "Invalid directory." : "Ungültiges Verzeichnis.", "Files" : "Dateien", "All files" : "Alle Dateien", + "File could not be found" : "Datei konnte nicht gefunden werden", "Home" : "Home", "Close" : "Schließen", "Favorites" : "Favoriten", diff --git a/apps/files/l10n/de_DE.js b/apps/files/l10n/de_DE.js index 9a349357a99..6a2f0ab1f59 100644 --- a/apps/files/l10n/de_DE.js +++ b/apps/files/l10n/de_DE.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Ungültiges Verzeichnis.", "Files" : "Dateien", "All files" : "Alle Dateien", + "File could not be found" : "Datei konnte nicht gefunden werden", "Home" : "Zuhause", "Close" : "Schließen", "Favorites" : "Favoriten", diff --git a/apps/files/l10n/de_DE.json b/apps/files/l10n/de_DE.json index 9df557e8fa4..047299f9510 100644 --- a/apps/files/l10n/de_DE.json +++ b/apps/files/l10n/de_DE.json @@ -19,6 +19,7 @@ "Invalid directory." : "Ungültiges Verzeichnis.", "Files" : "Dateien", "All files" : "Alle Dateien", + "File could not be found" : "Datei konnte nicht gefunden werden", "Home" : "Zuhause", "Close" : "Schließen", "Favorites" : "Favoriten", diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js index ec8b821c3e7..82ed2364dd6 100644 --- a/apps/files/l10n/en_GB.js +++ b/apps/files/l10n/en_GB.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Invalid directory.", "Files" : "Files", "All files" : "All files", + "File could not be found" : "File could not be found", "Home" : "Home", "Close" : "Close", "Favorites" : "Favourites", diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json index 6dae8ba41b7..98b3d2000cb 100644 --- a/apps/files/l10n/en_GB.json +++ b/apps/files/l10n/en_GB.json @@ -19,6 +19,7 @@ "Invalid directory." : "Invalid directory.", "Files" : "Files", "All files" : "All files", + "File could not be found" : "File could not be found", "Home" : "Home", "Close" : "Close", "Favorites" : "Favourites", diff --git a/apps/files/l10n/fi_FI.js b/apps/files/l10n/fi_FI.js index 325955a5492..8bf1c47612a 100644 --- a/apps/files/l10n/fi_FI.js +++ b/apps/files/l10n/fi_FI.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Virheellinen kansio.", "Files" : "Tiedostot", "All files" : "Kaikki tiedostot", + "File could not be found" : "TIedostoa ei löytynyt", "Home" : "Koti", "Close" : "Sulje", "Favorites" : "Suosikit", diff --git a/apps/files/l10n/fi_FI.json b/apps/files/l10n/fi_FI.json index 966ef7074e4..dc8d168ffb5 100644 --- a/apps/files/l10n/fi_FI.json +++ b/apps/files/l10n/fi_FI.json @@ -19,6 +19,7 @@ "Invalid directory." : "Virheellinen kansio.", "Files" : "Tiedostot", "All files" : "Kaikki tiedostot", + "File could not be found" : "TIedostoa ei löytynyt", "Home" : "Koti", "Close" : "Sulje", "Favorites" : "Suosikit", diff --git a/apps/files/l10n/it.js b/apps/files/l10n/it.js index 7d85f952ed4..b560e6623ca 100644 --- a/apps/files/l10n/it.js +++ b/apps/files/l10n/it.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Cartella non valida.", "Files" : "File", "All files" : "Tutti i file", + "File could not be found" : "Il file non può essere trovato", "Home" : "Home", "Close" : "Chiudi", "Favorites" : "Preferiti", diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json index ec7003f7382..253fc5198aa 100644 --- a/apps/files/l10n/it.json +++ b/apps/files/l10n/it.json @@ -19,6 +19,7 @@ "Invalid directory." : "Cartella non valida.", "Files" : "File", "All files" : "Tutti i file", + "File could not be found" : "Il file non può essere trovato", "Home" : "Home", "Close" : "Chiudi", "Favorites" : "Preferiti", diff --git a/apps/files/l10n/pl.js b/apps/files/l10n/pl.js index cb243f6bf4d..a366c6a967c 100644 --- a/apps/files/l10n/pl.js +++ b/apps/files/l10n/pl.js @@ -32,6 +32,8 @@ OC.L10N.register( "Could not get result from server." : "Nie można uzyskać wyniku z serwera.", "Uploading..." : "Wgrywanie....", "..." : "...", + "{seconds} second{plural_s} left" : "Pozostało sekund: {seconds}", + "{seconds}s" : "{seconds} s", "File upload is in progress. Leaving the page now will cancel the upload." : "Wysyłanie pliku jest w toku. Jeśli opuścisz tę stronę, wysyłanie zostanie przerwane.", "Actions" : "Akcje", "Download" : "Pobierz", diff --git a/apps/files/l10n/pl.json b/apps/files/l10n/pl.json index 60323d0e757..05b65b2f84a 100644 --- a/apps/files/l10n/pl.json +++ b/apps/files/l10n/pl.json @@ -30,6 +30,8 @@ "Could not get result from server." : "Nie można uzyskać wyniku z serwera.", "Uploading..." : "Wgrywanie....", "..." : "...", + "{seconds} second{plural_s} left" : "Pozostało sekund: {seconds}", + "{seconds}s" : "{seconds} s", "File upload is in progress. Leaving the page now will cancel the upload." : "Wysyłanie pliku jest w toku. Jeśli opuścisz tę stronę, wysyłanie zostanie przerwane.", "Actions" : "Akcje", "Download" : "Pobierz", diff --git a/apps/files/l10n/pt_BR.js b/apps/files/l10n/pt_BR.js index d8a7097161d..7bc2a94deb1 100644 --- a/apps/files/l10n/pt_BR.js +++ b/apps/files/l10n/pt_BR.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Diretório inválido.", "Files" : "Arquivos", "All files" : "Todos os arquivos", + "File could not be found" : "O arquivo não foi encontrado", "Home" : "Home", "Close" : "Fechar", "Favorites" : "Favoritos", diff --git a/apps/files/l10n/pt_BR.json b/apps/files/l10n/pt_BR.json index f5fa97a94af..f16c8c374a6 100644 --- a/apps/files/l10n/pt_BR.json +++ b/apps/files/l10n/pt_BR.json @@ -19,6 +19,7 @@ "Invalid directory." : "Diretório inválido.", "Files" : "Arquivos", "All files" : "Todos os arquivos", + "File could not be found" : "O arquivo não foi encontrado", "Home" : "Home", "Close" : "Fechar", "Favorites" : "Favoritos", diff --git a/apps/files/l10n/sq.js b/apps/files/l10n/sq.js index c1485c154d7..b104afdd723 100644 --- a/apps/files/l10n/sq.js +++ b/apps/files/l10n/sq.js @@ -21,6 +21,7 @@ OC.L10N.register( "Invalid directory." : "Drejtori e pavlefshme.", "Files" : "Kartela", "All files" : "Krejt kartelat", + "File could not be found" : "Kartela s’u gjet dot", "Home" : "Kreu", "Close" : "Mbylle", "Favorites" : "Të parapëlqyera", diff --git a/apps/files/l10n/sq.json b/apps/files/l10n/sq.json index 9b40e9f7c9d..80e5f104fa6 100644 --- a/apps/files/l10n/sq.json +++ b/apps/files/l10n/sq.json @@ -19,6 +19,7 @@ "Invalid directory." : "Drejtori e pavlefshme.", "Files" : "Kartela", "All files" : "Krejt kartelat", + "File could not be found" : "Kartela s’u gjet dot", "Home" : "Kreu", "Close" : "Mbylle", "Favorites" : "Të parapëlqyera", diff --git a/apps/files_external/l10n/pl.js b/apps/files_external/l10n/pl.js index 8c3e394627e..00ae59b27c6 100644 --- a/apps/files_external/l10n/pl.js +++ b/apps/files_external/l10n/pl.js @@ -16,6 +16,7 @@ OC.L10N.register( "Saved" : "Zapisano", "Username" : "Nazwa użytkownika", "Password" : "Hasło", + "Credentials required" : "Wymagane poświadczenia", "Save" : "Zapisz", "Storage with id \"%i\" not found" : "Id magazynu nie został znaleziony", "Invalid mount point" : "Nieprawidłowy punkt montowania", diff --git a/apps/files_external/l10n/pl.json b/apps/files_external/l10n/pl.json index 8e00fc31863..235de7e9d10 100644 --- a/apps/files_external/l10n/pl.json +++ b/apps/files_external/l10n/pl.json @@ -14,6 +14,7 @@ "Saved" : "Zapisano", "Username" : "Nazwa użytkownika", "Password" : "Hasło", + "Credentials required" : "Wymagane poświadczenia", "Save" : "Zapisz", "Storage with id \"%i\" not found" : "Id magazynu nie został znaleziony", "Invalid mount point" : "Nieprawidłowy punkt montowania", diff --git a/apps/files_sharing/l10n/pl.js b/apps/files_sharing/l10n/pl.js index ebdfe2aa738..e1bec669533 100644 --- a/apps/files_sharing/l10n/pl.js +++ b/apps/files_sharing/l10n/pl.js @@ -25,6 +25,9 @@ OC.L10N.register( "Invalid ownCloud url" : "Błędny adres URL", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", + "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", + "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", + "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", diff --git a/apps/files_sharing/l10n/pl.json b/apps/files_sharing/l10n/pl.json index f5de5dd368c..6190871b16f 100644 --- a/apps/files_sharing/l10n/pl.json +++ b/apps/files_sharing/l10n/pl.json @@ -23,6 +23,9 @@ "Invalid ownCloud url" : "Błędny adres URL", "Shared by" : "Udostępniane przez", "Sharing" : "Udostępnianie", + "Public link sharing is disabled by the administrator" : "Udostępnianie linków publicznych zostało zablokowane przez twojego administratora", + "Public upload disabled by the administrator" : "Publiczne wczytywanie zostało zablokowane przez twojego administratora", + "Public upload is only possible for publicly shared folders" : "Publiczne wczytywanie jest możliwe wyłącznie do katalogów publicznych", "A file or folder has been <strong>shared</strong>" : "Plik lub folder stał się <strong>współdzielony</strong>", "You shared %1$s with %2$s" : "Współdzielisz %1$s z %2$s", "You shared %1$s with group %2$s" : "Współdzielisz %1$s z grupą %2$s", diff --git a/apps/files_sharing/l10n/ro.js b/apps/files_sharing/l10n/ro.js index 2481f77bcc6..5cddb6e8cdf 100644 --- a/apps/files_sharing/l10n/ro.js +++ b/apps/files_sharing/l10n/ro.js @@ -12,12 +12,28 @@ OC.L10N.register( "Shared with others" : "Partajat cu alții", "Shared by link" : "Partajat prin link", "Nothing shared with you yet" : "Nimic nu e partajat cu tine încă", + "Files and folders others share with you will show up here" : "Fișierele și directoarele partajate cu tine vor apărea aici", "Nothing shared yet" : "Nimic partajat încă", + "Files and folders you share will show up here" : "Fișierele și directoarele pe care le partajezi vor apărea aici", + "No shared links" : "Nicio legătură partajată", + "Files and folders you share by link will show up here" : "Fișierele și directoarele pe care le partajezi prin legături vor apărea aici", + "Remote share" : "Element partajat la distanță", + "Remote share password" : "Parolă element partajat la distanță", "Cancel" : "Anulare", + "Add remote share" : "Adaugă element partajat la distanță", + "You can upload into this folder" : "Poți încărca în acest director", "No ownCloud installation (7 or higher) found at {remote}" : "Nu s-a găsit nicio instanță ownCloud (versiunea 7 sau mai mare) la {remote}", "Invalid ownCloud url" : "URL ownCloud invalid", "Shared by" : "impartite in ", "Sharing" : "Partajare", + "Share API is disabled" : "API-ul de partajare este dezactivat", + "Wrong share ID, share doesn't exist" : "ID greșit al elementului partajat, acesta nu există", + "Could not delete share" : "Nu s-a putut șterge elementul partajat", + "Please specify a file or folder path" : "Specifică un fișier sau o cale către un director", + "Wrong path, file/folder doesn't exist" : "Cale greșită, fișierul/directorul nu există", + "Please specify a valid user" : "Specifică un utilizator valid", + "Please specify a valid group" : "Specifică un grup valid", + "Invalid date, date format must be YYYY-MM-DD" : "Dată invalidă, formatul trebuie să fie AAAA-LL-ZZ", "Not a directory" : "Nu este un director", "Could not lock path" : "Calea nu a putut fi blocată", "Cannot increase permissions" : "Nu se pot extinde permisiunile", @@ -26,6 +42,9 @@ OC.L10N.register( "You shared %1$s with group %2$s" : "Ai partajat %1$s cu grupul %2$s", "You shared %1$s via link" : "Ai partajat %1$s prin legătură", "%2$s shared %1$s with you" : "%2$s a partajat %1$s cu tine", + "Shared with %2$s" : "Partajat cu %2$s", + "Shared with %3$s by %2$s" : "Partajat de %2$s cu %3$s", + "Shared with group %2$s" : "Partajat cu grupul %2$s", "Shares" : "Partajări", "This share is password-protected" : "Această partajare este protejată cu parolă", "The password is wrong. Try again." : "Parola este incorectă. Încercaţi din nou.", @@ -38,6 +57,7 @@ OC.L10N.register( "sharing is disabled" : "Partajare este oprită", "Add to your ownCloud" : "Adaugă propriul tău ownCloud", "Download" : "Descarcă", - "Download %s" : "Descarcă %s" + "Download %s" : "Descarcă %s", + "Direct link" : "Legătură directă" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/apps/files_sharing/l10n/ro.json b/apps/files_sharing/l10n/ro.json index e3f9450bcb5..6d0d87037db 100644 --- a/apps/files_sharing/l10n/ro.json +++ b/apps/files_sharing/l10n/ro.json @@ -10,12 +10,28 @@ "Shared with others" : "Partajat cu alții", "Shared by link" : "Partajat prin link", "Nothing shared with you yet" : "Nimic nu e partajat cu tine încă", + "Files and folders others share with you will show up here" : "Fișierele și directoarele partajate cu tine vor apărea aici", "Nothing shared yet" : "Nimic partajat încă", + "Files and folders you share will show up here" : "Fișierele și directoarele pe care le partajezi vor apărea aici", + "No shared links" : "Nicio legătură partajată", + "Files and folders you share by link will show up here" : "Fișierele și directoarele pe care le partajezi prin legături vor apărea aici", + "Remote share" : "Element partajat la distanță", + "Remote share password" : "Parolă element partajat la distanță", "Cancel" : "Anulare", + "Add remote share" : "Adaugă element partajat la distanță", + "You can upload into this folder" : "Poți încărca în acest director", "No ownCloud installation (7 or higher) found at {remote}" : "Nu s-a găsit nicio instanță ownCloud (versiunea 7 sau mai mare) la {remote}", "Invalid ownCloud url" : "URL ownCloud invalid", "Shared by" : "impartite in ", "Sharing" : "Partajare", + "Share API is disabled" : "API-ul de partajare este dezactivat", + "Wrong share ID, share doesn't exist" : "ID greșit al elementului partajat, acesta nu există", + "Could not delete share" : "Nu s-a putut șterge elementul partajat", + "Please specify a file or folder path" : "Specifică un fișier sau o cale către un director", + "Wrong path, file/folder doesn't exist" : "Cale greșită, fișierul/directorul nu există", + "Please specify a valid user" : "Specifică un utilizator valid", + "Please specify a valid group" : "Specifică un grup valid", + "Invalid date, date format must be YYYY-MM-DD" : "Dată invalidă, formatul trebuie să fie AAAA-LL-ZZ", "Not a directory" : "Nu este un director", "Could not lock path" : "Calea nu a putut fi blocată", "Cannot increase permissions" : "Nu se pot extinde permisiunile", @@ -24,6 +40,9 @@ "You shared %1$s with group %2$s" : "Ai partajat %1$s cu grupul %2$s", "You shared %1$s via link" : "Ai partajat %1$s prin legătură", "%2$s shared %1$s with you" : "%2$s a partajat %1$s cu tine", + "Shared with %2$s" : "Partajat cu %2$s", + "Shared with %3$s by %2$s" : "Partajat de %2$s cu %3$s", + "Shared with group %2$s" : "Partajat cu grupul %2$s", "Shares" : "Partajări", "This share is password-protected" : "Această partajare este protejată cu parolă", "The password is wrong. Try again." : "Parola este incorectă. Încercaţi din nou.", @@ -36,6 +55,7 @@ "sharing is disabled" : "Partajare este oprită", "Add to your ownCloud" : "Adaugă propriul tău ownCloud", "Download" : "Descarcă", - "Download %s" : "Descarcă %s" + "Download %s" : "Descarcă %s", + "Direct link" : "Legătură directă" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php index b10c51ce2c9..3d6a715be99 100644 --- a/apps/files_sharing/lib/API/Share20OCS.php +++ b/apps/files_sharing/lib/API/Share20OCS.php @@ -100,15 +100,8 @@ class Share20OCS { */ protected function formatShare(\OCP\Share\IShare $share) { $sharedBy = $this->userManager->get($share->getSharedBy()); - // for federated shares the owner can be a remote user, in this - // case we use the initiator - if ($this->userManager->userExists($share->getShareOwner())) { - $shareOwner = $this->userManager->get($share->getShareOwner()); - $localUser = $share->getShareOwner(); - } else { - $shareOwner = $this->userManager->get($share->getSharedBy()); - $localUser = $share->getSharedBy(); - } + $shareOwner = $this->userManager->get($share->getShareOwner()); + $result = [ 'id' => $share->getId(), 'share_type' => $share->getShareType(), @@ -123,8 +116,16 @@ class Share20OCS { 'displayname_file_owner' => $shareOwner !== null ? $shareOwner->getDisplayName() : $share->getShareOwner(), ]; - $node = $share->getNode(); - $result['path'] = $this->rootFolder->getUserFolder($localUser)->getRelativePath($node->getPath()); + $userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID()); + $nodes = $userFolder->getById($share->getNodeId()); + + if (empty($nodes)) { + throw new NotFoundException(); + } + + $node = $nodes[0]; + + $result['path'] = $userFolder->getRelativePath($node->getPath()); if ($node instanceOf \OCP\Files\Folder) { $result['item_type'] = 'folder'; } else { @@ -536,7 +537,6 @@ class Share20OCS { $shares = array_merge($shares, $federatedShares); } - $formatted = []; foreach ($shares as $share) { try { diff --git a/apps/files_sharing/tests/API/Share20OCSTest.php b/apps/files_sharing/tests/API/Share20OCSTest.php index 02b16d7bf88..b760a0f47a0 100644 --- a/apps/files_sharing/tests/API/Share20OCSTest.php +++ b/apps/files_sharing/tests/API/Share20OCSTest.php @@ -433,8 +433,12 @@ class Share20OCSTest extends \Test\TestCase { ->method('getRelativePath') ->will($this->returnArgument(0)); + $userFolder->method('getById') + ->with($share->getNodeId()) + ->willReturn([$share->getNode()]); + $this->rootFolder->method('getUserFolder') - ->with($share->getShareOwner()) + ->with($this->currentUser->getUID()) ->willReturn($userFolder); $this->urlGenerator @@ -2006,8 +2010,19 @@ class Share20OCSTest extends \Test\TestCase { ->willReturn('myLink'); - $this->rootFolder->method('getUserFolder')->with($share->getShareOwner())->will($this->returnSelf()); - $this->rootFolder->method('getRelativePath')->will($this->returnArgument(0)); + $this->rootFolder->method('getUserFolder') + ->with($this->currentUser->getUID()) + ->will($this->returnSelf()); + + if (!$exception) { + $this->rootFolder->method('getById') + ->with($share->getNodeId()) + ->willReturn([$share->getNode()]); + + $this->rootFolder->method('getRelativePath') + ->with($share->getNode()->getPath()) + ->will($this->returnArgument(0)); + } try { $result = $this->invokePrivate($this->ocs, 'formatShare', [$share]); diff --git a/apps/files_sharing/tests/ApiTest.php b/apps/files_sharing/tests/ApiTest.php index f44c346236e..058b0c4758c 100644 --- a/apps/files_sharing/tests/ApiTest.php +++ b/apps/files_sharing/tests/ApiTest.php @@ -764,8 +764,7 @@ class ApiTest extends TestCase { // we should get exactly one result $this->assertCount(1, $data); - $expectedPath = $this->folder . $this->subfolder; - $this->assertEquals($expectedPath, $data[0]['path']); + $this->assertEquals($this->subfolder, $data[0]['path']); $this->shareManager->deleteShare($share2); $this->shareManager->deleteShare($share1); @@ -801,6 +800,9 @@ class ApiTest extends TestCase { ->setPermissions(1); $share3 = $this->shareManager->createShare($share3); + /* + * Test as recipient + */ $request = $this->createRequest(['path' => '/', 'subfiles' => 'true']); $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER3); $result = $ocs->getShares(); @@ -811,9 +813,37 @@ class ApiTest extends TestCase { // we should get exactly one result $this->assertCount(1, $data); + $this->assertEquals($this->subsubfolder, $data[0]['path']); - $expectedPath = $this->folder . $this->subfolder . $this->subsubfolder; - $this->assertEquals($expectedPath, $data[0]['path']); + /* + * Test for first owner/initiator + */ + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER1); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + // we should get exactly one result + $this->assertCount(1, $data); + $this->assertEquals($this->folder . $this->subfolder, $data[0]['path']); + + /* + * Test for second initiator + */ + $request = $this->createRequest([]); + $ocs = $this->createOCS($request, self::TEST_FILES_SHARING_API_USER2); + $result = $ocs->getShares(); + $this->assertTrue($result->succeeded()); + + // test should return one share within $this->folder + $data = $result->getData(); + + // we should get exactly one result + $this->assertCount(1, $data); + $this->assertEquals($this->subfolder . $this->subsubfolder, $data[0]['path']); $this->shareManager->deleteShare($share1); $this->shareManager->deleteShare($share2); @@ -922,8 +952,7 @@ class ApiTest extends TestCase { // we should get exactly one result $this->assertCount(1, $data); - $expectedPath = $this->folder.$this->subfolder.$this->filename; - $this->assertEquals($expectedPath, $data[0]['path']); + $this->assertEquals($this->filename, $data[0]['path']); $this->shareManager->deleteShare($share1); $this->shareManager->deleteShare($share2); diff --git a/apps/systemtags/l10n/hu_HU.js b/apps/systemtags/l10n/hu_HU.js index 13d1705ff1c..783b90ece8a 100644 --- a/apps/systemtags/l10n/hu_HU.js +++ b/apps/systemtags/l10n/hu_HU.js @@ -21,6 +21,7 @@ OC.L10N.register( "%1$s assigned system tag %3$s to %2$s" : "%1$s hozzárendelte ezt a rendszer címkét: %3$s neki: %2$s", "You unassigned system tag %3$s from %2$s" : "%3$s rendszer címke hozzárendelést elvette tőle: %2$s", "%1$s unassigned system tag %3$s from %2$s" : "%1$s elvette ezt a rendszer címkét %3$s tőle: %2$s", + "%s (restricted)" : "%s (korlátozott)", "%s (invisible)" : "%s (láthatatlan)", "No files in here" : "Itt nincsenek fájlok", "No entries found in this folder" : "Nincsenek bejegyzések ebben a könyvtárban", diff --git a/apps/systemtags/l10n/hu_HU.json b/apps/systemtags/l10n/hu_HU.json index 6408b3a5314..f89da5d3dfd 100644 --- a/apps/systemtags/l10n/hu_HU.json +++ b/apps/systemtags/l10n/hu_HU.json @@ -19,6 +19,7 @@ "%1$s assigned system tag %3$s to %2$s" : "%1$s hozzárendelte ezt a rendszer címkét: %3$s neki: %2$s", "You unassigned system tag %3$s from %2$s" : "%3$s rendszer címke hozzárendelést elvette tőle: %2$s", "%1$s unassigned system tag %3$s from %2$s" : "%1$s elvette ezt a rendszer címkét %3$s tőle: %2$s", + "%s (restricted)" : "%s (korlátozott)", "%s (invisible)" : "%s (láthatatlan)", "No files in here" : "Itt nincsenek fájlok", "No entries found in this folder" : "Nincsenek bejegyzések ebben a könyvtárban", diff --git a/apps/updatenotification/l10n/hu_HU.js b/apps/updatenotification/l10n/hu_HU.js index 1df38a6746f..cce4549f01e 100644 --- a/apps/updatenotification/l10n/hu_HU.js +++ b/apps/updatenotification/l10n/hu_HU.js @@ -1,8 +1,11 @@ OC.L10N.register( "updatenotification", { + "Update notifications" : "Frissítési értesítés", "{version} is available. Get more information on how to update." : "{version} rendelkezésre áll. További információ a frissítéshez.", "Updated channel" : "Frissített csatorna", + "ownCloud core" : "ownCloud mag", + "Update for %1$s to version %2$s is available." : "%1$s frissíthető %2$s verzióra.", "Updater" : "Frissítéskezelő", "A new version is available: %s" : "Új verzió érhető el: %s", "Open updater" : "Frissítő megnyitása", diff --git a/apps/updatenotification/l10n/hu_HU.json b/apps/updatenotification/l10n/hu_HU.json index eb953669ab1..952b499d52a 100644 --- a/apps/updatenotification/l10n/hu_HU.json +++ b/apps/updatenotification/l10n/hu_HU.json @@ -1,6 +1,9 @@ { "translations": { + "Update notifications" : "Frissítési értesítés", "{version} is available. Get more information on how to update." : "{version} rendelkezésre áll. További információ a frissítéshez.", "Updated channel" : "Frissített csatorna", + "ownCloud core" : "ownCloud mag", + "Update for %1$s to version %2$s is available." : "%1$s frissíthető %2$s verzióra.", "Updater" : "Frissítéskezelő", "A new version is available: %s" : "Új verzió érhető el: %s", "Open updater" : "Frissítő megnyitása", diff --git a/apps/user_ldap/l10n/pl.js b/apps/user_ldap/l10n/pl.js index de8f1f49ad3..a75b38fc12f 100644 --- a/apps/user_ldap/l10n/pl.js +++ b/apps/user_ldap/l10n/pl.js @@ -31,6 +31,7 @@ OC.L10N.register( "Confirm Deletion" : "Potwierdź usunięcie", "Mappings cleared successfully!" : "Mapowanie wyczyszczone!", "Error while clearing the mappings." : "Błąd podczas czyszczenia mapowania.", + "Mode switch" : "Przełącznik trybów", "Select attributes" : "Wybierz atrybuty", "_%s group found_::_%s groups found_" : ["%s znaleziona grupa","%s znalezionych grup","%s znalezionych grup"], "_%s user found_::_%s users found_" : ["%s znaleziony użytkownik","%s znalezionych użytkowników","%s znalezionych użytkowników"], diff --git a/apps/user_ldap/l10n/pl.json b/apps/user_ldap/l10n/pl.json index 5a853c3abed..472148fa3b0 100644 --- a/apps/user_ldap/l10n/pl.json +++ b/apps/user_ldap/l10n/pl.json @@ -29,6 +29,7 @@ "Confirm Deletion" : "Potwierdź usunięcie", "Mappings cleared successfully!" : "Mapowanie wyczyszczone!", "Error while clearing the mappings." : "Błąd podczas czyszczenia mapowania.", + "Mode switch" : "Przełącznik trybów", "Select attributes" : "Wybierz atrybuty", "_%s group found_::_%s groups found_" : ["%s znaleziona grupa","%s znalezionych grup","%s znalezionych grup"], "_%s user found_::_%s users found_" : ["%s znaleziony użytkownik","%s znalezionych użytkowników","%s znalezionych użytkowników"], diff --git a/apps/user_ldap/lib/Group_LDAP.php b/apps/user_ldap/lib/Group_LDAP.php index 7c12613f34d..14d86fb0619 100644 --- a/apps/user_ldap/lib/Group_LDAP.php +++ b/apps/user_ldap/lib/Group_LDAP.php @@ -535,7 +535,7 @@ class Group_LDAP extends BackendUtility implements \OCP\GroupInterface { } if(isset($this->cachedGroupsByMember[$uid])) { - $groups[] = $this->cachedGroupsByMember[$uid]; + $groups = array_merge($groups, $this->cachedGroupsByMember[$uid]); } else { $groupsByMember = array_values($this->getGroupsByMember($uid)); $groupsByMember = $this->access->ownCloudGroupNames($groupsByMember); diff --git a/apps/user_ldap/tests/Group_LDAPTest.php b/apps/user_ldap/tests/Group_LDAPTest.php index 556c4b0b394..35d525068a6 100644 --- a/apps/user_ldap/tests/Group_LDAPTest.php +++ b/apps/user_ldap/tests/Group_LDAPTest.php @@ -454,4 +454,57 @@ class Group_LDAPTest extends \Test\TestCase { $groupBackend->getUserGroups('userX'); } + public function testGetGroupsByMember() { + $access = $this->getAccessMock(); + + $access->connection->expects($this->any()) + ->method('__get') + ->will($this->returnCallback(function($name) { + if($name === 'useMemberOfToDetectMembership') { + return 0; + } else if($name === 'ldapDynamicGroupMemberURL') { + return ''; + } else if($name === 'ldapNestedGroups') { + return false; + } + return 1; + })); + + $dn = 'cn=userX,dc=foobar'; + + $access->connection->hasPrimaryGroups = false; + + $access->expects($this->exactly(2)) + ->method('username2dn') + ->will($this->returnValue($dn)); + + $access->expects($this->never()) + ->method('readAttribute') + ->with($dn, 'memberOf'); + + $group1 = [ + 'cn' => 'group1', + 'dn' => ['cn=group1,ou=groups,dc=domain,dc=com'], + ]; + $group2 = [ + 'cn' => 'group2', + 'dn' => ['cn=group2,ou=groups,dc=domain,dc=com'], + ]; + + $access->expects($this->once()) + ->method('ownCloudGroupNames') + ->with([$group1, $group2]) + ->will($this->returnValue(['group1', 'group2'])); + + $access->expects($this->once()) + ->method('fetchListOfGroups') + ->will($this->returnValue([$group1, $group2])); + + $groupBackend = new GroupLDAP($access); + $groups = $groupBackend->getUserGroups('userX'); + $this->assertEquals(['group1', 'group2'], $groups); + + $groupsAgain = $groupBackend->getUserGroups('userX'); + $this->assertEquals(['group1', 'group2'], $groupsAgain); + } } |