Beispiel #1
0
 /**
  * Updates the VCard-formatted object 
  * 
  * @param string $cardData 
  * @return void 
  */
 public function put($cardData)
 {
     if (is_resource($cardData)) {
         $cardData = stream_get_contents($cardData);
     }
     // Converting to UTF-8, if needed
     $cardData = Sabre_DAV_StringUtil::ensureUTF8($cardData);
     $this->carddavBackend->updateCard($this->addressBookInfo['id'], $this->cardData['uri'], $cardData);
     $this->cardData['carddata'] = $cardData;
 }
 /**
  * Updates the ICalendar-formatted object 
  * 
  * @param string $calendarData 
  * @return void 
  */
 public function put($calendarData)
 {
     if (is_resource($calendarData)) {
         $calendarData = stream_get_contents($calendarData);
     }
     // Converting to UTF-8, if needed
     $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData);
     $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set'];
     if ($supportedComponents) {
         $supportedComponents = $supportedComponents->getValue();
     } else {
         $supportedComponents = null;
     }
     Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents);
     $this->caldavBackend->updateCalendarObject($this->calendarInfo['id'], $this->objectData['uri'], $calendarData);
     $this->objectData['calendardata'] = $calendarData;
 }
Beispiel #3
0
 /**
  * Checks if the submitted vCard data is in fact, valid.
  *
  * An exception is thrown if it's not.
  *
  * @param resource|string $data
  * @return void
  */
 protected function validateVCard(&$data)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     // Converting the data to unicode, if needed.
     $data = \Sabre_DAV_StringUtil::ensureUTF8($data);
     //\OCP\Util::writeLog('contacts', __METHOD__ . "\n".$data, \OCP\Util::DEBUG);
     try {
         $vobj = VObject\Reader::read($data, VObject\Reader::OPTION_IGNORE_INVALID_LINES);
     } catch (VObject\ParseException $e) {
         throw new \Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage());
     }
     if ($vobj->name !== 'VCARD') {
         throw new \Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support vcard objects.');
     }
     $vobj->validate(VCard::REPAIR | VCard::UPGRADE);
     $data = $vobj->serialize();
 }
Beispiel #4
0
 /**
  * Validates if a text-filter can be applied to a specific property.
  *
  * @param array $texts
  * @param array $filters
  * @param string $test
  * @return bool
  */
 protected function validateTextMatches(array $texts, array $filters, $test)
 {
     foreach ($filters as $filter) {
         $success = false;
         foreach ($texts as $haystack) {
             $success = Sabre_DAV_StringUtil::textMatch($haystack, $filter['value'], $filter['collation'], $filter['match-type']);
             // Breaking on the first match
             if ($success) {
                 break;
             }
         }
         if ($filter['negate-condition']) {
             $success = !$success;
         }
         if ($success && $test === 'anyof') {
             return true;
         }
         if (!$success && $test == 'allof') {
             return false;
         }
     }
     // If we got all the way here, it means we haven't been able to
     // determine early if the test failed or not.
     //
     // This implies for 'anyof' that the test failed, and for 'allof' that
     // we succeeded. Sounds weird, but makes sense.
     return $test === 'allof';
 }
Beispiel #5
0
 /**
  * Creates a new file
  *
  * The contents of the new file must be a valid VCARD
  * 
  * @param string $name 
  * @param resource $vcardData 
  * @return void
  */
 public function createFile($name, $vcardData = null)
 {
     $vcardData = stream_get_contents($vcardData);
     // Converting to UTF-8, if needed
     $vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData);
     $this->carddavBackend->createCard($this->addressBookInfo['id'], $name, $vcardData);
 }
Beispiel #6
0
 /**
  * Checks if the submitted iCalendar data is in fact, valid.
  *
  * An exception is thrown if it's not.
  *
  * @param resource|string $data
  * @return void
  */
 protected function validateICalendar(&$data)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     // Converting the data to unicode, if needed.
     $data = Sabre_DAV_StringUtil::ensureUTF8($data);
     try {
         $vobj = Sabre_VObject_Reader::read($data);
     } catch (Sabre_VObject_ParseException $e) {
         throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
     }
     if ($vobj->name !== 'VCALENDAR') {
         throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.');
     }
     $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 (!isset($component->UID)) {
                         throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID');
                     }
                     $foundUID = (string) $component->UID;
                 } else {
                     if ($foundType !== $component->name) {
                         throw new Sabre_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 Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
                     }
                 }
                 break;
             default:
                 throw new Sabre_DAV_Exception_BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
         }
     }
     if (!$foundType) {
         throw new Sabre_DAV_Exception_BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
     }
 }
