Пример #1
1
 /**
  * PropFind
  *
  * This method handler is invoked before any after properties for a
  * resource are fetched. This allows us to add in any CalDAV specific
  * properties.
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFind(DAV\PropFind $propFind, DAV\INode $node)
 {
     $ns = '{' . self::NS_CALDAV . '}';
     if ($node instanceof ICalendarObjectContainer) {
         $propFind->handle($ns . 'max-resource-size', $this->maxResourceSize);
         $propFind->handle($ns . 'supported-calendar-data', function () {
             return new Xml\Property\SupportedCalendarData();
         });
         $propFind->handle($ns . 'supported-collation-set', function () {
             return new Xml\Property\SupportedCollationSet();
         });
     }
     if ($node instanceof DAVACL\IPrincipal) {
         $principalUrl = $node->getPrincipalUrl();
         $propFind->handle('{' . self::NS_CALDAV . '}calendar-home-set', function () use($principalUrl) {
             $calendarHomePath = $this->getCalendarHomeForPrincipal($principalUrl) . '/';
             return new Href($calendarHomePath);
         });
         // The calendar-user-address-set property is basically mapped to
         // the {DAV:}alternate-URI-set property.
         $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-address-set', function () use($node) {
             $addresses = $node->getAlternateUriSet();
             $addresses[] = $this->server->getBaseUri() . $node->getPrincipalUrl() . '/';
             return new Href($addresses, false);
         });
         // For some reason somebody thought it was a good idea to add
         // another one of these properties. We're supporting it too.
         $propFind->handle('{' . self::NS_CALENDARSERVER . '}email-address-set', function () use($node) {
             $addresses = $node->getAlternateUriSet();
             $emails = [];
             foreach ($addresses as $address) {
                 if (substr($address, 0, 7) === 'mailto:') {
                     $emails[] = substr($address, 7);
                 }
             }
             return new Xml\Property\EmailAddressSet($emails);
         });
         // These two properties are shortcuts for ical to easily find
         // other principals this principal has access to.
         $propRead = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-read-for';
         $propWrite = '{' . self::NS_CALENDARSERVER . '}calendar-proxy-write-for';
         if ($propFind->getStatus($propRead) === 404 || $propFind->getStatus($propWrite) === 404) {
             $aclPlugin = $this->server->getPlugin('acl');
             $membership = $aclPlugin->getPrincipalMembership($propFind->getPath());
             $readList = [];
             $writeList = [];
             foreach ($membership as $group) {
                 $groupNode = $this->server->tree->getNodeForPath($group);
                 $listItem = Uri\split($group)[0] . '/';
                 // If the node is either ap proxy-read or proxy-write
                 // group, we grab the parent principal and add it to the
                 // list.
                 if ($groupNode instanceof Principal\IProxyRead) {
                     $readList[] = $listItem;
                 }
                 if ($groupNode instanceof Principal\IProxyWrite) {
                     $writeList[] = $listItem;
                 }
             }
             $propFind->set($propRead, new Href($readList));
             $propFind->set($propWrite, new Href($writeList));
         }
     }
     // instanceof IPrincipal
     if ($node instanceof ICalendarObject) {
         // The calendar-data property is not supposed to be a 'real'
         // property, but in large chunks of the spec it does act as such.
         // Therefore we simply expose it as a property.
         $propFind->handle('{' . self::NS_CALDAV . '}calendar-data', function () use($node) {
             $val = $node->get();
             if (is_resource($val)) {
                 $val = stream_get_contents($val);
             }
             // Taking out \r to not screw up the xml output
             return str_replace("\r", "", $val);
         });
     }
 }
Пример #2
0
 /**
  * This method is called after most properties have been found
  * it allows us to add in any Lock-related properties
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFind(DAV\PropFind $propFind, DAV\INode $node)
 {
     $propFind->handle('{DAV:}supportedlock', function () {
         return new DAV\Property\SupportedLock(!!$this->locksBackend);
     });
     $propFind->handle('{DAV:}lockdiscovery', function () use($propFind) {
         return new DAV\Property\LockDiscovery($this->getLocks($propFind->getPath()));
     });
 }
Пример #3
0
 /**
  * Adds tags and favorites properties to the response,
  * if requested.
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if (!$node instanceof File && !$node instanceof Directory) {
         return;
     }
     $propFind->handle(self::PROPERTY_NAME_COUNT, function () use($node) {
         return $this->commentsManager->getNumberOfCommentsForObject('files', strval($node->getId()));
     });
     $propFind->handle(self::PROPERTY_NAME_HREF, function () use($node) {
         return $this->getCommentsLink($node);
     });
     $propFind->handle(self::PROPERTY_NAME_UNREAD, function () use($node) {
         return $this->getUnreadCount($node);
     });
 }
 /**
  * Our PROPFIND handler
  *
  * Here we set a contenttype, if the node didn't already have one.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     $propFind->handle('{DAV:}getcontenttype', function () use($propFind) {
         list(, $fileName) = URLUtil::splitPath($propFind->getPath());
         return $this->getContentType($fileName);
     });
 }
Пример #5
0
 /**
  * Adds all CardDAV-specific properties
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     $ns = '{http://owncloud.org/ns}';
     if ($node instanceof AddressBook) {
         $propFind->handle($ns . 'groups', function () use($node) {
             return new Groups($node->getContactsGroups());
         });
     }
 }
Пример #6
0
 function propFind(PropFind $propFind, INode $node)
 {
     /* Overload current-user-principal */
     $propFind->handle('{DAV:}current-user-principal', function () {
         if ($url = parent::getCurrentUserPrincipal()) {
             return new Principal(Principal::HREF, $url . '/');
         } else {
             return new Principal(Principal::UNAUTHENTICATED);
         }
     });
     parent::propFind($propFind, $node);
 }
