Example #1
0
 /**
  * Sends one or more iTip messages through email.
  *
  * @param string $originator Originator Email
  * @param array $recipients Array of email addresses
  * @param VObject\Component $vObject
  * @param string $principal Principal Url of the originator
  * @return void
  */
 public function sendMessage($originator, array $recipients, VObject\Component $vObject, $principal)
 {
     foreach ($recipients as $recipient) {
         $to = $recipient;
         $replyTo = $originator;
         $subject = 'SabreDAV iTIP message';
         switch (strtoupper($vObject->METHOD)) {
             case 'REPLY':
                 $subject = 'Response for: ' . $vObject->VEVENT->SUMMARY;
                 break;
             case 'REQUEST':
                 $subject = 'Invitation for: ' . $vObject->VEVENT->SUMMARY;
                 break;
             case 'CANCEL':
                 $subject = 'Cancelled event: ' . $vObject->VEVENT->SUMMARY;
                 break;
         }
         $headers = array();
         $headers[] = 'Reply-To: ' . $replyTo;
         $headers[] = 'From: ' . $this->senderEmail;
         $headers[] = 'Content-Type: text/calendar; method=' . (string) $vObject->method . '; charset=utf-8';
         if (DAV\Server::$exposeVersion) {
             $headers[] = 'X-Sabre-Version: ' . DAV\Version::VERSION . '-' . DAV\Version::STABILITY;
         }
         $vcalBody = $vObject->serialize();
         $this->mail($to, $subject, $vcalBody, $headers);
     }
 }
Example #2
0
 private function getValueOrEmpty(\Sabre\VObject\Component $component, $property)
 {
     $value = $component->__get($property);
     if ($value) {
         return $value->getValue();
     } else {
         return '';
     }
 }
Example #3
0
 /**
  * Constructor
  *
  * The splitter should receive an readable file stream as it's input.
  *
  * @param resource $input
  */
 public function __construct($input)
 {
     $data = VObject\Reader::read(stream_get_contents($input));
     $vtimezones = array();
     $components = array();
     foreach ($data->children as $component) {
         if (!$component instanceof VObject\Component) {
             continue;
         }
         // Get all timezones
         if ($component->name === 'VTIMEZONE') {
             $this->vtimezones[(string) $component->TZID] = $component;
             continue;
         }
         // Get component UID for recurring Events search
         if ($component->UID) {
             $uid = (string) $component->UID;
         } else {
             // Generating a random UID
             $uid = sha1(microtime()) . '-vobjectimport';
         }
         // Take care of recurring events
         if (!array_key_exists($uid, $this->objects)) {
             $this->objects[$uid] = VObject\Component::create('VCALENDAR');
         }
         $this->objects[$uid]->add(clone $component);
     }
 }
 /**
  * Different bug, also likely an infinite loop.
  */
 function testYearlyByMonthLoop()
 {
     $ev = Component::create('VEVENT');
     $ev->UID = 'uuid';
     $ev->DTSTART = '20120101T154500';
     $ev->DTSTART['TZID'] = 'Europe/Berlin';
     $ev->RRULE = 'FREQ=YEARLY;INTERVAL=1;UNTIL=20120203T225959Z;BYMONTH=2;BYSETPOS=1;BYDAY=SU,MO,TU,WE,TH,FR,SA';
     $ev->DTEND = '20120101T164500';
     $ev->DTEND['TZID'] = 'Europe/Berlin';
     // This recurrence rule by itself is a yearly rule that should happen
     // every february.
     //
     // The BYDAY part expands this to every day of the month, but the
     // BYSETPOS limits this to only the 1st day of the month. Very crazy
     // way to specify this, and could have certainly been a lot easier.
     $cal = Component::create('VCALENDAR');
     $cal->add($ev);
     $it = new RecurrenceIterator($cal, 'uuid');
     $it->fastForward(new DateTime('2012-01-29 23:00:00', new DateTimeZone('UTC')));
     $collect = array();
     while ($it->valid()) {
         $collect[] = $it->getDTSTART();
         if ($it->getDTSTART() > new DateTime('2013-02-05 22:59:59', new DateTimeZone('UTC'))) {
             break;
         }
         $it->next();
     }
     $this->assertEquals(array(new DateTime('2012-02-01 15:45:00', new DateTimeZone('Europe/Berlin'))), $collect);
 }