Beispiel #7
0
 /**
  * Verify if a list of filters applies to the calendar data object 
  *
  * The calendarData object must be a valid iCalendar blob. The list of 
  * filters must be formatted as parsed by Sabre_CalDAV_Plugin::parseCalendarQueryFilters
  *
  * @param string $calendarData 
  * @param array $filters 
  * @return bool 
  */
 public function validateFilters($calendarData, $filters)
 {
     // We are converting the calendar object to an XML structure
     // This makes it far easier to parse
     $xCalendarData = Sabre_CalDAV_ICalendarUtil::toXCal($calendarData);
     $xml = simplexml_load_string($xCalendarData);
     $xml->registerXPathNamespace('c', 'urn:ietf:params:xml:ns:xcal');
     foreach ($filters as $xpath => $filter) {
         // if-not-defined comes first
         if (isset($filter['is-not-defined'])) {
             if (!$xml->xpath($xpath)) {
                 continue;
             } else {
                 return false;
             }
         }
         $elem = $xml->xpath($xpath);
         if (!$elem) {
             return false;
         }
         $elem = $elem[0];
         if (isset($filter['time-range'])) {
             switch ($elem->getName()) {
                 case 'vevent':
                     $result = $this->validateTimeRangeFilterForEvent($xml, $xpath, $filter);
                     if ($result === false) {
                         return false;
                     }
                     break;
                 case 'vtodo':
                     $result = $this->validateTimeRangeFilterForTodo($xml, $xpath, $filter);
                     if ($result === false) {
                         return false;
                     }
                     break;
                 case 'vjournal':
                 case 'vfreebusy':
                 case 'valarm':
                     // TODO: not implemented
                     break;
                     /*
                     
                                         case 'vjournal' :
                                             $result = $this->validateTimeRangeFilterForJournal($xml,$xpath,$filter);
                                             if ($result===false) return false;
                                             break;
                                         case 'vfreebusy' :
                                             $result = $this->validateTimeRangeFilterForFreeBusy($xml,$xpath,$filter);
                                             if ($result===false) return false;
                                             break;
                                         case 'valarm' :
                                             $result = $this->validateTimeRangeFilterForAlarm($xml,$xpath,$filter);
                                             if ($result===false) return false;
                                             break;
                     */
             }
         }
         if (isset($filter['text-match'])) {
             $currentString = (string) $elem;
             $isMatching = Sabre_DAV_StringUtil::textMatch($currentString, $filter['text-match']['value'], $filter['text-match']['collation']);
             if ($filter['text-match']['negate-condition'] && $isMatching) {
                 return false;
             }
             if (!$filter['text-match']['negate-condition'] && !$isMatching) {
                 return false;
             }
         }
     }
     return true;
 }
Beispiel #8
0
 /**
  * Checks if the submitted iCalendar data is in fact, valid.
  *
  * An exception is thrown if it's not.
  *
  * @param resource|string $data
  * @return void
  */
 protected function validateICalendar(&$data)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     // Converting the data to unicode, if needed.
     $data = Sabre_DAV_StringUtil::ensureUTF8($data);
     try {
         $vobj = Sabre_VObject_Reader::read($data);
     } catch (Sabre_VObject_ParseException $e) {
         throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
     }
 }
 /**
  * This method checks the validity of a text-match.
  *
  * A single text-match should be specified as well as the specific property
  * or parameter we need to validate.
  *
  * @param Sabre_VObject_Node $parent
  * @param array $textMatch
  * @return bool
  */
 protected function validateTextMatch(Sabre_VObject_Node $parent, array $textMatch)
 {
     $value = (string) $parent;
     $isMatching = Sabre_DAV_StringUtil::textMatch($value, $textMatch['value'], $textMatch['collation']);
     return $textMatch['negate-condition'] xor $isMatching;
 }
Beispiel #10
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
  * @return void
  */
 protected function validateICalendar(&$data, $path)
 {
     // If it's a stream, we convert it to a string first.
     if (is_resource($data)) {
         $data = stream_get_contents($data);
     }
     // Converting the data to unicode, if needed.
     $data = Sabre_DAV_StringUtil::ensureUTF8($data);
     try {
         $vobj = VObject\Reader::read($data);
     } catch (VObject\ParseException $e) {
         throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid iCalendar 2.0 data. Parse error: ' . $e->getMessage());
     }
     if ($vobj->name !== 'VCALENDAR') {
         throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.');
     }
     // Get the Supported Components for the target calendar
     list($parentPath, $object) = Sabre_Dav_URLUtil::splitPath($path);
     $calendarProperties = $this->server->getProperties($parentPath, array('{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'));
     $supportedComponents = $calendarProperties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set']->getValue();
     $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 Sabre_CalDAV_Exception_InvalidComponentType('This calendar only supports ' . implode(', ', $supportedComponents) . '. We found a ' . $foundType);
                     }
                     if (!isset($component->UID)) {
                         throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID');
                     }
                     $foundUID = (string) $component->UID;
                 } else {
                     if ($foundType !== $component->name) {
                         throw new Sabre_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 Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
                     }
                 }
                 break;
             default:
                 throw new Sabre_DAV_Exception_BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
         }
     }
     if (!$foundType) {
         throw new Sabre_DAV_Exception_BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
     }
 }