Пример #7
0
 /**
  * PropFind
  *
  * @param PropFind $propFind
  * @param BaseINode $node
  * @return void
  */
 function propFind(PropFind $propFind, BaseINode $node)
 {
     $caldavPlugin = $this->server->getPlugin('caldav');
     if ($node instanceof DAVACL\IPrincipal) {
         $principalUrl = $node->getPrincipalUrl();
         // notification-URL property
         $propFind->handle('{' . self::NS_CALENDARSERVER . '}notification-URL', function () use($principalUrl, $caldavPlugin) {
             $notificationPath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl) . '/notifications/';
             return new DAV\Xml\Property\Href($notificationPath);
         });
     }
     if ($node instanceof INode) {
         $propFind->handle('{' . self::NS_CALENDARSERVER . '}notificationtype', [$node, 'getNotificationType']);
     }
 }
Пример #8
0
 /**
  * Triggered before properties are looked up in specific nodes.
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @param array $requestedProperties
  * @param array $returnedProperties
  * @TODO really should be broken into multiple methods, or even a class.
  * @return bool
  */
 function propFind(DAV\PropFind $propFind, DAV\INode $node)
 {
     $path = $propFind->getPath();
     // Checking the read permission
     if (!$this->checkPrivileges($path, '{DAV:}read', self::R_PARENT, false)) {
         // User is not allowed to read properties
         // Returning false causes the property-fetching system to pretend
         // that the node does not exist, and will cause it to be hidden
         // from listings such as PROPFIND or the browser plugin.
         if ($this->hideNodesFromListings) {
             return false;
         }
         // Otherwise we simply mark every property as 403.
         foreach ($propFind->getRequestedProperties() as $requestedProperty) {
             $propFind->set($requestedProperty, null, 403);
         }
         return;
     }
     /* Adding principal properties */
     if ($node instanceof IPrincipal) {
         $propFind->handle('{DAV:}alternate-URI-set', function () use($node) {
             return new DAV\Property\HrefList($node->getAlternateUriSet());
         });
         $propFind->handle('{DAV:}principal-URL', function () use($node) {
             return new DAV\Property\Href($node->getPrincipalUrl() . '/');
         });
         $propFind->handle('{DAV:}group-member-set', function () use($node) {
             $members = $node->getGroupMemberSet();
             foreach ($members as $k => $member) {
                 $members[$k] = rtrim($member, '/') . '/';
             }
             return new DAV\Property\HrefList($members);
         });
         $propFind->handle('{DAV:}group-membership', function () use($node) {
             $members = $node->getGroupMembership();
             foreach ($members as $k => $member) {
                 $members[$k] = rtrim($member, '/') . '/';
             }
             return new DAV\Property\HrefList($members);
         });
         $propFind->handle('{DAV:}displayname', [$node, 'getDisplayName']);
     }
     $propFind->handle('{DAV:}principal-collection-set', function () {
         $val = $this->principalCollectionSet;
         // Ensuring all collections end with a slash
         foreach ($val as $k => $v) {
             $val[$k] = $v . '/';
         }
         return new DAV\Property\HrefList($val);
     });
     $propFind->handle('{DAV:}current-user-principal', function () {
         if ($url = $this->getCurrentUserPrincipal()) {
             return new Property\Principal(Property\Principal::HREF, $url . '/');
         } else {
             return new Property\Principal(Property\Principal::UNAUTHENTICATED);
         }
     });
     $propFind->handle('{DAV:}supported-privilege-set', function () use($node) {
         return new Property\SupportedPrivilegeSet($this->getSupportedPrivilegeSet($node));
     });
     $propFind->handle('{DAV:}current-user-privilege-set', function () use($node, $propFind, $path) {
         if (!$this->checkPrivileges($path, '{DAV:}read-current-user-privilege-set', self::R_PARENT, false)) {
             $propFind->set('{DAV:}current-user-privilege-set', null, 403);
         } else {
             $val = $this->getCurrentUserPrivilegeSet($node);
             if (!is_null($val)) {
                 return new Property\CurrentUserPrivilegeSet($val);
             }
         }
     });
     $propFind->handle('{DAV:}acl', function () use($node, $propFind, $path) {
         /* The ACL property contains all the permissions */
         if (!$this->checkPrivileges($path, '{DAV:}read-acl', self::R_PARENT, false)) {
             $propFind->set('{DAV:}acl', null, 403);
         } else {
             $acl = $this->getACL($node);
             if (!is_null($acl)) {
                 return new Property\Acl($this->getACL($node));
             }
         }
     });
     $propFind->handle('{DAV:}acl-restrictions', function () {
         return new Property\AclRestrictions();
     });
     /* Adding ACL properties */
     if ($node instanceof IACL) {
         $propFind->handle('{DAV:}owner', function () use($node) {
             return new DAV\Property\Href($node->getOwner() . '/');
         });
     }
 }
