Example #1
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param Xml\Request\FreeBusyQueryReport $report
  * @return void
  */
 protected function freeBusyQueryReport(Xml\Request\FreeBusyQueryReport $report)
 {
     $uri = $this->server->getRequestUri();
     $acl = $this->server->getPlugin('acl');
     if ($acl) {
         $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     }
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof ICalendar) {
         throw new DAV\Exception\NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     $tzProp = '{' . self::NS_CALDAV . '}calendar-timezone';
     // Figuring out the default timezone for the calendar, for floating
     // times.
     $calendarProps = $this->server->getProperties($uri, [$tzProp]);
     if (isset($calendarProps[$tzProp])) {
         $vtimezoneObj = VObject\Reader::read($calendarProps[$tzProp]);
         $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();
     } else {
         $calendarTimeZone = new DateTimeZone('UTC');
     }
     // Doing a calendar-query first, to make sure we get the most
     // performance.
     $urls = $calendar->calendarQuery(['name' => 'VCALENDAR', 'comp-filters' => [['name' => 'VEVENT', 'comp-filters' => [], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => ['start' => $report->start, 'end' => $report->end]]], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => null]);
     $objects = array_map(function ($url) use($calendar) {
         $obj = $calendar->getChild($url)->get();
         return $obj;
     }, $urls);
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($report->start, $report->end);
     $generator->setTimeZone($calendarTimeZone);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->setStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->setBody($result);
 }
Example #2
0
 /**
  * Returns free-busy information for a specific address. The returned
  * data is an array containing the following properties:
  *
  * calendar-data : A VFREEBUSY VObject
  * request-status : an iTip status code.
  * href: The principal's email address, as requested
  *
  * The following request status codes may be returned:
  *   * 2.0;description
  *   * 3.7;description
  *
  * @param string $email address
  * @param \DateTime $start
  * @param \DateTime $end
  * @param VObject\Component $request
  * @return array
  */
 protected function getFreeBusyForEmail($email, \DateTime $start, \DateTime $end, VObject\Component $request)
 {
     $caldavNS = '{' . Plugin::NS_CALDAV . '}';
     $aclPlugin = $this->server->getPlugin('acl');
     if (substr($email, 0, 7) === 'mailto:') {
         $email = substr($email, 7);
     }
     $result = $aclPlugin->principalSearch(['{http://sabredav.org/ns}email-address' => $email], ['{DAV:}principal-URL', $caldavNS . 'calendar-home-set', '{http://sabredav.org/ns}email-address']);
     if (!count($result)) {
         return ['request-status' => '3.7;Could not find principal', 'href' => 'mailto:' . $email];
     }
     if (!isset($result[0][200][$caldavNS . 'calendar-home-set'])) {
         return ['request-status' => '3.7;No calendar-home-set property found', 'href' => 'mailto:' . $email];
     }
     $homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref();
     // Grabbing the calendar list
     $objects = [];
     foreach ($this->server->tree->getNodeForPath($homeSet)->getChildren() as $node) {
         if (!$node instanceof ICalendar) {
             continue;
         }
         $sct = $caldavNS . 'schedule-calendar-transp';
         $ctz = $caldavNS . 'calendar-timezone';
         $props = $node->getProperties([$sct, $ctz]);
         if (isset($props[$sct]) && $props[$sct]->getValue() == ScheduleCalendarTransp::TRANSPARENT) {
             // If a calendar is marked as 'transparent', it means we must
             // ignore it for free-busy purposes.
             continue;
         }
         $aclPlugin->checkPrivileges($homeSet . $node->getName(), $caldavNS . 'read-free-busy');
         if (isset($props[$ctz])) {
             $vtimezoneObj = VObject\Reader::read($props[$ctz]);
             $calendarTimeZone = $vtimezoneObj->VTIMEZONE->getTimeZone();
         } else {
             $calendarTimeZone = new DateTimeZone('UTC');
         }
         // Getting the list of object uris within the time-range
         $urls = $node->calendarQuery(['name' => 'VCALENDAR', 'comp-filters' => [['name' => 'VEVENT', 'comp-filters' => [], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => ['start' => $start, 'end' => $end]]], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => null]);
         $calObjects = array_map(function ($url) use($node) {
             $obj = $node->getChild($url)->get();
             return $obj;
         }, $urls);
         $objects = array_merge($objects, $calObjects);
     }
     $vcalendar = new VObject\Component\VCalendar();
     $vcalendar->METHOD = 'REPLY';
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $generator->setBaseObject($vcalendar);
     $generator->setTimeZone($calendarTimeZone);
     $result = $generator->getResult();
     $vcalendar->VFREEBUSY->ATTENDEE = 'mailto:' . $email;
     $vcalendar->VFREEBUSY->UID = (string) $request->VFREEBUSY->UID;
     $vcalendar->VFREEBUSY->ORGANIZER = clone $request->VFREEBUSY->ORGANIZER;
     return ['calendar-data' => $result, 'request-status' => '2.0;Success', 'href' => 'mailto:' . $email];
 }
Example #3
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param \DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(\DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = DAV\XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = VObject\DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = VObject\DateTimeParser::parseDateTime($end);
     }
     if (!$start && !$end) {
         throw new DAV\Exception\BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if (!$acl) {
         throw new DAV\Exception('The ACL plugin must be loaded for free-busy queries to work');
     }
     $uri = $this->server->getRequestUri();
     $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof ICalendar) {
         throw new DAV\Exception\NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     // Doing a calendar-query first, to make sure we get the most
     // performance.
     $urls = $calendar->calendarQuery(['name' => 'VCALENDAR', 'comp-filters' => [['name' => 'VEVENT', 'comp-filters' => [], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => ['start' => $start, 'end' => $end]]], 'prop-filters' => [], 'is-not-defined' => false, 'time-range' => null]);
     $objects = array_map(function ($url) use($calendar) {
         $obj = $calendar->getChild($url)->get();
         return $obj;
     }, $urls);
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->setStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->setBody($result);
 }