Beispiel #11
0
 /**
  * Creates a new file
  *
  * The contents of the new file must be a valid ICalendar string.
  * 
  * @param string $name 
  * @param resource $calendarData 
  * @return void
  */
 public function createFile($name, $calendarData = null)
 {
     $calendarData = stream_get_contents($calendarData);
     // Converting to UTF-8, if needed
     $calendarData = Sabre_DAV_StringUtil::ensureUTF8($calendarData);
     $supportedComponents = $this->calendarInfo['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set'];
     if ($supportedComponents) {
         $supportedComponents = $supportedComponents->getValue();
     } else {
         $supportedComponents = null;
     }
     Sabre_CalDAV_ICalendarUtil::validateICalendarObject($calendarData, $supportedComponents);
     $this->caldavBackend->createCalendarObject($this->calendarInfo['id'], $name, $calendarData);
 }
Beispiel #12
0
 /**
  * Updates the VCard-formatted object
  *
  * @param string $cardData
  * @return void
  */
 public function put($cardData)
 {
     if (get_class($this->_converter) == 'Calendar_Convert_Event_VCalendar_Generic') {
         if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) {
             Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . " update by generic client not allowed. See Calendat_Convert_Event_VCalendar_Factory for supported clients.");
         }
         throw new Sabre_DAV_Exception_Forbidden('Update denied for unknow client');
     }
     if (is_resource($cardData)) {
         $cardData = stream_get_contents($cardData);
     }
     // Converting to UTF-8, if needed
     $cardData = Sabre_DAV_StringUtil::ensureUTF8($cardData);
     Sabre_CalDAV_ICalendarUtil::validateICalendarObject($cardData, array('VEVENT', 'VFREEBUSY'));
     $vobject = Calendar_Convert_Event_VCalendar_Abstract::getVcal($cardData);
     foreach ($vobject->children() as $component) {
         if (isset($component->{'X-TINE20-CONTAINER'})) {
             $xContainerId = $component->{'X-TINE20-CONTAINER'};
             break;
         }
     }
     // keep old record for reference
     $recordBeforeUpdate = clone $this->getRecord();
     $event = $this->_converter->toTine20Model($vobject, $this->getRecord());
     // iCal does sends back an old value, because it does not refresh the vcalendar after
     // update. Therefor we must reapply the value of last_modified_time after the convert
     $event->last_modified_time = $recordBeforeUpdate->last_modified_time;
     $currentContainer = Tinebase_Container::getInstance()->getContainerById($this->getRecord()->container_id);
     $ownAttendee = Calendar_Model_Attender::getOwnAttender($this->getRecord()->attendee);
     // event 'belongs' current user -> allow container move
     if ($currentContainer->isPersonalOf(Tinebase_Core::getUser())) {
         $event->container_id = $this->_container->getId();
     } else {
         if (isset($xContainerId)) {
             if ($xContainerId == $currentContainer->getId()) {
                 $event->container_id = $this->_container->getId();
             } else {
                 // @TODO allow organizer to move original cal when he edits the displaycal event?
                 if ($ownAttendee && $this->_container->type == Tinebase_Model_Container::TYPE_PERSONAL) {
                     $ownAttendee->displaycontainer_id = $this->_container->getId();
                 }
             }
         } else {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " X-TINE20-CONTAINER not present -> restrict container moves");
             }
             if ($ownAttendee && $this->_container->type == Tinebase_Model_Container::TYPE_PERSONAL) {
                 if ($ownAttendee->displaycontainer_id == $currentContainer->getId()) {
                     $event->container_id = $this->_container->getId();
                 }
                 $ownAttendee->displaycontainer_id = $this->_container->getId();
             }
         }
     }
     self::enforceEventParameters($event);
     // don't allow update of alarms for non organizer if oganizer is Tine 2.0 user
     if ($event->organizer !== Tinebase_Core::getUser()->contact_id) {
         $organizerContact = Addressbook_Controller_Contact::getInstance()->get($event->organizer);
         // reset alarms if organizer is Tine 2.0 user
         if (!empty($organizerContact->account_id)) {
             $this->_resetAlarms($event, $recordBeforeUpdate);
         }
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . print_r($event->toArray(), true));
     }
     try {
         $this->_event = Calendar_Controller_MSEventFacade::getInstance()->update($event);
     } catch (Tinebase_Timemachine_Exception_ConcurrencyConflict $ttecc) {
         throw new Sabre_DAV_Exception_PreconditionFailed('An If-Match header was specified, but none of the specified the ETags matched.', 'If-Match');
     }
     // avoid sending headers during unit tests
     if (php_sapi_name() != 'cli') {
         // @todo this belong to DAV_Server, but it currently not supported
         header('ETag: ' . $this->getETag());
     }
 }