Пример #9
0
 /**
  * This method handler is invoked during fetching of properties.
  *
  * We use this event to add calendar-auto-schedule-specific properties.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     if (!$node instanceof DAVACL\IPrincipal) {
         return;
     }
     $caldavPlugin = $this->server->getPlugin('caldav');
     $principalUrl = $node->getPrincipalUrl();
     // schedule-outbox-URL property
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-outbox-URL', function () use($principalUrl, $caldavPlugin) {
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $outboxPath = $calendarHomePath . '/outbox/';
         return new Href($outboxPath);
     });
     // schedule-inbox-URL property
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-inbox-URL', function () use($principalUrl, $caldavPlugin) {
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $inboxPath = $calendarHomePath . '/inbox/';
         return new Href($inboxPath);
     });
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function () use($principalUrl, $caldavPlugin) {
         // We don't support customizing this property yet, so in the
         // meantime we just grab the first calendar in the home-set.
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $sccs = '{' . self::NS_CALDAV . '}supported-calendar-component-set';
         $result = $this->server->getPropertiesForPath($calendarHomePath, ['{DAV:}resourcetype', $sccs], 1);
         foreach ($result as $child) {
             if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar') || $child[200]['{DAV:}resourcetype']->is('{http://calendarserver.org/ns/}shared')) {
                 // Node is either not a calendar or a shared instance.
                 continue;
             }
             if (!isset($child[200][$sccs]) || in_array('VEVENT', $child[200][$sccs]->getValue())) {
                 // Either there is no supported-calendar-component-set
                 // (which is fine) or we found one that supports VEVENT.
                 return new Href($child['href']);
             }
         }
     });
     // The server currently reports every principal to be of type
     // 'INDIVIDUAL'
     $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function () {
         return 'INDIVIDUAL';
     });
 }
Пример #10
0
 /**
  * This method is triggered whenever properties are requested for a node.
  * We intercept this to see if we must return a {DAV:}sync-token.
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFind(DAV\PropFind $propFind, DAV\INode $node)
 {
     $propFind->handle('{DAV:}sync-token', function () use($node) {
         if (!$node instanceof ISyncCollection || !($token = $node->getSyncToken())) {
             return;
         }
         return self::SYNCTOKEN_PREFIX . $token;
     });
 }
Пример #11
0
 /**
  * Adds shares to propfind response
  *
  * @param PropFind $propFind propfind object
  * @param \Sabre\DAV\INode $sabreNode sabre node
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $sabreNode)
 {
     if (!$sabreNode instanceof \OCA\DAV\Connector\Sabre\Node) {
         return;
     }
     // need prefetch ?
     if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory && $propFind->getDepth() !== 0 && !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME))) {
         $folderNode = $this->userFolder->get($propFind->getPath());
         $children = $folderNode->getDirectoryListing();
         $this->cachedShareTypes[$folderNode->getId()] = $this->getShareTypes($folderNode);
         foreach ($children as $childNode) {
             $this->cachedShareTypes[$childNode->getId()] = $this->getShareTypes($childNode);
         }
     }
     $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use($sabreNode) {
         if (isset($this->cachedShareTypes[$sabreNode->getId()])) {
             $shareTypes = $this->cachedShareTypes[$sabreNode->getId()];
         } else {
             $node = $this->userFolder->get($sabreNode->getPath());
             $shareTypes = $this->getShareTypes($node);
         }
         return new ShareTypeList($shareTypes);
     });
 }
Пример #12
0
 /**
  * Adds all ownCloud-specific properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     $httpRequest = $this->server->httpRequest;
     if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
         $propFind->handle(self::FILEID_PROPERTYNAME, function () use($node) {
             return $node->getFileId();
         });
         $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function () use($node) {
             return $node->getInternalFileId();
         });
         $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use($node) {
             $perms = $node->getDavPermissions();
             if ($this->isPublic) {
                 // remove mount information
                 $perms = str_replace(['S', 'M'], '', $perms);
             }
             return $perms;
         });
         $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function () use($node, $httpRequest) {
             return $node->getSharePermissions($httpRequest->getRawServerValue('PHP_AUTH_USER'));
         });
         $propFind->handle(self::GETETAG_PROPERTYNAME, function () use($node) {
             return $node->getETag();
         });
         $propFind->handle(self::OWNER_ID_PROPERTYNAME, function () use($node) {
             $owner = $node->getOwner();
             return $owner->getUID();
         });
         $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function () use($node) {
             $owner = $node->getOwner();
             $displayName = $owner->getDisplayName();
             return $displayName;
         });
         $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () use($node) {
             if ($node->getPath() === '/') {
                 return $this->config->getSystemValue('data-fingerprint', '');
             }
         });
     }
     if ($node instanceof \OCA\DAV\Files\FilesHome) {
         $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () use($node) {
             return $this->config->getSystemValue('data-fingerprint', '');
         });
     }
     if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
         $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use($node) {
             /** @var $node \OCA\DAV\Connector\Sabre\File */
             try {
                 $directDownloadUrl = $node->getDirectDownload();
                 if (isset($directDownloadUrl['url'])) {
                     return $directDownloadUrl['url'];
                 }
             } catch (StorageNotAvailableException $e) {
                 return false;
             } catch (ForbiddenException $e) {
                 return false;
             }
             return false;
         });
         $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function () use($node) {
             $checksum = $node->getChecksum();
             if ($checksum === NULL || $checksum === '') {
                 return null;
             }
             return new ChecksumList($checksum);
         });
     }
     if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
         $propFind->handle(self::SIZE_PROPERTYNAME, function () use($node) {
             return $node->getSize();
         });
     }
 }