Example #5
0
 /**
  * Serializes a xCal or xCard object.
  *
  * @param Component $component
  *
  * @return string
  */
 static function writeXml(Component $component)
 {
     $writer = new Xml\Writer();
     $writer->openMemory();
     $writer->setIndent(true);
     $writer->startDocument('1.0', 'utf-8');
     if ($component instanceof Component\VCalendar) {
         $writer->startElement('icalendar');
         $writer->writeAttribute('xmlns', Parser\Xml::XCAL_NAMESPACE);
     } else {
         $writer->startElement('vcards');
         $writer->writeAttribute('xmlns', Parser\Xml::XCARD_NAMESPACE);
     }
     $component->xmlSerialize($writer);
     $writer->endElement();
     return $writer->outputMemory();
 }
 /**
  * Validates the node for correctness.
  *
  * The following options are supported:
  *   Node::REPAIR - May attempt to automatically repair the problem.
  *   Node::PROFILE_CARDDAV - validate the vCard for CardDAV purposes.
  *   Node::PROFILE_CALDAV - validate the iCalendar for CalDAV purposes.
  *
  * This method returns an array with detected problems.
  * Every element has the following properties:
  *
  *  * level - problem level.
  *  * message - A human-readable string describing the issue.
  *  * node - A reference to the problematic node.
  *
  * The level means:
  *   1 - The issue was repaired (only happens if REPAIR was turned on).
  *   2 - A warning.
  *   3 - An error.
  *
  * @param int $options
  * @return array
  */
 function validate($options = 0)
 {
     $result = parent::validate($options);
     if (isset($this->DTEND) && isset($this->DURATION)) {
         $result[] = array('level' => 3, 'message' => 'DTEND and DURATION cannot both be present', 'node' => $this);
     }
     return $result;
 }
