Пример #1
0
 function testHTMLActionsPanel()
 {
     $output = '';
     $r = $this->server->emit('onHTMLActionsPanel', [$this->server->tree->getNodeForPath('calendars/user1'), &$output]);
     $this->assertFalse($r);
     $this->assertTrue(!!strpos($output, 'Display name'));
 }
Пример #2
0
 function testCurrentUserPrincipal()
 {
     $fakeServer = new DAV\Server();
     $plugin = new DAV\Auth\Plugin(new DAV\Auth\Backend\Mock());
     $fakeServer->addPlugin($plugin);
     $plugin = new Plugin();
     $plugin->setDefaultACL([['principal' => '{DAV:}all', 'privilege' => '{DAV:}all']]);
     $fakeServer->addPlugin($plugin);
     $requestedProperties = ['{DAV:}current-user-principal'];
     $result = $fakeServer->getPropertiesForPath('', $requestedProperties);
     $result = $result[0];
     $this->assertEquals(1, count($result[200]));
     $this->assertArrayHasKey('{DAV:}current-user-principal', $result[200]);
     $this->assertInstanceOf('Sabre\\DAVACL\\Xml\\Property\\Principal', $result[200]['{DAV:}current-user-principal']);
     $this->assertEquals(Xml\Property\Principal::UNAUTHENTICATED, $result[200]['{DAV:}current-user-principal']->getType());
     // This will force the login
     $fakeServer->emit('beforeMethod', [$fakeServer->httpRequest, $fakeServer->httpResponse]);
     $result = $fakeServer->getPropertiesForPath('', $requestedProperties);
     $result = $result[0];
     $this->assertEquals(1, count($result[200]));
     $this->assertArrayHasKey('{DAV:}current-user-principal', $result[200]);
     $this->assertInstanceOf('Sabre\\DAVACL\\Xml\\Property\\Principal', $result[200]['{DAV:}current-user-principal']);
     $this->assertEquals(Xml\Property\Principal::HREF, $result[200]['{DAV:}current-user-principal']->getType());
     $this->assertEquals('principals/admin/', $result[200]['{DAV:}current-user-principal']->getHref());
 }
Пример #3
0
 function testBeforeGetPropertiesNoListing()
 {
     $this->plugin->hideNodesFromListings = true;
     $propFind = new DAV\PropFind('testdir', ['{DAV:}displayname', '{DAV:}getcontentlength', '{DAV:}bar', '{DAV:}owner']);
     $r = $this->server->emit('propFind', [$propFind, new DAV\SimpleCollection('testdir')]);
     $this->assertFalse($r);
 }
Пример #4
0
 /**
  * This method is responsible for delivering the ITip message.
  *
  * @param ITip\Message $itipMessage
  * @return void
  */
 function deliver(ITip\Message $iTipMessage)
 {
     $this->server->emit('schedule', [$iTipMessage]);
     if (!$iTipMessage->scheduleStatus) {
         $iTipMessage->scheduleStatus = '5.2;There was no system capable of delivering the scheduling message';
     }
 }
Пример #5
0
 function schedule(Message $message)
 {
     $plugin = new IMip\MockPlugin('*****@*****.**');
     $server = new Server();
     $server->addPlugin($plugin);
     $server->emit('schedule', [$message]);
     return $plugin->getSentEmails();
 }
Пример #6
0
 /**
  * @depends testInit
  */
 function testGetCurrentUserPrincipal()
 {
     $fakeServer = new DAV\Server(new DAV\SimpleCollection('bla'));
     $plugin = new Plugin(new Backend\Mock(), 'realm');
     $fakeServer->addPlugin($plugin);
     $fakeServer->emit('beforeMethod', [new HTTP\Request(), new HTTP\Response()]);
     $this->assertEquals('admin', $plugin->getCurrentUser());
 }
Пример #7
0
 /**
  * HTTP REPORT method implementation
  *
  * Although the REPORT method is not part of the standard WebDAV spec (it's from rfc3253)
  * It's used in a lot of extensions, so it made sense to implement it into the core.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpReport(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $result = $this->server->xml->parse($request->getBody(), $request->getUrl(), $rootElementName);
     if ($this->server->emit('report', [$rootElementName, $result, $path])) {
         // If emit returned true, it means the report was not supported
         throw new Exception\ReportNotSupported();
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
Пример #8
0
 /**
  * This method is responsible for delivering the ITip message.
  *
  * @param ITip\Message $itipMessage
  * @return void
  */
 function deliver(ITip\Message $iTipMessage)
 {
     $this->server->emit('schedule', [$iTipMessage]);
     if (!$iTipMessage->scheduleStatus) {
         $iTipMessage->scheduleStatus = '5.2;There was no system capable of delivering the scheduling message';
     }
     // In case the change was considered 'insignificant', we are going to
     // remove any error statuses, if any. See ticket #525.
     list($baseCode) = explode('.', $iTipMessage->scheduleStatus);
     if (!$iTipMessage->significantChange && in_array($baseCode, ['3', '5'])) {
         $iTipMessage->scheduleStatus = null;
     }
 }