Пример #13
0
 /**
  * This method is called when properties are retrieved.
  *
  * This specific handler is called very late in the process, because we
  * want other systems to first have a chance to handle the properties.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFindLate(PropFind $propFind, INode $node)
 {
     $propFind->handle('{http://calendarserver.org/ns/}getctag', function () use($propFind) {
         // If we already have a sync-token from the current propFind
         // request, we can re-use that.
         $val = $propFind->get('{http://sabredav.org/ns}sync-token');
         if ($val) {
             return $val;
         }
         $val = $propFind->get('{DAV:}sync-token');
         if ($val && is_scalar($val)) {
             return $val;
         }
         if ($val && $val instanceof Property\IHref) {
             return substr($val->getHref(), strlen(Sync\Plugin::SYNCTOKEN_PREFIX));
         }
         // If we got here, the earlier two properties may simply not have
         // been part of the earlier request. We're going to fetch them.
         $result = $this->server->getProperties($propFind->getPath(), ['{http://sabredav.org/ns}sync-token', '{DAV:}sync-token']);
         if (isset($result['{http://sabredav.org/ns}sync-token'])) {
             return $result['{http://sabredav.org/ns}sync-token'];
         }
         if (isset($result['{DAV:}sync-token'])) {
             $val = $result['{DAV:}sync-token'];
             if (is_scalar($val)) {
                 return $val;
             } elseif ($val instanceof Property\IHref) {
                 return substr($val->getHref(), strlen(Sync\Plugin::SYNCTOKEN_PREFIX));
             }
         }
     });
 }
Пример #14
0
 /**
  * Return some dummy response for PROPFIND requests with regard to locking
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     $propFind->handle('{DAV:}supportedlock', function () {
         return new SupportedLock(true);
     });
     $propFind->handle('{DAV:}lockdiscovery', function () use($propFind) {
         return new LockDiscovery([]);
     });
 }
Пример #15
0
 /**
  * Adds all ownCloud-specific properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if ($node instanceof \OC\Connector\Sabre\Node) {
         $propFind->handle(self::FILEID_PROPERTYNAME, function () use($node) {
             return $node->getFileId();
         });
         $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use($node) {
             return $node->getDavPermissions();
         });
         $propFind->handle(self::GETETAG_PROPERTYNAME, function () use($node) {
             return $node->getEtag();
         });
     }
     if ($node instanceof \OC\Connector\Sabre\File) {
         $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use($node) {
             /** @var $node \OC\Connector\Sabre\File */
             $directDownloadUrl = $node->getDirectDownload();
             if (isset($directDownloadUrl['url'])) {
                 return $directDownloadUrl['url'];
             }
             return false;
         });
     }
     if ($node instanceof \OC\Connector\Sabre\Directory) {
         $propFind->handle(self::SIZE_PROPERTYNAME, function () use($node) {
             return $node->getSize();
         });
     }
 }
