/** * test testGetProperties method */ public function testGetProperties() { $body = '<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"> <prop> <default-alarm-vevent-date xmlns="urn:ietf:params:xml:ns:caldav"/> <default-alarm-vevent-datetime xmlns="urn:ietf:params:xml:ns:caldav"/> <default-alarm-vtodo-date xmlns="urn:ietf:params:xml:ns:caldav"/> <default-alarm-vtodo-datetime xmlns="urn:ietf:params:xml:ns:caldav"/> </prop> </propfind>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'PROPFIND', 'REQUEST_URI' => '/calendars/' . Tinebase_Core::getUser()->contact_id, 'HTTP_DEPTH' => '0')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); //var_dump($this->response->body); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $responseDoc = new DOMDocument(); $responseDoc->loadXML($this->response->body); //$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav'); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vevent-datetime'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vevent-date'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vtodo-datetime'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vtodo-date'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
public function testExpandProperty() { $list = Tinebase_Group::getInstance()->getGroupById(Tinebase_Core::getUser()->accountPrimaryGroup); $body = '<?xml version="1.0" encoding="UTF-8"?> <A:expand-property xmlns:A="DAV:"> <A:property name="expanded-group-member-set" namespace="http://calendarserver.org/ns/"> <A:property name="last-name" namespace="http://calendarserver.org/ns/"/> <A:property name="principal-URL" namespace="DAV:"/> <A:property name="calendar-user-type" namespace="urn:ietf:params:xml:ns:caldav"/> <A:property name="calendar-user-address-set" namespace="urn:ietf:params:xml:ns:caldav"/> <A:property name="first-name" namespace="http://calendarserver.org/ns/"/> <A:property name="record-type" namespace="http://calendarserver.org/ns/"/> <A:property name="displayname" namespace="DAV:"/> </A:property> </A:expand-property>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/principals/groups/' . $list->list_id . '/')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); $responseDoc = new DOMDocument(); $responseDoc->loadXML($this->response->body); #$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav'); $xpath->registerNamespace('cs', 'http://calendarserver.org/ns/'); $nodes = $xpath->query('///cs:expanded-group-member-set/d:response/d:href[text()="/principals/groups/' . $list->list_id . '/"]'); $this->assertEquals(1, $nodes->length, 'group itself (not shown by client) is missing'); $nodes = $xpath->query('///cs:expanded-group-member-set/d:response/d:href[text()="/principals/intelligroups/' . $list->list_id . '/"]'); $this->assertEquals(1, $nodes->length, 'intelligroup (to keep group itself) is missing'); $nodes = $xpath->query('///cs:expanded-group-member-set/d:response/d:href[text()="/principals/users/' . Tinebase_Core::getUser()->contact_id . '/"]'); $this->assertEquals(1, $nodes->length, 'user is missing'); }
/** * (non-PHPdoc) * @see Sabre\DAV\Collection::getChild() */ public function getChild($_name) { $eventId = $_name instanceof Tinebase_Record_Interface ? $_name->getId() : $this->_getIdFromName($_name); // check if child exists in calendarQuery cache if ($this->_calendarQueryCache && isset($this->_calendarQueryCache[$eventId])) { $child = $this->_calendarQueryCache[$eventId]; // remove entries from cache / they will not be used anymore unset($this->_calendarQueryCache[$eventId]); if (empty($this->_calendarQueryCache)) { $this->_calendarQueryCache = null; } return $child; } $modelName = $this->_application->name . '_Model_' . $this->_model; if ($_name instanceof $modelName) { $object = $_name; } else { $filterClass = $this->_application->name . '_Model_' . $this->_model . 'Filter'; $filter = new $filterClass(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_container->getId()), array('condition' => 'OR', 'filters' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $eventId), array('field' => 'uid', 'operator' => 'equals', 'value' => $eventId))))); $object = $this->_getController()->search($filter, null, false, false, 'sync')->getFirstRecord(); if ($object == null) { throw new Sabre\DAV\Exception\NotFound('Object not found'); } } $httpRequest = new Sabre\HTTP\Request(); // lie about existence of event of request is a PUT request from an ATTENDEE for an already existing event // to prevent ugly (and not helpful) error messages on the client if (isset($_SERVER['REQUEST_METHOD']) && $httpRequest->getMethod() == 'PUT' && $httpRequest->getHeader('If-None-Match') === '*') { if ($object->organizer != Tinebase_Core::getUser()->contact_id && Calendar_Model_Attender::getOwnAttender($object->attendee) !== null) { throw new Sabre\DAV\Exception\NotFound('Object not found'); } } $objectClass = $this->_application->name . '_Frontend_WebDAV_' . $this->_model; return new $objectClass($this->_container, $object); }
/** * test testGetProperties method */ public function testGetProperties() { $body = '<?xml version="1.0" encoding="utf-8"?> <propfind xmlns="DAV:"> <prop> <getlastmodified xmlns="DAV:"/> <getcontentlength xmlns="DAV:"/> <resourcetype xmlns="DAV:"/> <getetag xmlns="DAV:"/> <id xmlns="http://owncloud.org/ns"/> </prop> </propfind>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'PROPFIND', 'REQUEST_URI' => '/remote.php/webdav/' . Tinebase_Core::getUser()->accountDisplayName, 'HTTP_DEPTH' => '0')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); //var_dump($this->response->body); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $responseDoc = new DOMDocument(); $responseDoc->loadXML($this->response->body); //$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('owncloud', 'http://owncloud.org/ns'); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/owncloud:id'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
function testDefaultInputStream() { $h = fopen('php://memory', 'r+'); fwrite($h, 'testing'); rewind($h); $previousValue = Request::$defaultInputStream; Request::$defaultInputStream = $h; $this->assertEquals('testing', $this->request->getBody(true), 'We didn\'t get our testbody back'); Request::$defaultInputStream = $previousValue; }
/** * Returns the HTTP Prefer header information. * * The prefer header is defined in: * http://tools.ietf.org/html/draft-snell-http-prefer-14 * * This method will return an array with options. * * Currently, the following options may be returned: * [ * 'return-asynch' => true, * 'return-minimal' => true, * 'return-representation' => true, * 'wait' => 30, * 'strict' => true, * 'lenient' => true, * ] * * This method also supports the Brief header, and will also return * 'return-minimal' if the brief header was set to 't'. * * For the boolean options, false will be returned if the headers are not * specified. For the integer options it will be 'null'. * * @return array */ function getHTTPPrefer() { $result = [ // can be true or false 'respond-async' => false, // Could be set to 'representation' or 'minimal'. 'return' => null, // Used as a timeout, is usually a number. 'wait' => null, // can be 'strict' or 'lenient'. 'handling' => false, ]; if ($prefer = $this->httpRequest->getHeader('Prefer')) { $result = array_merge( $result, \Sabre\HTTP\parsePrefer($prefer) ); } elseif ($this->httpRequest->getHeader('Brief') == 't') { $result['return'] = 'minimal'; } return $result; }
/** * Returns the HTTP Prefer header information. * * The prefer header is defined in: * http://tools.ietf.org/html/draft-snell-http-prefer-14 * * This method will return an array with options. * * Currently, the following options may be returned: * [ * 'return-asynch' => true, * 'return-minimal' => true, * 'return-representation' => true, * 'wait' => 30, * 'strict' => true, * 'lenient' => true, * ] * * This method also supports the Brief header, and will also return * 'return-minimal' if the brief header was set to 't'. * * For the boolean options, false will be returned if the headers are not * specified. For the integer options it will be 'null'. * * @return array */ function getHTTPPrefer() { $result = ['return-asynch' => false, 'return-minimal' => false, 'return-representation' => false, 'wait' => null, 'strict' => false, 'lenient' => false]; if ($prefer = $this->httpRequest->getHeader('Prefer')) { $parameters = array_map('trim', explode(',', $prefer)); foreach ($parameters as $parameter) { // Right now our regex only supports the tokens actually // specified in the draft. We may need to expand this if new // tokens get registered. if (!preg_match('/^(?P<token>[a-z0-9-]+)(?:=(?P<value>[0-9]+))?$/', $parameter, $matches)) { continue; } switch ($matches['token']) { case 'return-asynch': case 'return-minimal': case 'return-representation': case 'strict': case 'lenient': $result[$matches['token']] = true; break; case 'wait': $result[$matches['token']] = $matches['value']; break; } } } elseif ($this->httpRequest->getHeader('Brief') == 't') { $result['return-minimal'] = true; } return $result; }
/** * Returns the HTTP Prefer header information. * * The prefer header is defined in: * http://tools.ietf.org/html/draft-snell-http-prefer-14 * * This method will return an array with options. * * Currently, the following options may be returned: * [ * 'return-asynch' => true, * 'return-minimal' => true, * 'return-representation' => true, * 'wait' => 30, * 'strict' => true, * 'lenient' => true, * ] * * This method also supports the Brief header, and will also return * 'return-minimal' if the brief header was set to 't'. * * For the boolean options, false will be returned if the headers are not * specified. For the integer options it will be 'null'. * * @return array */ function getHTTPPrefer() { $result = ['respond-async' => false, 'return' => null, 'wait' => null, 'handling' => false]; if ($prefer = $this->httpRequest->getHeader('Prefer')) { $result = array_merge($result, \Sabre\HTTP\parsePrefer($prefer)); } elseif ($this->httpRequest->getHeader('Brief') == 't') { $result['return'] = 'minimal'; } return $result; }
/** * test testGetProperties method */ public function testGetProperties() { $body = '<?xml version="1.0" encoding="utf-8"?> <A:calendarserver-principal-search xmlns:A="http://calendarserver.org/ns/" context="attendee"> <A:search-token>Administrators</A:search-token> <A:limit> <A:nresults>50</A:nresults> </A:limit> <B:prop xmlns:B="DAV:"> <C:calendar-user-address-set xmlns:C="urn:ietf:params:xml:ns:caldav"/> <C:calendar-user-type xmlns:C="urn:ietf:params:xml:ns:caldav"/> <A:record-type/> <A:first-name/> <A:last-name/> </B:prop> </A:calendarserver-principal-search>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/principals')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); //var_dump($this->response->body); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $responseDoc = new DOMDocument(); $responseDoc->loadXML($this->response->body); #$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav'); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:calendar-user-address-set'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:calendar-user-type'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); $this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); #$nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vtodo-datetime'); #$this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); #$this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); #$nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:default-alarm-vtodo-date'); #$this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); #$this->assertNotEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
/** * */ public function process() { $this->emit('process:before', [['request' => $this->httpRequest]]); // set Content Security Policy and CORS headers $this->httpResponse->addHeader('Content-Security-Policy', "default-src *"); $this->httpResponse->addHeader('X-Content-Security-Policy', "default-src *"); if ($this->httpRequest->hasHeader('Origin')) { // TODO: allow to configure allowed origins $this->httpResponse->addHeader('Access-Control-Allow-Origin', "*"); } // FIXME: respond to OPTIONS requests directly and without validation if ($this->httpRequest->getMethod() == 'OPTIONS') { $this->httpResponse->addHeader('Access-Control-Request-Method', 'GET, POST, OPTIONS'); $this->httpResponse->addHeader('Access-Control-Allow-Headers', $this->httpRequest->getHeader('Access-Control-Request-Headers')); $this->httpResponse->setStatus(204); $this->sapi->sendResponse($this->httpResponse); return; } // extract route from request (jmap, auth|.well-known/jmap, upload) if ($route = $this->getRouteMatch($this->httpRequest->getPath())) { try { call_user_func($this->routes[$route], $this->httpRequest, $this->httpResponse); } catch (\RuntimeException $e) { if ($e instanceof Exception\ProcessorException) { $this->httpResponse->setStatus($e->getStatusCode()); } else { $this->httpResponse->setStatus(500); } $this->logger->err(strval($e)); $this->emit('process:error', [['request' => $this->httpRequest, 'exception' => $e]]); } } else { // TODO: throw invalid route error $this->httpResponse->setStatus(404); } $this->emit('process:after', [['response' => $this->httpResponse]]); $this->sapi->sendResponse($this->httpResponse); }
/** * test sync-collection request */ public function testSyncCollection() { $body = '<?xml version="1.0" encoding="UTF-8"?> <A:sync-collection xmlns:A="DAV:"> <A:sync-token>http://tine20.net/ns/sync/0</A:sync-token> <A:sync-level>1</A:sync-level> <A:prop> <A:getetag/> <A:getcontenttype/> </A:prop> </A:sync-collection>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/calendars/' . Tinebase_Core::getUser()->contact_id . '/' . $this->objects['initialContainer']->id, 'HTTP_DEPTH' => '1')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $this->assertContains('<d:sync-token>http://tine20.net/ns/sync/5</d:sync-token></d:multistatus>', $this->response->body); //check that we only got 2 responses, so no reoccuring events! $this->assertEquals(2, preg_match_all('/<d:response>/', $this->response->body, $m)); }
/** * login from HTTP post * * redirects the tine main screen if authentication is successful * otherwise redirects back to login url */ public function loginFromPost($username, $password) { Tinebase_Core::startCoreSession(); if (!empty($username)) { // try to login user $success = Tinebase_Controller::getInstance()->login($username, $password, Tinebase_Core::get(Tinebase_Core::REQUEST), self::REQUEST_TYPE) === TRUE; } else { $success = FALSE; } if ($success === TRUE) { $this->_setJsonKeyCookie(); $ccAdapter = Tinebase_Auth_CredentialCache::getInstance()->getCacheAdapter(); if (Tinebase_Core::isRegistered(Tinebase_Core::USERCREDENTIALCACHE)) { $ccAdapter->setCache(Tinebase_Core::getUserCredentialCache()); } else { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Something went wrong with the CredentialCache / no CC registered.'); $success = FALSE; $ccAdapter->resetCache(); } } $request = new Sabre\HTTP\Request(); $redirectUrl = str_replace('index.php', '', $request->getAbsoluteUri()); // authentication failed if ($success !== TRUE) { $_SESSION = array(); Tinebase_Session::destroyAndRemoveCookie(); // redirect back to loginurl if needed $redirectUrl = Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, $redirectUrl); } // load the client with GET header('Location: ' . $redirectUrl); }
/** * returns protocol + hostname * * @return string */ public static function getHostname() { $hostname = self::get('HOSTNAME'); if (!$hostname) { $request = new Sabre\HTTP\Request(); $hostname = strlen($request->getUri()) > 1 ? str_replace($request->getUri(), '', $request->getAbsoluteUri()) : $request->getAbsoluteUri(); self::set('HOSTNAME', $hostname); } return $hostname; }
/** * test testGetProperties method */ public function testGetPropertiesSharedUserPrincipal() { $body = '<?xml version="1.0" encoding="UTF-8"?> <A:propfind xmlns:A="DAV:"> <A:prop> <B:calendar-home-set xmlns:B="urn:ietf:params:xml:ns:caldav"/> <B:calendar-user-address-set xmlns:B="urn:ietf:params:xml:ns:caldav"/> <A:current-user-principal/> <A:displayname/> <C:dropbox-home-URL xmlns:C="http://calendarserver.org/ns/"/> <C:email-address-set xmlns:C="http://calendarserver.org/ns/"/> <C:notification-URL xmlns:C="http://calendarserver.org/ns/"/> <A:principal-collection-set/> <A:principal-URL/> <A:resource-id/> <B:schedule-inbox-URL xmlns:B="urn:ietf:params:xml:ns:caldav"/> <B:schedule-outbox-URL xmlns:B="urn:ietf:params:xml:ns:caldav"/> <A:supported-report-set/> </A:prop> </A:propfind>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'PROPFIND', 'REQUEST_URI' => '/' . Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_WebDav_PrincipalBackend::SHARED, 'HTTP_BRIEF' => 't', 'HTTP_DEPTH' => '0')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); //var_dump($this->response->body); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $responseDoc = new DOMDocument(); $responseDoc->loadXML($this->response->body); //$responseDoc->formatOutput = true; echo $responseDoc->saveXML(); $xpath = new DomXPath($responseDoc); $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav'); $xpath->registerNamespace('cs', 'http://calendarserver.org/ns/'); $xpath->registerNamespace('d', 'DAV'); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:calendar-home-set'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/d:principal-URL'); $this->assertEquals(1, $nodes->length, $responseDoc->saveXML()); #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML()); }
/** * This method checks the main HTTP preconditions. * * Currently these are: * * If-Match * * If-None-Match * * If-Modified-Since * * If-Unmodified-Since * * The method will return true if all preconditions are met * The method will return false, or throw an exception if preconditions * failed. If false is returned the operation should be aborted, and * the appropriate HTTP response headers are already set. * * Normally this method will throw 412 Precondition Failed for failures * related to If-None-Match, If-Match and If-Unmodified Since. It will * set the status to 304 Not Modified for If-Modified_since. * * If the $handleAsGET argument is set to true, it will also return 304 * Not Modified for failure of the If-None-Match precondition. This is the * desired behaviour for HTTP GET and HTTP HEAD requests. * * @param bool $handleAsGET * @return bool */ public function checkPreconditions($handleAsGET = false) { $uri = $this->getRequestUri(); $node = null; $lastMod = null; $etag = null; if ($ifMatch = $this->httpRequest->getHeader('If-Match')) { // If-Match contains an entity tag. Only if the entity-tag // matches we are allowed to make the request succeed. // If the entity-tag is '*' we are only allowed to make the // request succeed if a resource exists at that url. try { $node = $this->tree->getNodeForPath($uri); } catch (Exception\NotFound $e) { throw new Exception\PreconditionFailed('An If-Match header was specified and the resource did not exist', 'If-Match'); } // Only need to check entity tags if they are not * if ($ifMatch !== '*') { // There can be multiple etags $ifMatch = explode(',', $ifMatch); $haveMatch = false; foreach ($ifMatch as $ifMatchItem) { // Stripping any extra spaces $ifMatchItem = trim($ifMatchItem, ' '); $etag = $node->getETag(); if ($etag === $ifMatchItem) { $haveMatch = true; } else { // Evolution has a bug where it sometimes prepends the " // with a \. This is our workaround. if (str_replace('\\"', '"', $ifMatchItem) === $etag) { $haveMatch = true; } } } if (!$haveMatch) { throw new Exception\PreconditionFailed('An If-Match header was specified, but none of the specified the ETags matched.', 'If-Match'); } } } if ($ifNoneMatch = $this->httpRequest->getHeader('If-None-Match')) { // The If-None-Match header contains an etag. // Only if the ETag does not match the current ETag, the request will succeed // The header can also contain *, in which case the request // will only succeed if the entity does not exist at all. $nodeExists = true; if (!$node) { try { $node = $this->tree->getNodeForPath($uri); } catch (Exception\NotFound $e) { $nodeExists = false; } } if ($nodeExists) { $haveMatch = false; if ($ifNoneMatch === '*') { $haveMatch = true; } else { // There might be multiple etags $ifNoneMatch = explode(',', $ifNoneMatch); $etag = $node->getETag(); foreach ($ifNoneMatch as $ifNoneMatchItem) { // Stripping any extra spaces $ifNoneMatchItem = trim($ifNoneMatchItem, ' '); if ($etag === $ifNoneMatchItem) { $haveMatch = true; } } } if ($haveMatch) { if ($handleAsGET) { $this->httpResponse->sendStatus(304); return false; } else { throw new Exception\PreconditionFailed('An If-None-Match header was specified, but the ETag matched (or * was specified).', 'If-None-Match'); } } } } if (!$ifNoneMatch && ($ifModifiedSince = $this->httpRequest->getHeader('If-Modified-Since'))) { // The If-Modified-Since header contains a date. We // will only return the entity if it has been changed since // that date. If it hasn't been changed, we return a 304 // header // Note that this header only has to be checked if there was no If-None-Match header // as per the HTTP spec. $date = HTTP\Util::parseHTTPDate($ifModifiedSince); if ($date) { if (is_null($node)) { $node = $this->tree->getNodeForPath($uri); } $lastMod = $node->getLastModified(); if ($lastMod) { $lastMod = new \DateTime('@' . $lastMod); if ($lastMod <= $date) { $this->httpResponse->sendStatus(304); $this->httpResponse->setHeader('Last-Modified', HTTP\Util::toHTTPDate($lastMod)); return false; } } } } if ($ifUnmodifiedSince = $this->httpRequest->getHeader('If-Unmodified-Since')) { // The If-Unmodified-Since will allow allow the request if the // entity has not changed since the specified date. $date = HTTP\Util::parseHTTPDate($ifUnmodifiedSince); // We must only check the date if it's valid if ($date) { if (is_null($node)) { $node = $this->tree->getNodeForPath($uri); } $lastMod = $node->getLastModified(); if ($lastMod) { $lastMod = new \DateTime('@' . $lastMod); if ($lastMod > $date) { throw new Exception\PreconditionFailed('An If-Unmodified-Since header was specified, but the entity has been changed since the specified date.', 'If-Unmodified-Since'); } } } } return true; }
/** * test userQuery method */ public function testUserQuery() { $body = '<?xml version="1.0" encoding="UTF-8"?> <user-query xmlns="urn:inverse:params:xml:ns:inverse-dav"> <users match-name="' . Tinebase_Core::getUser()->accountFullName . '"/> </user-query>'; $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'REPORT', 'REQUEST_URI' => '/calendars/' . Tinebase_Core::getUser()->contact_id . '/' . $this->objects['initialContainer']->id, 'HTTP_DEPTH' => '1')); $request->setBody($body); $this->server->httpRequest = $request; $this->server->exec(); $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status); $this->assertContains('<displayName>' . Tinebase_Core::getUser()->accountDisplayName . '</displayName>', $this->response->body); $this->assertContains('<id>' . Tinebase_Core::getUser()->contact_id . '</id>', $this->response->body); }
public function testDropBoxPut() { $event = $this->calDAVTests->testCreateEventWithInternalOrganizer(); $request = new Sabre\HTTP\Request(array('REQUEST_METHOD' => 'PUT', 'REQUEST_URI' => '/calendars/' . Tinebase_Core::getUser()->contact_id . '/dropbox/' . $event->getRecord()->getId() . '.dropbox/agenda.txt')); $agenda = 'HELLO WORLD'; $request->setBody($agenda); $this->server->httpRequest = $request; $this->server->exec(); // echo $this->response->body; $attachments = Tinebase_FileSystem_RecordAttachments::getInstance()->getRecordAttachments($event->getRecord()); $this->assertEquals(1, $attachments->count()); $this->assertEquals('agenda.txt', $attachments[0]->name); }