Пример #9
0
 /**
  * HTTP REPORT method implementation
  *
  * Although the REPORT method is not part of the standard WebDAV spec (it's from rfc3253)
  * It's used in a lot of extensions, so it made sense to implement it into the core.
  *
  * @param RequestInterface $request
  * @param ResponseInterface $response
  * @return bool
  */
 function httpReport(RequestInterface $request, ResponseInterface $response)
 {
     $path = $request->getPath();
     $body = $request->getBodyAsString();
     $dom = XMLUtil::loadDOMDocument($body);
     $reportName = XMLUtil::toClarkNotation($dom->firstChild);
     if ($this->server->emit('report', [$reportName, $dom, $path])) {
         // If emit returned true, it means the report was not supported
         throw new Exception\ReportNotSupported();
     }
     // Sending back false will interupt the event chain and tell the server
     // we've handled this method.
     return false;
 }
Пример #10
0
 /**
  * Updates the list of sharees on a shared resource.
  *
  * The sharees  array is a list of people that are to be added modified
  * or removed in the list of shares.
  *
  * @param string $path
  * @param Sharee[] $sharees
  * @return void
  */
 function shareResource($path, array $sharees)
 {
     $node = $this->server->tree->getNodeForPath($path);
     if (!$node instanceof ISharedNode) {
         throw new Forbidden('Sharing is not allowed on this node');
     }
     // Getting ACL info
     $acl = $this->server->getPlugin('acl');
     // If there's no ACL support, we allow everything
     if ($acl) {
         $acl->checkPrivileges($path, '{DAV:}share');
     }
     foreach ($sharees as $sharee) {
         // We're going to attempt to get a local principal uri for a share
         // href by emitting the getPrincipalByUri event.
         $principal = null;
         $this->server->emit('getPrincipalByUri', [$sharee->href, &$principal]);
         $sharee->principal = $principal;
     }
     $node->updateInvites($sharees);
 }
Пример #11
0
 /**
  * Checks if the submitted iCalendar data is in fact, valid.
  *
  * An exception is thrown if it's not.
  *
  * @param resource|string $data
  * @param string $path
  * @param bool $modified Should be set to true, if this event handler
  *                       changed &$data.
  * @param RequestInterface $request The http request.
  * @param ResponseInterface $response The http response.
  * @param bool $isNew Is the item a new one, or an update.
  * @return void
  */
 protected function validateICalendar(&$data, $path, &$modified, RequestInterface $request, ResponseInterface $response, $isNew)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     $before = md5($data);
     // Converting the data to unicode, if needed.
     $data = DAV\StringUtil::ensureUTF8($data);
     if ($before !== md5($data)) {
         $modified = true;
     }
     try {
         // If the data starts with a [, we can reasonably assume we're dealing
         // with a jCal object.
         if (substr($data, 0, 1) === '[') {
             $vobj = VObject\Reader::readJson($data);
             // Converting $data back to iCalendar, as that's what we
             // technically support everywhere.
             $data = $vobj->serialize();
             $modified = true;
         } else {
             $vobj = VObject\Reader::read($data);
         }
     } catch (VObject\ParseException $e) {
         throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
     }
     if ($vobj->name !== 'VCALENDAR') {
         throw new DAV\Exception\UnsupportedMediaType('This collection can only support iCalendar objects.');
     }
     $sCCS = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
     // Get the Supported Components for the target calendar
     list($parentPath) = Uri\split($path);
     $calendarProperties = $this->server->getProperties($parentPath, [$sCCS]);
     if (isset($calendarProperties[$sCCS])) {
         $supportedComponents = $calendarProperties[$sCCS]->getValue();
     } else {
         $supportedComponents = ['VJOURNAL', 'VTODO', 'VEVENT'];
     }
     $foundType = null;
     $foundUID = null;
     foreach ($vobj->getComponents() as $component) {
         switch ($component->name) {
             case 'VTIMEZONE':
                 continue 2;
             case 'VEVENT':
             case 'VTODO':
             case 'VJOURNAL':
                 if (is_null($foundType)) {
                     $foundType = $component->name;
                     if (!in_array($foundType, $supportedComponents)) {
                         throw new Exception\InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType);
                     }
                     if (!isset($component->UID)) {
                         throw new DAV\Exception\BadRequest('Every ' . $component->name . ' component must have an UID');
                     }
                     $foundUID = (string) $component->UID;
                 } else {
                     if ($foundType !== $component->name) {
                         throw new DAV\Exception\BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType);
                     }
                     if ($foundUID !== (string) $component->UID) {
                         throw new DAV\Exception\BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
                     }
                 }
                 break;
             default:
                 throw new DAV\Exception\BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
         }
     }
     if (!$foundType) {
         throw new DAV\Exception\BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
     }
     // We use an extra variable to allow event handles to tell us wether
     // the object was modified or not.
     //
     // This helps us determine if we need to re-serialize the object.
     $subModified = false;
     $this->server->emit('calendarObjectChange', [$request, $response, $vobj, $parentPath, &$subModified, $isNew]);
     if ($subModified) {
         // An event handler told us that it modified the object.
         $data = $vobj->serialize();
         // Using md5 to figure out if there was an *actual* change.
         if (!$modified && $before !== md5($data)) {
             $modified = true;
         }
     }
 }