Пример #16
0
 /**
  * This method is triggered *after* all properties have been retrieved.
  * This allows us to inject the correct resourcetype for calendars that
  * have been shared.
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFindLate(DAV\PropFind $propFind, DAV\INode $node)
 {
     if ($node instanceof ISharedCalendar) {
         $shareAccess = $node->getShareAccess();
         if ($rt = $propFind->get('{DAV:}resourcetype')) {
             switch ($shareAccess) {
                 case \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER:
                     $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
                     break;
                 case \Sabre\DAV\Sharing\Plugin::ACCESS_READ:
                 case \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE:
                     $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared');
                     break;
             }
         }
         $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function () {
             return new Xml\Property\AllowedSharingModes(true, false);
         });
     }
 }
Пример #17
0
 /**
  * Retrieves system tag properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if (!$node instanceof SystemTagNode && !$node instanceof SystemTagMappingNode) {
         return;
     }
     $propFind->handle(self::ID_PROPERTYNAME, function () use($node) {
         return $node->getSystemTag()->getId();
     });
     $propFind->handle(self::DISPLAYNAME_PROPERTYNAME, function () use($node) {
         return $node->getSystemTag()->getName();
     });
     $propFind->handle(self::USERVISIBLE_PROPERTYNAME, function () use($node) {
         return $node->getSystemTag()->isUserVisible() ? 'true' : 'false';
     });
     $propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function () use($node) {
         // this is the tag's inherent property "is user assignable"
         return $node->getSystemTag()->isUserAssignable() ? 'true' : 'false';
     });
     $propFind->handle(self::CANASSIGN_PROPERTYNAME, function () use($node) {
         // this is the effective permission for the current user
         return $this->tagManager->canUserAssignTag($node->getSystemTag(), $this->userSession->getUser()) ? 'true' : 'false';
     });
     $propFind->handle(self::GROUPS_PROPERTYNAME, function () use($node) {
         if (!$this->groupManager->isAdmin($this->userSession->getUser()->getUID())) {
             // property only available for admins
             throw new Forbidden();
         }
         $groups = [];
         // no need to retrieve groups for namespaces that don't qualify
         if ($node->getSystemTag()->isUserVisible() && !$node->getSystemTag()->isUserAssignable()) {
             $groups = $this->tagManager->getTagGroups($node->getSystemTag());
         }
         return implode('|', $groups);
     });
 }
Пример #18
0
 /**
  * Triggered by a `PROPFIND` or `GET`. The goal is to set an appropriated
  * Content-Type.
  *
  * @param  SabreDav\PropFind  $propFind    PropFind object.
  * @param  SabreDav\INode     $node        Node.
  */
 function propFind(SabreDav\PropFind $propFind, SabreDav\INode $node)
 {
     $propFind->handle('{DAV:}getcontenttype', function () use($propFind) {
         Mime::compute('katana://resource/mime.types');
         $extension = pathinfo($propFind->getPath(), PATHINFO_EXTENSION);
         return Mime::getMimeFromExtension($extension);
     });
 }
Пример #19
0
 /**
  * This event is triggered when properties are requested for nodes.
  *
  * This allows us to inject any sharings-specific properties.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     if ($node instanceof ISharedNode) {
         $propFind->handle('{DAV:}share-access', function () use($node) {
             return new Property\ShareAccess($node->getShareAccess());
         });
         $propFind->handle('{DAV:}invite', function () use($node) {
             return new Property\Invite($node->getInvites());
         });
         $propFind->handle('{DAV:}share-resource-uri', function () use($node) {
             return new Property\Href($node->getShareResourceUri());
         });
     }
 }
Пример #20
0
 /**
  * Adds all ownCloud-specific properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if ($node instanceof \OC\Connector\Sabre\Node) {
         $propFind->handle(self::FILEID_PROPERTYNAME, function () use($node) {
             return $node->getFileId();
         });
         $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use($node) {
             $perms = $node->getDavPermissions();
             if ($this->isPublic) {
                 // remove mount information
                 $perms = str_replace(['S', 'M'], '', $perms);
             }
             return $perms;
         });
         $propFind->handle(self::GETETAG_PROPERTYNAME, function () use($node) {
             return $node->getEtag();
         });
     }
     if ($node instanceof \OC\Connector\Sabre\File) {
         $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use($node) {
             /** @var $node \OC\Connector\Sabre\File */
             try {
                 $directDownloadUrl = $node->getDirectDownload();
                 if (isset($directDownloadUrl['url'])) {
                     return $directDownloadUrl['url'];
                 }
             } catch (StorageNotAvailableException $e) {
                 // return empty download link when storage not available
                 return false;
             }
             return false;
         });
     }
     if ($node instanceof \OC\Connector\Sabre\Directory) {
         $propFind->handle(self::SIZE_PROPERTYNAME, function () use($node) {
             return $node->getSize();
         });
     }
 }
