function testLibICalLocationName() { $input = <<<HI BEGIN:VCALENDAR VERSION:2.0 BEGIN:VTIMEZONE TZID:My own timezone name X-LIC-LOCATION:America/Los_Angeles BEGIN:STANDARD DTSTART:16010101T030000 TZOFFSETFROM:+0200 TZOFFSETTO:+0100 RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:+0100 TZOFFSETTO:+0200 RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=My own timezone name:20120113T100000 DTEND;TZID=My own timezone name:20120113T110000 END:VEVENT END:VCALENDAR HI; $validator = new Sabre_CalDAV_CalendarQueryValidator(); $filters = array('name' => 'VCALENDAR', 'comp-filters' => array(array('name' => 'VEVENT', 'comp-filters' => array(), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => array('start' => new DateTime('2012-01-13 10:30:00 GMT-08:00'), 'end' => new DateTime('2012-01-13 10:30:00 GMT-08:00')))), 'prop-filters' => array()); $input = Sabre_VObject_Reader::read($input); $this->assertTrue($validator->validate($input, $filters)); }
function testFlaw() { $input = <<<HI BEGIN:VCALENDAR PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN VERSION:2.0 BEGIN:VTIMEZONE TZID:Asia/Pyongyang X-LIC-LOCATION:Asia/Pyongyang BEGIN:STANDARD TZOFFSETFROM:+0900 TZOFFSETTO:+0900 TZNAME:KST DTSTART:19700101T000000 END:STANDARD END:VTIMEZONE BEGIN:VEVENT CREATED:20111118T010857Z LAST-MODIFIED:20111118T010937Z DTSTAMP:20111118T010937Z UID:a03245b3-9947-9a48-a088-863c74e0fdd8 SUMMARY:New Event RRULE:FREQ=YEARLY DTSTART;TZID=Asia/Pyongyang:19960102T111500 DTEND;TZID=Asia/Pyongyang:19960102T121500 END:VEVENT END:VCALENDAR HI; $validator = new Sabre_CalDAV_CalendarQueryValidator(); $filters = array('name' => 'VCALENDAR', 'comp-filters' => array(array('name' => 'VEVENT', 'comp-filters' => array(), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => array('start' => new DateTime('2011-12-01'), 'end' => new DateTime('2012-02-01')))), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => null); $input = VObject\Reader::read($input); $this->assertTrue($validator->validate($input, $filters)); }
function testAlarmWayBefore() { $vevent = Sabre_VObject_Component::create('VEVENT'); $vevent->DTSTART = '20120101T120000Z'; $vevent->UID = 'bla'; $valarm = Sabre_VObject_Component::create('VALARM'); $valarm->TRIGGER = '-P2W1D'; $vevent->add($valarm); $vcalendar = Sabre_VObject_Component::create('VCALENDAR'); $vcalendar->add($vevent); $filter = array('name' => 'VCALENDAR', 'is-not-defined' => false, 'time-range' => null, 'prop-filters' => array(), 'comp-filters' => array(array('name' => 'VEVENT', 'is-not-defined' => false, 'time-range' => null, 'prop-filters' => array(), 'comp-filters' => array(array('name' => 'VALARM', 'is-not-defined' => false, 'prop-filters' => array(), 'comp-filters' => array(), 'time-range' => array('start' => new DateTime('2011-12-10'), 'end' => new DateTime('2011-12-20'))))))); $validator = new Sabre_CalDAV_CalendarQueryValidator(); $this->assertTrue($validator->validate($vcalendar, $filter)); }
/** * @dataProvider provider */ function testValid($icalObject, $filters, $outcome) { $validator = new Sabre_CalDAV_CalendarQueryValidator(); // Wrapping filter in a VCALENDAR component filter, as this is always // there anyway. $filters = array('name' => 'VCALENDAR', 'comp-filters' => array($filters), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => null); $vObject = Sabre_VObject_Reader::read($icalObject); switch ($outcome) { case 0: $this->assertFalse($validator->validate($vObject, $filters)); break; case 1: $this->assertTrue($validator->validate($vObject, $filters)); break; case -1: try { $validator->validate($vObject, $filters); } catch (Sabre_DAV_Exception $e) { // Success } break; } }
/** * This function handles the calendar-query REPORT * * This report is used by clients to request calendar objects based on * complex conditions. * * @param DOMNode $dom * @return void */ public function calendarQueryReport($dom) { $parser = new Sabre_CalDAV_CalendarQueryParser($dom); $parser->parse(); $node = $this->server->tree->getNodeForPath($this->server->getRequestUri()); $depth = $this->server->getHTTPDepth(0); // The default result is an empty array $result = array(); // The calendarobject was requested directly. In this case we handle // this locally. if ($depth == 0 && $node instanceof Sabre_CalDAV_ICalendarObject) { $requestedCalendarData = true; $requestedProperties = $parser->requestedProperties; if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) { // We always retrieve calendar-data, as we need it for filtering. $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data'; // If calendar-data wasn't explicitly requested, we need to remove // it after processing. $requestedCalendarData = false; } $properties = $this->server->getPropertiesForPath($this->server->getRequestUri(), $requestedProperties, 0); // This array should have only 1 element, the first calendar // object. $properties = current($properties); // If there wasn't any calendar-data returned somehow, we ignore // this. if (isset($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) { $validator = new Sabre_CalDAV_CalendarQueryValidator(); $vObject = Sabre_VObject_Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); if ($validator->validate($vObject, $parser->filters)) { // If the client didn't require the calendar-data property, // we won't give it back. if (!$requestedCalendarData) { unset($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); } else { if ($parser->expand) { $vObject->expand($parser->expand['start'], $parser->expand['end']); $properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); } } $result = array($properties); } } } // If we're dealing with a calendar, the calendar itself is responsible // for the calendar-query. if ($node instanceof Sabre_CalDAV_ICalendar && ($depth = 1)) { $nodePaths = $node->calendarQuery($parser->filters); foreach ($nodePaths as $path) { list($properties) = $this->server->getPropertiesForPath($this->server->getRequestUri() . '/' . $path, $parser->requestedProperties); if ($parser->expand) { // We need to do some post-processing $vObject = Sabre_VObject_Reader::read($properties[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); $vObject->expand($parser->expand['start'], $parser->expand['end']); $properties[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); } $result[] = $properties; } } $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($result)); }
/** * This method validates if a filters (as passed to calendarQuery) matches * the given object. * * @param array $object * @param array $filter * @return bool */ protected function validateFilterForObject(array $object, array $filters) { // Unfortunately, setting the 'calendardata' here is optional. If // it was excluded, we actually need another call to get this as // well. if (!isset($object['calendardata'])) { $object = $this->getCalendarObject($object['calendarid'], $object['uri']); } $vObject = VObject\Reader::read($object['calendardata']); $validator = new Sabre_CalDAV_CalendarQueryValidator(); return $validator->validate($vObject, $filters); }
/** * This function handles the calendar-query REPORT * * This report is used by clients to request calendar objects based on * complex conditions. * * @param DOMNode $dom * @return void */ public function calendarQueryReport($dom) { $parser = new Sabre_CalDAV_CalendarQueryParser($dom); $parser->parse(); $requestedCalendarData = true; $requestedProperties = $parser->requestedProperties; if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar-data', $requestedProperties)) { // We always retrieve calendar-data, as we need it for filtering. $requestedProperties[] = '{urn:ietf:params:xml:ns:caldav}calendar-data'; // If calendar-data wasn't explicitly requested, we need to remove // it after processing. $requestedCalendarData = false; } // These are the list of nodes that potentially match the requirement $candidateNodes = $this->server->getPropertiesForPath($this->server->getRequestUri(), $requestedProperties, $this->server->getHTTPDepth(0)); $verifiedNodes = array(); $validator = new Sabre_CalDAV_CalendarQueryValidator(); foreach ($candidateNodes as $node) { // If the node didn't have a calendar-data property, it must not be a calendar object if (!isset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data'])) { continue; } $vObject = Sabre_VObject_Reader::read($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); if ($validator->validate($vObject, $parser->filters)) { if (!$requestedCalendarData) { unset($node[200]['{urn:ietf:params:xml:ns:caldav}calendar-data']); } if ($parser->expand) { $vObject->expand($parser->expand['start'], $parser->expand['end']); $node[200]['{' . self::NS_CALDAV . '}calendar-data'] = $vObject->serialize(); } $verifiedNodes[] = $node; } } $this->server->httpResponse->sendStatus(207); $this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8'); $this->server->httpResponse->sendBody($this->server->generateMultiStatus($verifiedNodes)); }