Example #4
0
 /**
  * Returns free-busy information for a specific address. The returned
  * data is an array containing the following properties:
  *
  * calendar-data : A VFREEBUSY VObject
  * request-status : an iTip status code.
  * href: The principal's email address, as requested
  *
  * The following request status codes may be returned:
  *   * 2.0;description
  *   * 3.7;description
  *
  * @param string $email address
  * @param \DateTime $start
  * @param \DateTime $end
  * @param VObject\Component $request
  * @return array
  */
 protected function getFreeBusyForEmail($email, \DateTime $start, \DateTime $end, VObject\Component $request)
 {
     $caldavNS = '{' . Plugin::NS_CALDAV . '}';
     $aclPlugin = $this->server->getPlugin('acl');
     if (substr($email, 0, 7) === 'mailto:') {
         $email = substr($email, 7);
     }
     $result = $aclPlugin->principalSearch(array('{http://sabredav.org/ns}email-address' => $email), array('{DAV:}principal-URL', $caldavNS . 'calendar-home-set', '{http://sabredav.org/ns}email-address'));
     if (!count($result)) {
         return array('request-status' => '3.7;Could not find principal', 'href' => 'mailto:' . $email);
     }
     if (!isset($result[0][200][$caldavNS . 'calendar-home-set'])) {
         return array('request-status' => '3.7;No calendar-home-set property found', 'href' => 'mailto:' . $email);
     }
     $homeSet = $result[0][200][$caldavNS . 'calendar-home-set']->getHref();
     // Grabbing the calendar list
     $objects = array();
     foreach ($this->server->tree->getNodeForPath($homeSet)->getChildren() as $node) {
         if (!$node instanceof ICalendar) {
             continue;
         }
         $aclPlugin->checkPrivileges($homeSet . $node->getName(), $caldavNS . 'read-free-busy');
         // Getting the list of object uris within the time-range
         $urls = $node->calendarQuery(array('name' => 'VCALENDAR', 'comp-filters' => array(array('name' => 'VEVENT', 'comp-filters' => array(), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => array('start' => $start, 'end' => $end))), 'prop-filters' => array(), 'is-not-defined' => false, 'time-range' => null));
         $calObjects = array_map(function ($url) use($node) {
             $obj = $node->getChild($url)->get();
             return $obj;
         }, $urls);
         $objects = array_merge($objects, $calObjects);
     }
     $vcalendar = VObject\Component::create('VCALENDAR');
     $vcalendar->VERSION = '2.0';
     $vcalendar->METHOD = 'REPLY';
     $vcalendar->CALSCALE = 'GREGORIAN';
     $vcalendar->PRODID = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN';
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $generator->setBaseObject($vcalendar);
     $result = $generator->getResult();
     $vcalendar->VFREEBUSY->ATTENDEE = 'mailto:' . $email;
     $vcalendar->VFREEBUSY->UID = (string) $request->VFREEBUSY->UID;
     $vcalendar->VFREEBUSY->ORGANIZER = clone $request->VFREEBUSY->ORGANIZER;
     return array('calendar-data' => $result, 'request-status' => '2.0;Success', 'href' => 'mailto:' . $email);
 }
Example #5
0
 /**
  * This method is responsible for parsing the request and generating the
  * response for the CALDAV:free-busy-query REPORT.
  *
  * @param DOMNode $dom
  * @return void
  */
 protected function freeBusyQueryReport(DOMNode $dom)
 {
     $start = null;
     $end = null;
     foreach ($dom->firstChild->childNodes as $childNode) {
         $clark = Sabre_DAV_XMLUtil::toClarkNotation($childNode);
         if ($clark == '{' . self::NS_CALDAV . '}time-range') {
             $start = $childNode->getAttribute('start');
             $end = $childNode->getAttribute('end');
             break;
         }
     }
     if ($start) {
         $start = VObject\DateTimeParser::parseDateTime($start);
     }
     if ($end) {
         $end = VObject\DateTimeParser::parseDateTime($end);
     }
     if (!$start && !$end) {
         throw new Sabre_DAV_Exception_BadRequest('The freebusy report must have a time-range filter');
     }
     $acl = $this->server->getPlugin('acl');
     if (!$acl) {
         throw new Sabre_DAV_Exception('The ACL plugin must be loaded for free-busy queries to work');
     }
     $uri = $this->server->getRequestUri();
     $acl->checkPrivileges($uri, '{' . self::NS_CALDAV . '}read-free-busy');
     $calendar = $this->server->tree->getNodeForPath($uri);
     if (!$calendar instanceof Sabre_CalDAV_ICalendar) {
         throw new Sabre_DAV_Exception_NotImplemented('The free-busy-query REPORT is only implemented on calendars');
     }
     $objects = array_map(function ($child) {
         $obj = $child->get();
         if (is_resource($obj)) {
             $obj = stream_get_contents($obj);
         }
         return $obj;
     }, $calendar->getChildren());
     $generator = new VObject\FreeBusyGenerator();
     $generator->setObjects($objects);
     $generator->setTimeRange($start, $end);
     $result = $generator->getResult();
     $result = $result->serialize();
     $this->server->httpResponse->sendStatus(200);
     $this->server->httpResponse->setHeader('Content-Type', 'text/calendar');
     $this->server->httpResponse->setHeader('Content-Length', strlen($result));
     $this->server->httpResponse->sendBody($result);
 }