Пример #21
0
 /**
  * Adds tags and favorites properties to the response,
  * if requested.
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if (!$node instanceof \OCA\DAV\Connector\Sabre\Node) {
         return;
     }
     // need prefetch ?
     if ($node instanceof \OCA\DAV\Connector\Sabre\Directory && $propFind->getDepth() !== 0 && (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME)) || !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME)))) {
         // note: pre-fetching only supported for depth <= 1
         $folderContent = $node->getChildren();
         $fileIds[] = (int) $node->getId();
         foreach ($folderContent as $info) {
             $fileIds[] = (int) $info->getId();
         }
         $tags = $this->getTagger()->getTagsForObjects($fileIds);
         if ($tags === false) {
             // the tags API returns false on error...
             $tags = array();
         }
         $this->cachedTags = $this->cachedTags + $tags;
         $emptyFileIds = array_diff($fileIds, array_keys($tags));
         // also cache the ones that were not found
         foreach ($emptyFileIds as $fileId) {
             $this->cachedTags[$fileId] = [];
         }
     }
     $tags = null;
     $isFav = null;
     $propFind->handle(self::TAGS_PROPERTYNAME, function () use($tags, &$isFav, $node) {
         list($tags, $isFav) = $this->getTagsAndFav($node->getId());
         return new TagList($tags);
     });
     $propFind->handle(self::FAVORITE_PROPERTYNAME, function () use($isFav, $node) {
         if (is_null($isFav)) {
             list(, $isFav) = $this->getTagsAndFav($node->getId());
         }
         return $isFav;
     });
 }
Пример #22
0
 /**
  * This event is triggered when properties are requested for a certain
  * node.
  *
  * This allows us to inject any properties early.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     if ($node instanceof IShareable) {
         $propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use($node) {
             return new Invite($node->getShares());
         });
     }
 }
Пример #23
0
 /**
  * This method handler is invoked during fetching of properties.
  *
  * We use this event to add calendar-auto-schedule-specific properties.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     if ($node instanceof DAVACL\IPrincipal) {
         $caldavPlugin = $this->server->getPlugin('caldav');
         $principalUrl = $node->getPrincipalUrl();
         // schedule-outbox-URL property
         $propFind->handle('{' . self::NS_CALDAV . '}schedule-outbox-URL', function () use($principalUrl, $caldavPlugin) {
             $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
             if (!$calendarHomePath) {
                 return null;
             }
             $outboxPath = $calendarHomePath . '/outbox/';
             return new LocalHref($outboxPath);
         });
         // schedule-inbox-URL property
         $propFind->handle('{' . self::NS_CALDAV . '}schedule-inbox-URL', function () use($principalUrl, $caldavPlugin) {
             $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
             if (!$calendarHomePath) {
                 return null;
             }
             $inboxPath = $calendarHomePath . '/inbox/';
             return new LocalHref($inboxPath);
         });
         $propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function () use($principalUrl, $caldavPlugin) {
             // We don't support customizing this property yet, so in the
             // meantime we just grab the first calendar in the home-set.
             $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
             if (!$calendarHomePath) {
                 return null;
             }
             $sccs = '{' . self::NS_CALDAV . '}supported-calendar-component-set';
             $result = $this->server->getPropertiesForPath($calendarHomePath, ['{DAV:}resourcetype', '{DAV:}share-access', $sccs], 1);
             foreach ($result as $child) {
                 if (!isset($child[200]['{DAV:}resourcetype']) || !$child[200]['{DAV:}resourcetype']->is('{' . self::NS_CALDAV . '}calendar')) {
                     // Node is either not a calendar
                     continue;
                 }
                 if (isset($child[200]['{DAV:}share-access'])) {
                     $shareAccess = $child[200]['{DAV:}share-access']->getValue();
                     if ($shareAccess !== Sharing\Plugin::ACCESS_NOTSHARED && $shareAccess !== Sharing\Plugin::ACCESS_SHAREDOWNER) {
                         // Node is a shared node, not owned by the relevant
                         // user.
                         continue;
                     }
                 }
                 if (!isset($child[200][$sccs]) || in_array('VEVENT', $child[200][$sccs]->getValue())) {
                     // Either there is no supported-calendar-component-set
                     // (which is fine) or we found one that supports VEVENT.
                     return new LocalHref($child['href']);
                 }
             }
         });
         // The server currently reports every principal to be of type
         // 'INDIVIDUAL'
         $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function () {
             return 'INDIVIDUAL';
         });
     }
     // Mapping the old property to the new property.
     $propFind->handle('{http://calendarserver.org/ns/}calendar-availability', function () use($propFind, $node) {
         // In case it wasn't clear, the only difference is that we map the
         // old property to a different namespace.
         $availProp = '{' . self::NS_CALDAV . '}calendar-availability';
         $subPropFind = new PropFind($propFind->getPath(), [$availProp]);
         $this->server->getPropertiesByNode($subPropFind, $node);
         $propFind->set('{http://calendarserver.org/ns/}calendar-availability', $subPropFind->get($availProp), $subPropFind->getStatus($availProp));
     });
 }
Пример #24
0
 /**
  * This method is triggered *after* all properties have been retrieved.
  * This allows us to inject the correct resourcetype for calendars that
  * have been shared.
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFindLate(DAV\PropFind $propFind, DAV\INode $node)
 {
     if ($node instanceof IShareableCalendar) {
         if ($rt = $propFind->get('{DAV:}resourcetype')) {
             if (count($node->getShares()) > 0) {
                 $rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
             }
         }
         $propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function () {
             return new Xml\Property\AllowedSharingModes(true, false);
         });
     }
 }
Пример #25
0
 /**
  * Retrieves system tag properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if (!$node instanceof SystemTagNode) {
         return;
     }
     $propFind->handle(self::ID_PROPERTYNAME, function () use($node) {
         return $node->getSystemTag()->getId();
     });
     $propFind->handle(self::DISPLAYNAME_PROPERTYNAME, function () use($node) {
         return $node->getSystemTag()->getName();
     });
     $propFind->handle(self::USERVISIBLE_PROPERTYNAME, function () use($node) {
         return (int) $node->getSystemTag()->isUserVisible();
     });
     $propFind->handle(self::USERASSIGNABLE_PROPERTYNAME, function () use($node) {
         return (int) $node->getSystemTag()->isUserAssignable();
     });
 }
Пример #26
0
 /**
  * Adds all ownCloud-specific properties
  *
  * @param PropFind $propFind
  * @param \Sabre\DAV\INode $node
  * @return void
  */
 public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
 {
     if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
         $propFind->handle(self::FILEID_PROPERTYNAME, function () use($node) {
             return $node->getFileId();
         });
         $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function () use($node) {
             return $node->getInternalFileId();
         });
         $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use($node) {
             $perms = $node->getDavPermissions();
             if ($this->isPublic) {
                 // remove mount information
                 $perms = str_replace(['S', 'M'], '', $perms);
             }
             return $perms;
         });
         $propFind->handle(self::GETETAG_PROPERTYNAME, function () use($node) {
             return $node->getEtag();
         });
     }
     if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
         $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use($node) {
             /** @var $node \OCA\DAV\Connector\Sabre\File */
             $directDownloadUrl = $node->getDirectDownload();
             if (isset($directDownloadUrl['url'])) {
                 return $directDownloadUrl['url'];
             }
             return false;
         });
     }
     if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
         $propFind->handle(self::SIZE_PROPERTYNAME, function () use($node) {
             return $node->getSize();
         });
     }
     $propFind->handle(self::OWNER_ID_PROPERTYNAME, function () use($node) {
         $owner = $node->getOwner();
         return $owner->getUID();
     });
     $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function () use($node) {
         $owner = $node->getOwner();
         $displayName = $owner->getDisplayName();
         return $displayName;
     });
 }