Пример #12
0
 function testBeforeUnbind()
 {
     $this->assertTrue($this->server->emit('beforeUnbind', ['testdir']));
 }
Пример #13
0
 /**
  * Checks if the submitted iCalendar data is in fact, valid.
  *
  * An exception is thrown if it's not.
  *
  * @param resource|string $data
  * @param string $path
  * @param bool $modified Should be set to true, if this event handler
  *                       changed &$data.
  * @param RequestInterface $request The http request.
  * @param ResponseInterface $response The http response.
  * @param bool $isNew Is the item a new one, or an update.
  * @return void
  */
 protected function validateICalendar(&$data, $path, &$modified, RequestInterface $request, ResponseInterface $response, $isNew)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     $before = $data;
     try {
         // If the data starts with a [, we can reasonably assume we're dealing
         // with a jCal object.
         if (substr($data, 0, 1) === '[') {
             $vobj = VObject\Reader::readJson($data);
             // Converting $data back to iCalendar, as that's what we
             // technically support everywhere.
             $data = $vobj->serialize();
             $modified = true;
         } else {
             $vobj = VObject\Reader::read($data);
         }
     } catch (VObject\ParseException $e) {
         throw new DAV\Exception\UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
     }
     if ($vobj->name !== 'VCALENDAR') {
         throw new DAV\Exception\UnsupportedMediaType('This collection can only support iCalendar objects.');
     }
     $sCCS = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
     // Get the Supported Components for the target calendar
     list($parentPath) = Uri\split($path);
     $calendarProperties = $this->server->getProperties($parentPath, [$sCCS]);
     if (isset($calendarProperties[$sCCS])) {
         $supportedComponents = $calendarProperties[$sCCS]->getValue();
     } else {
         $supportedComponents = ['VJOURNAL', 'VTODO', 'VEVENT'];
     }
     $foundType = null;
     foreach ($vobj->getComponents() as $component) {
         switch ($component->name) {
             case 'VTIMEZONE':
                 continue 2;
             case 'VEVENT':
             case 'VTODO':
             case 'VJOURNAL':
                 $foundType = $component->name;
                 break;
         }
     }
     if (!$foundType || !in_array($foundType, $supportedComponents)) {
         throw new Exception\InvalidComponentType('iCalendar objects must at least have a component of type ' . implode(', ', $supportedComponents));
     }
     $options = VObject\Node::PROFILE_CALDAV;
     $prefer = $this->server->getHTTPPrefer();
     if ($prefer['handling'] !== 'strict') {
         $options |= VObject\Node::REPAIR;
     }
     $messages = $vobj->validate($options);
     $highestLevel = 0;
     $warningMessage = null;
     // $messages contains a list of problems with the vcard, along with
     // their severity.
     foreach ($messages as $message) {
         if ($message['level'] > $highestLevel) {
             // Recording the highest reported error level.
             $highestLevel = $message['level'];
             $warningMessage = $message['message'];
         }
         switch ($message['level']) {
             case 1:
                 // Level 1 means that there was a problem, but it was repaired.
                 $modified = true;
                 break;
             case 2:
                 // Level 2 means a warning, but not critical
                 break;
             case 3:
                 // Level 3 means a critical error
                 throw new DAV\Exception\UnsupportedMediaType('Validation error in iCalendar: ' . $message['message']);
         }
     }
     if ($warningMessage) {
         $response->setHeader('X-Sabre-Ew-Gross', 'iCalendar validation warning: ' . $warningMessage);
     }
     // We use an extra variable to allow event handles to tell us wether
     // the object was modified or not.
     //
     // This helps us determine if we need to re-serialize the object.
     $subModified = false;
     $this->server->emit('calendarObjectChange', [$request, $response, $vobj, $parentPath, &$subModified, $isNew]);
     if ($modified || $subModified) {
         // An event handler told us that it modified the object.
         $data = $vobj->serialize();
         // Using md5 to figure out if there was an *actual* change.
         if (!$modified && strcmp($data, $before) !== 0) {
             $modified = true;
         }
     }
     // Destroy circular references so PHP will garbage collect the object.
     $vobj->destroy();
 }