Example #7
0
 /**
  * Validates the node for correctness.
  *
  * The following options are supported:
  *   Node::REPAIR - May attempt to automatically repair the problem.
  *   Node::PROFILE_CARDDAV - Validate the vCard for CardDAV purposes.
  *   Node::PROFILE_CALDAV - Validate the iCalendar for CalDAV purposes.
  *
  * This method returns an array with detected problems.
  * Every element has the following properties:
  *
  *  * level - problem level.
  *  * message - A human-readable string describing the issue.
  *  * node - A reference to the problematic node.
  *
  * The level means:
  *   1 - The issue was repaired (only happens if REPAIR was turned on).
  *   2 - A warning.
  *   3 - An error.
  *
  * @param int $options
  *
  * @return array
  */
 function validate($options = 0)
 {
     $result = parent::validate($options);
     if (isset($this->DTEND) && isset($this->DURATION)) {
         $result[] = ['level' => 3, 'message' => 'DTEND and DURATION cannot both be present', 'node' => $this];
     }
     if (isset($this->DURATION) && !isset($this->DTSTART)) {
         $result[] = ['level' => 3, 'message' => 'DURATION must be declared with a DTSTART.', 'node' => $this];
     }
     return $result;
 }
 /**
  * Something, somewhere produced an ics with an interval set to 0. Because
  * this means we increase the current day (or week, month) by 0, this also
  * results in an infinite loop.
  *
  * @expectedException InvalidArgumentException
  * @return void
  */
 function testZeroInterval()
 {
     $ev = Component::create('VEVENT');
     $ev->UID = 'uuid';
     $ev->DTSTART = '20120824T145700Z';
     $ev->RRULE = 'FREQ=YEARLY;INTERVAL=0';
     $cal = Component::create('VCALENDAR');
     $cal->add($ev);
     $it = new RecurrenceIterator($cal, 'uuid');
     $it->fastForward(new DateTime('2013-01-01 23:00:00', new DateTimeZone('UTC')));
     // if we got this far.. it means we are no longer infinitely looping
 }
 function testAlarmWayBefore()
 {
     $vevent = VObject\Component::create('VEVENT');
     $vevent->DTSTART = '20120101T120000Z';
     $vevent->UID = 'bla';
     $valarm = VObject\Component::create('VALARM');
     $valarm->TRIGGER = '-P2W1D';
     $vevent->add($valarm);
     $vcalendar = 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));
 }
 /**
  * Merges all calendar objects, and builds one big ics export
  *
  * @param array $nodes
  * @return string
  */
 public function generateICS(array $nodes)
 {
     $calendar = new VObject\Component('vcalendar');
     $calendar->version = '2.0';
     if (Sabre_DAV_Server::$exposeVersion) {
         $calendar->prodid = '-//SabreDAV//SabreDAV ' . Sabre_DAV_Version::VERSION . '//EN';
     } else {
         $calendar->prodid = '-//SabreDAV//SabreDAV//EN';
     }
     $calendar->calscale = 'GREGORIAN';
     $collectedTimezones = array();
     $timezones = array();
     $objects = array();
     foreach ($nodes as $node) {
         if (!isset($node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'])) {
             continue;
         }
         $nodeData = $node[200]['{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}calendar-data'];
         $nodeComp = VObject\Reader::read($nodeData);
         foreach ($nodeComp->children() as $child) {
             switch ($child->name) {
                 case 'VEVENT':
                 case 'VTODO':
                 case 'VJOURNAL':
                     $objects[] = $child;
                     break;
                     // VTIMEZONE is special, because we need to filter out the duplicates
                 // VTIMEZONE is special, because we need to filter out the duplicates
                 case 'VTIMEZONE':
                     // Naively just checking tzid.
                     if (in_array((string) $child->TZID, $collectedTimezones)) {
                         continue;
                     }
                     $timezones[] = $child;
                     $collectedTimezones[] = $child->TZID;
                     break;
             }
         }
     }
     foreach ($timezones as $tz) {
         $calendar->add($tz);
     }
     foreach ($objects as $obj) {
         $calendar->add($obj);
     }
     return $calendar->serialize();
 }
Example #11
0
 public function timeRangeTestData()
 {
     $tests = array();
     $vjournal = Component::create('VJOURNAL');
     $vjournal->DTSTART = '20111223T120000Z';
     $tests[] = array($vjournal, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vjournal, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vjournal2 = Component::create('VJOURNAL');
     $vjournal2->DTSTART = '20111223';
     $vjournal2->DTSTART['VALUE'] = 'DATE';
     $tests[] = array($vjournal2, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vjournal2, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vjournal3 = Component::create('VJOURNAL');
     $tests[] = array($vjournal3, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), false);
     $tests[] = array($vjournal3, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     return $tests;
 }
Example #12
0
 /**
  * @brief transform a ldap entry into an VCard object
  *	for each ldap entry which is like "property: value"
  *	to a VCard entry which is like "PROPERTY[;PARAMETER=param]:value"
  * @param array $ldap_entry
  * @return OC_VCard
  */
 public function ldapToVCard($ldapEntry)
 {
     $vcard = \Sabre\VObject\Component::create('VCARD');
     $vcard->REV = $this->convertDate($ldapEntry['modifytimestamp'][0])->format(\DateTime::W3C);
     //error_log("modifytimestamp: ".$vcard->REV);
     $vcard->{'X-LDAP-DN'} = base64_encode($ldapEntry['dn']);
     // OCP\Util::writeLog('ldap_vcard_connector', __METHOD__.' vcard is '.$vcard->serialize(), \OCP\Util::DEBUG);
     for ($i = 0; $i < $ldapEntry["count"]; $i++) {
         // ldap property name : $ldap_entry[$i]
         $lProperty = $ldapEntry[$i];
         for ($j = 0; $j < $ldapEntry[$lProperty]["count"]; $j++) {
             // What to do :
             // convert the ldap property into vcard property, type and position (if needed)
             // $v_params format: array('property' => property, 'type' => array(types), 'position' => position)
             $v_params = $this->getVCardProperty($lProperty);
             foreach ($v_params as $v_param) {
                 if (isset($v_param['unassigned'])) {
                     // if the value comes from the unassigned entry, it's a vcard property dumped
                     try {
                         $property = \Sabre\VObject\Reader::read($ldapEntry[$lProperty][$j]);
                         $vcard->add($property);
                     } catch (exception $e) {
                     }
                 } else {
                     // Checks if a same kind of property already exists in the VCard (property and parameters)
                     // if so, sets a property variable with the current data
                     // else, creates a property variable
                     $v_property = $this->getOrCreateVCardProperty($vcard, $v_param, $j);
                     // modify the property with the new data
                     if (strcasecmp($v_param['image'], 'true') == 0) {
                         $this->updateVCardImageProperty($v_property, $ldapEntry[$lProperty][$j], $vcard->VERSION);
                     } else {
                         $this->updateVCardProperty($v_property, $ldapEntry[$lProperty][$j], $v_param['position']);
                     }
                 }
             }
         }
     }
     if (!isset($vcard->UID)) {
         $vcard->UID = base64_encode($ldapEntry['dn']);
     }
     return $vcard;
 }
Example #13
0
 /**
  * Validates the node for correctness.
  *
  * The following options are supported:
  *   - Node::REPAIR - If something is broken, and automatic repair may
  *                    be attempted.
  *
  * An array is returned with warnings.
  *
  * Every item in the array has the following properties:
  *    * level - (number between 1 and 3 with severity information)
  *    * message - (human readable message)
  *    * node - (reference to the offending node)
  *
  * @param int $options
  * @return array
  */
 public function validate($options = 0)
 {
     $warnings = array();
     $version = $this->select('VERSION');
     if (count($version) !== 1) {
         $warnings[] = array('level' => 1, 'message' => 'The VERSION property must appear in the VCARD component exactly 1 time', 'node' => $this);
         if ($options & self::REPAIR) {
             $this->VERSION = self::DEFAULT_VERSION;
         }
     } else {
         $version = (string) $this->VERSION;
         if ($version !== '2.1' && $version !== '3.0' && $version !== '4.0') {
             $warnings[] = array('level' => 1, 'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.', 'node' => $this);
             if ($options & self::REPAIR) {
                 $this->VERSION = '4.0';
             }
         }
     }
     $fn = $this->select('FN');
     if (count($fn) !== 1) {
         $warnings[] = array('level' => 1, 'message' => 'The FN property must appear in the VCARD component exactly 1 time', 'node' => $this);
         if ($options & self::REPAIR && count($fn) === 0) {
             // We're going to try to see if we can use the contents of the
             // N property.
             if (isset($this->N)) {
                 $value = explode(';', (string) $this->N);
                 if (isset($value[1]) && $value[1]) {
                     $this->FN = $value[1] . ' ' . $value[0];
                 } else {
                     $this->FN = $value[0];
                 }
                 // Otherwise, the ORG property may work
             } elseif (isset($this->ORG)) {
                 $this->FN = (string) $this->ORG;
             }
         }
     }
     return array_merge(parent::validate($options), $warnings);
 }
Example #14
0
 /**
  * Create online calendar for user
  *
  * @Route("/{username}.ics")
  *
  * @param  string                                    $username User to create the calendar for
  * @return Symfony\Component\HttpFoundation\Response
  */
 public function calendarAction($username)
 {
     $user = $this->get('user_provider')->loadUserByUsername($username);
     $om = $this->getObjectManager('VIB\\FliesBundle\\Entity\\Vial');
     $calendar = VObject\Component::create('VCALENDAR');
     $calendar->VERSION = '2.0';
     $field = 'X-WR-CALNAME';
     $calendar->{$field} = $user->getShortName() . '\'s flywork';
     $stockDates = $om->getRepository('VIB\\FliesBundle\\Entity\\StockVial')->getFlipDates($user);
     foreach ($stockDates as $stockDate) {
         $event = VObject\Component::create('VEVENT');
         $calendar->add($event);
         $event->SUMMARY = 'Transfer stocks';
         $dtstart = VObject\Property::create('DTSTART');
         $dtstart->setDateTime($stockDate, VObject\Property\DateTime::DATE);
         $event->DTSTART = $dtstart;
         $alarm = VObject\Component::create('VALARM');
         $event->add($alarm);
         $alarm->TRIGGER = 'PT8H';
         $alarm->ACTION = 'DISPLAY';
     }
     $crossDates = $om->getRepository('VIB\\FliesBundle\\Entity\\CrossVial')->getFlipDates($user);
     foreach ($crossDates as $crossDate) {
         $crossDates[] = $crossDate;
         $event = VObject\Component::create('VEVENT');
         $calendar->add($event);
         $event->SUMMARY = 'Check crosses';
         $dtstart = VObject\Property::create('DTSTART');
         $dtstart->setDateTime($crossDate, VObject\Property\DateTime::DATE);
         $event->DTSTART = $dtstart;
         $alarm = VObject\Component::create('VALARM');
         $event->add($alarm);
         $alarm->TRIGGER = 'PT8H';
         $alarm->ACTION = 'DISPLAY';
     }
     return new Response($calendar->serialize(), 200, array('Content-Type' => 'text/calendar; charset=utf-8', 'Content-Disposition' => 'inline; filename="calendar.ics"'));
 }
Example #15
0
 public function timeRangeTestData()
 {
     $tests = array();
     $vtodo = Component::create('VTODO');
     $vtodo->DTSTART = '20111223T120000Z';
     $tests[] = array($vtodo, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo2 = clone $vtodo;
     $vtodo2->DURATION = 'P1D';
     $tests[] = array($vtodo2, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo2, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo3 = clone $vtodo;
     $vtodo3->DUE = '20111225';
     $tests[] = array($vtodo3, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo3, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo4 = Component::create('VTODO');
     $vtodo4->DUE = '20111225';
     $tests[] = array($vtodo4, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo4, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo5 = Component::create('VTODO');
     $vtodo5->COMPLETED = '20111225';
     $tests[] = array($vtodo5, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo5, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo6 = Component::create('VTODO');
     $vtodo6->CREATED = '20111225';
     $tests[] = array($vtodo6, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo6, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo7 = Component::create('VTODO');
     $vtodo7->CREATED = '20111225';
     $vtodo7->COMPLETED = '20111226';
     $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), false);
     $vtodo7 = Component::create('VTODO');
     $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2012-01-01'), true);
     $tests[] = array($vtodo7, new \DateTime('2011-01-01'), new \DateTime('2011-11-01'), true);
     return $tests;
 }
Example #16
0
 /**
  * Reads a property or component from a line.
  *
  * @return void
  */
 protected function readProperty($line)
 {
     if ($this->options & self::OPTION_FORGIVING) {
         $propNameToken = 'A-Z0-9\\-\\._\\/';
     } else {
         $propNameToken = 'A-Z0-9\\-\\.';
     }
     $paramNameToken = 'A-Z0-9\\-';
     $safeChar = '^";:,';
     $qSafeChar = '^"';
     $regex = "/\n            ^(?P<name> [{$propNameToken}]+ ) (?=[;:])        # property name\n            |\n            (?<=:)(?P<propValue> .+)\$                      # property value\n            |\n            ;(?P<paramName> [{$paramNameToken}]+) (?=[=;:])  # parameter name\n            |\n            (=|,)(?P<paramValue>                           # parameter value\n                (?: [{$safeChar}]*) |\n                \"(?: [{$qSafeChar}]+)\"\n            ) (?=[;:,])\n            /xi";
     //echo $regex, "\n"; die();
     preg_match_all($regex, $line, $matches, PREG_SET_ORDER);
     $property = ['name' => null, 'parameters' => [], 'value' => null];
     $lastParam = null;
     /**
      * Looping through all the tokens.
      *
      * Note that we are looping through them in reverse order, because if a
      * sub-pattern matched, the subsequent named patterns will not show up
      * in the result.
      */
     foreach ($matches as $match) {
         if (isset($match['paramValue'])) {
             if ($match['paramValue'] && $match['paramValue'][0] === '"') {
                 $value = substr($match['paramValue'], 1, -1);
             } else {
                 $value = $match['paramValue'];
             }
             $value = $this->unescapeParam($value);
             if (is_null($lastParam)) {
                 throw new ParseException('Invalid Mimedir file. Line starting at ' . $this->startLine . ' did not follow iCalendar/vCard conventions');
             }
             if (is_null($property['parameters'][$lastParam])) {
                 $property['parameters'][$lastParam] = $value;
             } elseif (is_array($property['parameters'][$lastParam])) {
                 $property['parameters'][$lastParam][] = $value;
             } else {
                 $property['parameters'][$lastParam] = [$property['parameters'][$lastParam], $value];
             }
             continue;
         }
         if (isset($match['paramName'])) {
             $lastParam = strtoupper($match['paramName']);
             if (!isset($property['parameters'][$lastParam])) {
                 $property['parameters'][$lastParam] = null;
             }
             continue;
         }
         if (isset($match['propValue'])) {
             $property['value'] = $match['propValue'];
             continue;
         }
         if (isset($match['name']) && $match['name']) {
             $property['name'] = strtoupper($match['name']);
             continue;
         }
         // @codeCoverageIgnoreStart
         throw new \LogicException('This code should not be reachable');
         // @codeCoverageIgnoreEnd
     }
     if (is_null($property['value'])) {
         $property['value'] = '';
     }
     if (!$property['name']) {
         if ($this->options & self::OPTION_IGNORE_INVALID_LINES) {
             return false;
         }
         throw new ParseException('Invalid Mimedir file. Line starting at ' . $this->startLine . ' did not follow iCalendar/vCard conventions');
     }
     // vCard 2.1 states that parameters may appear without a name, and only
     // a value. We can deduce the value based on it's name.
     //
     // Our parser will get those as parameters without a value instead, so
     // we're filtering these parameters out first.
     $namedParameters = [];
     $namelessParameters = [];
     foreach ($property['parameters'] as $name => $value) {
         if (!is_null($value)) {
             $namedParameters[$name] = $value;
         } else {
             $namelessParameters[] = $name;
         }
     }
     $propObj = $this->root->createProperty($property['name'], null, $namedParameters);
     foreach ($namelessParameters as $namelessParameter) {
         $propObj->add(null, $namelessParameter);
     }
     if (strtoupper($propObj['ENCODING']) === 'QUOTED-PRINTABLE') {
         $propObj->setQuotedPrintableValue($this->extractQuotedPrintableValue());
     } else {
         $propObj->setRawMimeDirValue($property['value']);
     }
     return $propObj;
 }
 /**
  * add photo data to VCard
  * 
  * @param  Addressbook_Model_Contact $record
  * @param  \Sabre\VObject\Component  $card
  */
 protected function _fromTine20ModelAddPhoto(Addressbook_Model_Contact $record, \Sabre\VObject\Component $card)
 {
     if (!empty($record->jpegphoto)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__);
         try {
             $jpegData = $record->getSmallContactImage($this->_maxPhotoSize);
             $card->add('PHOTO', $jpegData, array('TYPE' => 'JPEG', 'ENCODING' => 'b'));
         } catch (Exception $e) {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Image for contact {$record->getId()} not found or invalid: {$e->getMessage()}");
             }
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString());
             }
         }
     }
 }
	/**
	 * @brief converts a ldif into a owncloud VCard
	 * @param $element the VCard element to convert
	 * @return VCard
	 */
	public function convertElementToVCard($element) {
		$dest = \Sabre\VObject\Component::create('VCARD');
		
		foreach ($element as $ldifProperty) {
			$importEntry = $this->getImportEntry($ldifProperty[0]);
			if ($importEntry) {
				$value = $ldifProperty[1];
				if (isset($importEntry['remove'])) {
					$value = str_replace($importEntry['remove'], '', $ldifProperty[1]);
				}
				$values = array($value);
				if (isset($importEntry['separator'])) {
					$values = explode($importEntry['separator'], $value);
				}
				
				foreach ($values as $oneValue) {
					$this->convertElementToProperty($oneValue, $importEntry, $dest);
				}
			} else {
				$property = \Sabre\VObject\Property::create("X-Unknown-Element", ''.StringUtil::convertToUTF8($ldifProperty[1]));
				$property->parameters[] = new \Sabre\VObject\Parameter('TYPE', ''.StringUtil::convertToUTF8($ldifProperty[0]));
				$dest->add($property);
			}
		}
		
		$dest->validate(\Sabre\VObject\Component\VCard::REPAIR);
		return $dest;
	}
Example #19
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 #20
0
 public static function getBirthdayEvents($parameters)
 {
     $name = $parameters['calendar_id'];
     if (strpos($name, 'birthday_') != 0) {
         return;
     }
     $info = explode('_', $name);
     $aid = $info[1];
     Addressbook::find($aid);
     foreach (VCard::all($aid) as $contact) {
         try {
             $vcard = VObject\Reader::read($contact['carddata']);
         } catch (Exception $e) {
             continue;
         }
         $birthday = $vcard->BDAY;
         if ($birthday) {
             $date = new \DateTime($birthday);
             $vevent = VObject\Component::create('VEVENT');
             //$vevent->setDateTime('LAST-MODIFIED', new DateTime($vcard->REV));
             $vevent->add('DTSTART');
             $vevent->DTSTART->setDateTime($date, VObject\Property\DateTime::DATE);
             $vevent->add('DURATION', 'P1D');
             $vevent->{'UID'} = substr(md5(rand() . time()), 0, 10);
             // DESCRIPTION?
             $vevent->{'RRULE'} = 'FREQ=YEARLY';
             $title = str_replace('{name}', $vcard->FN, App::$l10n->t('{name}\'s Birthday'));
             $parameters['events'][] = array('id' => 0, 'vevent' => $vevent, 'repeating' => true, 'summary' => $title, 'calendardata' => "BEGIN:VCALENDAR\nVERSION:2.0\n" . "PRODID:ownCloud Contacts " . \OCP\App::getAppVersion('contacts') . "\n" . $vevent->serialize() . "END:VCALENDAR");
         }
     }
 }
	/**
	 * @brief converts a VCard into a owncloud VCard
	 * @param $element the VCard element to convert
	 * @return VCard|false
	 */
	public function convertElementToVCard($element) {
		try {
			$source = VObject\Reader::read($element, VObject\Reader::OPTION_FORGIVING);
		} catch (VObject\ParseException $error) {
			return false;
		}
		$dest = \Sabre\VObject\Component::create('VCARD');
		
		foreach ($source->children() as $sourceProperty) {
			$importEntry = $this->getImportEntry($sourceProperty, $source);
			if ($importEntry) {
				$value = $sourceProperty->value;
				if (isset($importEntry['remove'])) {
					$value = str_replace($importEntry['remove'], '', $sourceProperty->value);
				}
				$values = array($value);
				if (isset($importEntry['separator'])) {
					$values = explode($importEntry['separator'], $value);
				}
				
				foreach ($values as $oneValue) {
					if (isset($importEntry->vcard_favourites)) {
						foreach ($importEntry->vcard_favourites as $vcardFavourite) {
							if (strcasecmp((string)$vcardFavourite, trim($oneValue)) == 0) {
								$property = \Sabre\VObject\Property::create("X-FAVOURITES", 'yes');
								$dest->add($property);
							} else {
								$property = $this->getOrCreateVCardProperty($dest, $importEntry->vcard_entry);
								$this->updateProperty($property, $importEntry, trim($oneValue));
							}
						}
					} else {
						$property = $this->getOrCreateVCardProperty($dest, $importEntry->vcard_entry);
						$this->updateProperty($property, $importEntry, $sourceProperty->value);
					}
				}
			} else {
				$property = clone $sourceProperty;
				$dest->add($property);
			}
		}
		
		$dest->validate(\Sabre\VObject\Component\VCard::REPAIR);
		return $dest;
	}
 /**
  * Returns a VTIMEZONE component for a Olson timezone identifier
  * with daylight transitions covering the given date range.
  *
  * @param string Timezone ID as used in PHP's Date functions
  * @param integer Unix timestamp with first date/time in this timezone
  * @param integer Unix timestap with last date/time in this timezone
  *
  * @return mixed A Sabre\VObject\Component object representing a VTIMEZONE definition
  *               or false if no timezone information is available
  */
 public static function get_vtimezone($tzid, $from = 0, $to = 0)
 {
     if (!$from) {
         $from = time();
     }
     if (!$to) {
         $to = $from;
     }
     if (is_string($tzid)) {
         try {
             $tz = new \DateTimeZone($tzid);
         } catch (\Exception $e) {
             return false;
         }
     } else {
         if (is_a($tzid, '\\DateTimeZone')) {
             $tz = $tzid;
         }
     }
     if (!is_a($tz, '\\DateTimeZone')) {
         return false;
     }
     $year = 86400 * 360;
     $transitions = $tz->getTransitions($from - $year, $to + $year);
     $vt = new VObject\Component('VTIMEZONE');
     $vt->TZID = $tz->getName();
     $std = null;
     $dst = null;
     foreach ($transitions as $i => $trans) {
         $cmp = null;
         if ($i == 0) {
             $tzfrom = $trans['offset'] / 3600;
             continue;
         }
         if ($trans['isdst']) {
             $t_dst = $trans['ts'];
             $dst = new VObject\Component('DAYLIGHT');
             $cmp = $dst;
         } else {
             $t_std = $trans['ts'];
             $std = new VObject\Component('STANDARD');
             $cmp = $std;
         }
         if ($cmp) {
             $dt = new DateTime($trans['time']);
             $offset = $trans['offset'] / 3600;
             $cmp->DTSTART = $dt->format('Ymd\\THis');
             $cmp->TZOFFSETFROM = sprintf('%s%02d%02d', $tzfrom >= 0 ? '+' : '', floor($tzfrom), ($tzfrom - floor($tzfrom)) * 60);
             $cmp->TZOFFSETTO = sprintf('%s%02d%02d', $offset >= 0 ? '+' : '', floor($offset), ($offset - floor($offset)) * 60);
             if (!empty($trans['abbr'])) {
                 $cmp->TZNAME = $trans['abbr'];
             }
             $tzfrom = $offset;
             $vt->add($cmp);
         }
         // we covered the entire date range
         if ($std && $dst && min($t_std, $t_dst) < $from && max($t_std, $t_dst) > $to) {
             break;
         }
     }
     // add X-MICROSOFT-CDO-TZID if available
     $microsoftExchangeMap = array_flip(VObject\TimeZoneUtil::$microsoftExchangeMap);
     if (array_key_exists($tz->getName(), $microsoftExchangeMap)) {
         $vt->add('X-MICROSOFT-CDO-TZID', $microsoftExchangeMap[$tz->getName()]);
     }
     return $vt;
 }
Example #23
0
 /**
  * Repairs a VObject file
  *
  * @param Component $vObj
  * @return int
  */
 protected function repair($vObj)
 {
     $returnCode = 0;
     switch ($vObj->name) {
         case 'VCALENDAR':
             $this->log("iCalendar: " . (string) $vObj->VERSION);
             break;
         case 'VCARD':
             $this->log("vCard: " . (string) $vObj->VERSION);
             break;
     }
     $warnings = $vObj->validate(Node::REPAIR);
     if (!count($warnings)) {
         $this->log("  No warnings!");
     } else {
         $levels = [1 => 'REPAIRED', 2 => 'WARNING', 3 => 'ERROR'];
         $returnCode = 2;
         foreach ($warnings as $warn) {
             $extra = '';
             if ($warn['node'] instanceof Property) {
                 $extra = ' (property: "' . $warn['node']->name . '")';
             }
             $this->log("  [" . $levels[$warn['level']] . '] ' . $warn['message'] . $extra);
         }
     }
     fwrite($this->stdout, $vObj->serialize());
     return $returnCode;
 }
Example #24
0
 protected function serializeComponent(Component $vObj)
 {
     $this->cWrite('cyan', 'BEGIN');
     $this->cWrite('red', ':');
     $this->cWrite('yellow', $vObj->name . "\n");
     /**
      * Gives a component a 'score' for sorting purposes.
      *
      * This is solely used by the childrenSort method.
      *
      * A higher score means the item will be lower in the list.
      * To avoid score collisions, each "score category" has a reasonable
      * space to accomodate elements. The $key is added to the $score to
      * preserve the original relative order of elements.
      *
      * @param int $key
      * @param array $array
      *
      * @return int
      */
     $sortScore = function ($key, $array) {
         if ($array[$key] instanceof Component) {
             // We want to encode VTIMEZONE first, this is a personal
             // preference.
             if ($array[$key]->name === 'VTIMEZONE') {
                 $score = 300000000;
                 return $score + $key;
             } else {
                 $score = 400000000;
                 return $score + $key;
             }
         } else {
             // Properties get encoded first
             // VCARD version 4.0 wants the VERSION property to appear first
             if ($array[$key] instanceof Property) {
                 if ($array[$key]->name === 'VERSION') {
                     $score = 100000000;
                     return $score + $key;
                 } else {
                     // All other properties
                     $score = 200000000;
                     return $score + $key;
                 }
             }
         }
     };
     $children = $vObj->children();
     $tmp = $children;
     uksort($children, function ($a, $b) use($sortScore, $tmp) {
         $sA = $sortScore($a, $tmp);
         $sB = $sortScore($b, $tmp);
         return $sA - $sB;
     });
     foreach ($children as $child) {
         if ($child instanceof Component) {
             $this->serializeComponent($child);
         } else {
             $this->serializeProperty($child);
         }
     }
     $this->cWrite('cyan', 'END');
     $this->cWrite('red', ':');
     $this->cWrite('yellow', $vObj->name . "\n");
 }
Example #25
0
 /**
  * Create a property.
  *
  * @param Component $parentComponent
  * @param string $name
  * @param array $parameters
  * @param string $type
  * @param mixed $value
  *
  * @return void
  */
 protected function createProperty(Component $parentComponent, $name, $parameters, $type, $value)
 {
     $property = $this->root->createProperty($name, null, $parameters, $type);
     $parentComponent->add($property);
     $property->setXmlValue($value);
 }
 /**
  * @param $properties
  * @return mixed
  */
 public function createOrUpdate($properties)
 {
     $id = null;
     /**
      * @var \OCA\Contacts\VObject\VCard
      */
     $vcard = null;
     if (array_key_exists('id', $properties)) {
         // TODO: test if $id belongs to this addressbook
         $id = $properties['id'];
         // TODO: Test $vcard
         $vcard = $this->addressBook->getChild($properties['id']);
         foreach (array_keys($properties) as $name) {
             if (isset($vcard->{$name})) {
                 unset($vcard->{$name});
             }
         }
     } else {
         $vcard = \Sabre\VObject\Component::create('VCARD');
         $uid = substr(md5(rand() . time()), 0, 10);
         $vcard->add('UID', $uid);
         try {
             $id = $this->addressBook->addChild($vcard);
         } catch (\Exception $e) {
             \OCP\Util::writeLog('contacts', __METHOD__ . ' ' . $e->getMessage(), \OCP\Util::ERROR);
             return false;
         }
     }
     foreach ($properties as $name => $value) {
         switch ($name) {
             case 'ADR':
             case 'N':
                 if (is_array($value)) {
                     $property = \Sabre\VObject\Property::create($name);
                     $property->setParts($value);
                     $vcard->add($property);
                 } else {
                     $vcard->{$name} = $value;
                 }
                 break;
             case 'BDAY':
                 // TODO: try/catch
                 $date = new \DateTime($value);
                 $vcard->BDAY = $date->format('Y-m-d');
                 $vcard->BDAY->VALUE = 'DATE';
                 break;
             case 'EMAIL':
             case 'TEL':
             case 'IMPP':
                 // NOTE: We don't know if it's GTalk, Jabber etc. only the protocol
             // NOTE: We don't know if it's GTalk, Jabber etc. only the protocol
             case 'URL':
                 if (is_array($value)) {
                     foreach ($value as $val) {
                         $vcard->add($name, strip_tags($val));
                     }
                 } else {
                     $vcard->add($name, strip_tags($value));
                 }
             default:
                 $vcard->{$name} = $value;
                 break;
         }
     }
     try {
         VCard::edit($id, $vcard);
     } catch (\Exception $e) {
         \OCP\Util::writeLog('contacts', __METHOD__ . ' ' . $e->getMessage(), \OCP\Util::ERROR);
         return false;
     }
     $asarray = VCard::structureContact($vcard);
     $asarray['id'] = $id;
     return $asarray;
 }
Example #27
0
 /**
  * Validates the node for correctness.
  *
  * The following options are supported:
  *   Node::REPAIR - May attempt to automatically repair the problem.
  *
  * This method returns an array with detected problems.
  * Every element has the following properties:
  *
  *  * level - problem level.
  *  * message - A human-readable string describing the issue.
  *  * node - A reference to the problematic node.
  *
  * The level means:
  *   1 - The issue was repaired (only happens if REPAIR was turned on)
  *   2 - An inconsequential issue
  *   3 - A severe issue.
  *
  * @param int $options
  * @return array
  */
 public function validate($options = 0)
 {
     $result = parent::validate($options);
     if (isset($this->DUE) && isset($this->DTSTART)) {
         $due = $this->DUE;
         $dtStart = $this->DTSTART;
         if ($due->getValueType() !== $dtStart->getValueType()) {
             $result[] = array('level' => 3, 'message' => 'The value type (DATE or DATE-TIME) must be identical for DUE and DTSTART', 'node' => $due);
         } elseif ($due->getDateTime() < $dtStart->getDateTime()) {
             $result[] = array('level' => 3, 'message' => 'DUE must occur after DTSTART', 'node' => $due);
         }
     }
     return $result;
 }
Example #28
0
 /**
  * @expectedException LogicException
  */
 public function testInTimeRangeInvalidComponent()
 {
     $valarm = Component::create('VALARM');
     $valarm->TRIGGER = '-P1D';
     $valarm->TRIGGER['RELATED'] = 'END';
     $vjournal = Component::create('VJOURNAL');
     $vjournal->add($valarm);
     $valarm->isInTimeRange(new DateTime('2012-02-25 01:00:00'), new DateTime('2012-03-05 01:00:00'));
 }
Example #29
0
 /**
  * Generate an event to show in the calendar
  *
  * @return \Sabre\VObject\Component\VCalendar|null
  */
 public function getBirthdayEvent()
 {
     if (!isset($this->BDAY)) {
         return;
     }
     $birthday = $this->BDAY;
     if ((string) $birthday) {
         $title = str_replace('{name}', strtr((string) $this->FN, array('\\,' => ',', '\\;' => ';')), App::$l10n->t('{name}\'s Birthday'));
         try {
             $date = new \DateTime($birthday);
         } catch (\Exception $e) {
             continue;
         }
         $vevent = \Sabre\VObject\Component::create('VEVENT');
         $vevent->add('DTSTART');
         $vevent->DTSTART->setDateTime($date, \Sabre\VObject\Property\DateTime::DATE);
         $vevent->add('DURATION', 'P1D');
         $vevent->{'UID'} = $this->UID;
         $vevent->{'RRULE'} = 'FREQ=YEARLY';
         $vevent->{'SUMMARY'} = $title;
         $vcal = \Sabre\VObject\Component::create('VCALENDAR');
         $vcal->VERSION = '2.0';
         $appinfo = \OCP\App::getAppInfo('contacts');
         $appversion = \OCP\App::getAppVersion('contacts');
         $vcal->PRODID = '-//ownCloud//NONSGML ' . $appinfo['name'] . ' ' . $appversion . '//EN';
         $vcal->add($vevent);
         return $vcal;
     }
 }
 /**
  * Repairs a VObject file
  *
  * @param Component $vObj
  * @return int
  */
 protected function repair($vObj)
 {
     $returnCode = 0;
     switch ($vObj->name) {
         case 'VCALENDAR':
             $this->log("iCalendar: " . (string) $vObj->VERSION);
             break;
         case 'VCARD':
             $this->log("vCard: " . (string) $vObj->VERSION);
             break;
     }
     $warnings = $vObj->validate(Node::REPAIR);
     if (!count($warnings)) {
         $this->log("  No warnings!");
     } else {
         foreach ($warnings as $warn) {
             $returnCode = 2;
             $this->log("  " . $warn['message']);
         }
     }
     fwrite($this->stdout, $vObj->serialize());
     return $returnCode;
 }