Пример #27
0
    /**
     * Adds all CardDAV-specific properties
     *
     * @param DAV\PropFind $propFind
     * @param DAV\INode $node
     * @return void
     */
    function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {

        $ns = '{' . self::NS_CARDDAV . '}';

        if ($node instanceof IAddressBook) {

            $propFind->handle($ns . 'max-resource-size', $this->maxResourceSize);
            $propFind->handle($ns . 'supported-address-data', function() {
                return new Xml\Property\SupportedAddressData();
            });
            $propFind->handle($ns . 'supported-collation-set', function() {
                return new Xml\Property\SupportedCollationSet();
            });

        }
        if ($node instanceof DAVACL\IPrincipal) {

            $path = $propFind->getPath();

            $propFind->handle('{' . self::NS_CARDDAV . '}addressbook-home-set', function() use ($path) {
                return new Href($this->getAddressBookHomeForPrincipal($path) . '/');
            });

            if ($this->directories) $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function() {
                return new Href($this->directories);
            });

        }

        if ($node instanceof ICard) {

            // The address-data property is not supposed to be a 'real'
            // property, but in large chunks of the spec it does act as such.
            // Therefore we simply expose it as a property.
            $propFind->handle('{' . self::NS_CARDDAV . '}address-data', function() use ($node) {
                $val = $node->get();
                if (is_resource($val))
                    $val = stream_get_contents($val);

                return $val;

            });

        }

    }
Пример #28
0
 /**
  * Adds all CardDAV-specific properties
  *
  * @param DAV\PropFind $propFind
  * @param DAV\INode $node
  * @return void
  */
 function propFindEarly(DAV\PropFind $propFind, DAV\INode $node)
 {
     $ns = '{' . self::NS_CARDDAV . '}';
     if ($node instanceof IAddressBook) {
         $propFind->handle($ns . 'max-resource-size', $this->maxResourceSize);
         $propFind->handle($ns . 'supported-address-data', function () {
             return new Property\SupportedAddressData();
         });
         $propFind->handle($ns . 'supported-collation-set', function () {
             return new Property\SupportedCollationSet();
         });
     }
     if ($node instanceof DAVACL\IPrincipal) {
         $path = $propFind->getPath();
         $propFind->handle('{' . self::NS_CARDDAV . '}addressbook-home-set', function () use($path) {
             return new DAV\Property\Href($this->getAddressBookHomeForPrincipal($path) . '/');
         });
         if ($this->directories) {
             $propFind->handle('{' . self::NS_CARDDAV . '}directory-gateway', function () {
                 return new DAV\Property\HrefList($this->directories);
             });
         }
     }
     if ($node instanceof ICard) {
         // The address-data property is not supposed to be a 'real'
         // property, but in large chunks of the spec it does act as such.
         // Therefore we simply expose it as a property.
         $propFind->handle('{' . self::NS_CARDDAV . '}address-data', function () use($node) {
             $val = $node->get();
             if (is_resource($val)) {
                 $val = stream_get_contents($val);
             }
             return $val;
         });
     }
     if ($node instanceof UserAddressBooks) {
         $propFind->handle('{http://calendarserver.org/ns/}me-card', function () use($node) {
             $props = $this->server->getProperties($node->getOwner(), ['{http://sabredav.org/ns}vcard-url']);
             if (isset($props['{http://sabredav.org/ns}vcard-url'])) {
                 return new DAV\Property\Href($props['{http://sabredav.org/ns}vcard-url']);
             }
         });
     }
 }
Пример #29
0
 /**
  * This method handler is invoked during fetching of properties.
  *
  * We use this event to add calendar-auto-schedule-specific properties.
  *
  * @param PropFind $propFind
  * @param INode $node
  * @return void
  */
 function propFind(PropFind $propFind, INode $node)
 {
     if (!$node instanceof DAVACL\IPrincipal) {
         return;
     }
     $caldavPlugin = $this->server->getPlugin('caldav');
     $principalUrl = $node->getPrincipalUrl();
     // schedule-outbox-URL property
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-outbox-URL', function () use($principalUrl, $caldavPlugin) {
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $outboxPath = $calendarHomePath . '/outbox/';
         return new Href($outboxPath);
     });
     // schedule-inbox-URL property
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-inbox-URL', function () use($principalUrl, $caldavPlugin) {
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $inboxPath = $calendarHomePath . '/inbox/';
         return new Href($inboxPath);
     });
     $propFind->handle('{' . self::NS_CALDAV . '}schedule-default-calendar-URL', function () use($principalUrl, $caldavPlugin) {
         // We don't support customizing this property yet, so in the
         // meantime we just grab the first calendar in the home-set.
         $calendarHomePath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl);
         $nodes = $this->server->tree->getNodeForPath($calendarHomePath)->getChildren();
         foreach ($nodes as $node) {
             if ($node instanceof ICalendar) {
                 return new Href($calendarHomePath . '/' . $node->getName());
             }
         }
     });
     // The server currently reports every principal to be of type
     // 'INDIVIDUAL'
     $propFind->handle('{' . self::NS_CALDAV . '}calendar-user-type', function () {
         return 'INDIVIDUAL';
     });
 }