/** * 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); }
/** * 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)); }
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; }
/** * @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; }
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; }
/** * 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"')); }
/** * @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; }
/** * @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')); }
/** * @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; }
die; } $events = 100; if (isset($argv[1])) { $events = (int) $argv[1]; } include __DIR__ . '/../vendor/autoload.php'; fwrite(STDERR, "Generating " . $events . " events\n"); $currentDate = new DateTime('-' . round($events / 2) . ' days'); $calendar = VObject\Component::create('VCALENDAR'); $calendar->version = '2.0'; $calendar->calscale = 'GREGORIAN'; $ii = 0; while ($ii < $events) { $ii++; $event = VObject\Component::create('VEVENT'); $event->DTSTART = 'bla'; $event->SUMMARY = 'Event #' . $ii; $event->UID = md5(microtime(true)); $doctorRandom = mt_rand(1, 1000); switch ($doctorRandom) { // All-day event case 1: $event->DTEND = 'bla'; $dtStart = clone $currentDate; $dtEnd = clone $currentDate; $dtEnd->modify('+' . mt_rand(1, 3) . ' days'); $event->DTSTART->setDateTime($dtStart, VObject\Property\DateTime::DATE); $event->DTEND->setDateTime($dtEnd, VObject\Property\DateTime::DATE); break; case 2:
/** * Build a valid iCal format block from the given event * * @param array Hash array with event/task properties from libkolab * @param object VCalendar object to append event to or false for directly sending data to stdout * @param callable Callback function to fetch attachment contents, false if no attachment export * @param object RECURRENCE-ID property when serializing a recurrence exception */ private function _to_ical($event, $vcal, $get_attachment, $recurrence_id = null) { $type = $event['_type'] ?: 'event'; $ve = VObject\Component::create($this->type_component_map[$type]); $ve->add('UID', $event['uid']); // set DTSTAMP according to RFC 5545, 3.8.7.2. $dtstamp = !empty($event['changed']) && !empty($this->method) ? $event['changed'] : new DateTime(); $ve->add($this->datetime_prop('DTSTAMP', $dtstamp, true)); // all-day events end the next day if ($event['allday'] && !empty($event['end'])) { $event['end'] = clone $event['end']; $event['end']->add(new \DateInterval('P1D')); $event['end']->_dateonly = true; } if (!empty($event['created'])) { $ve->add($this->datetime_prop('CREATED', $event['created'], true)); } if (!empty($event['changed'])) { $ve->add($this->datetime_prop('LAST-MODIFIED', $event['changed'], true)); } if (!empty($event['start'])) { $ve->add($this->datetime_prop('DTSTART', $event['start'], false, (bool) $event['allday'])); } if (!empty($event['end'])) { $ve->add($this->datetime_prop('DTEND', $event['end'], false, (bool) $event['allday'])); } if (!empty($event['due'])) { $ve->add($this->datetime_prop('DUE', $event['due'], false)); } // we're exporting a recurrence instance only if (!$recurrence_id && $event['recurrence_date'] && $event['recurrence_date'] instanceof DateTime) { $recurrence_id = $this->datetime_prop('RECURRENCE-ID', $event['recurrence_date'], false, (bool) $event['allday']); if ($event['thisandfuture']) { $recurrence_id->add('RANGE', 'THISANDFUTURE'); } } if ($recurrence_id) { $ve->add($recurrence_id); } $ve->add('SUMMARY', $event['title']); if ($event['location']) { $ve->add($this->is_apple() ? new vobject_location_property('LOCATION', $event['location']) : new VObject\Property('LOCATION', $event['location'])); } if ($event['description']) { $ve->add('DESCRIPTION', strtr($event['description'], array("\r\n" => "\n", "\r" => "\n"))); } // normalize line endings if (isset($event['sequence'])) { $ve->add('SEQUENCE', $event['sequence']); } if ($event['recurrence'] && !$recurrence_id) { $exdates = $rdates = null; if (isset($event['recurrence']['EXDATE'])) { $exdates = $event['recurrence']['EXDATE']; unset($event['recurrence']['EXDATE']); // don't serialize EXDATEs into RRULE value } if (isset($event['recurrence']['RDATE'])) { $rdates = $event['recurrence']['RDATE']; unset($event['recurrence']['RDATE']); // don't serialize RDATEs into RRULE value } if ($event['recurrence']['FREQ']) { $ve->add('RRULE', libcalendaring::to_rrule($event['recurrence'], (bool) $event['allday'])); } // add EXDATEs each one per line (for Thunderbird Lightning) if (is_array($exdates)) { foreach ($exdates as $ex) { if ($ex instanceof \DateTime) { $exd = clone $event['start']; $exd->setDate($ex->format('Y'), $ex->format('n'), $ex->format('j')); $exd->setTimeZone(new \DateTimeZone('UTC')); $ve->add(new VObject\Property('EXDATE', $exd->format('Ymd\\THis\\Z'))); } } } // add RDATEs if (is_array($rdates) && !empty($rdates)) { $sample = $this->datetime_prop('RDATE', $rdates[0]); $rdprop = new VObject\Property\MultiDateTime('RDATE', null); $rdprop->setDateTimes($rdates, $sample->getDateType()); $ve->add($rdprop); } } if ($event['categories']) { $cat = VObject\Property::create('CATEGORIES'); $cat->setParts((array) $event['categories']); $ve->add($cat); } if (!empty($event['free_busy'])) { $ve->add('TRANSP', $event['free_busy'] == 'free' ? 'TRANSPARENT' : 'OPAQUE'); // for Outlook clients we provide the X-MICROSOFT-CDO-BUSYSTATUS property if (stripos($this->agent, 'outlook') !== false) { $ve->add('X-MICROSOFT-CDO-BUSYSTATUS', $event['free_busy'] == 'outofoffice' ? 'OOF' : strtoupper($event['free_busy'])); } } if ($event['priority']) { $ve->add('PRIORITY', $event['priority']); } if ($event['cancelled']) { $ve->add('STATUS', 'CANCELLED'); } else { if ($event['free_busy'] == 'tentative') { $ve->add('STATUS', 'TENTATIVE'); } else { if ($event['complete'] == 100) { $ve->add('STATUS', 'COMPLETED'); } else { if (!empty($event['status'])) { $ve->add('STATUS', $event['status']); } } } } if (!empty($event['sensitivity'])) { $ve->add('CLASS', strtoupper($event['sensitivity'])); } if (!empty($event['complete'])) { $ve->add('PERCENT-COMPLETE', intval($event['complete'])); } // Apple iCal and BusyCal required the COMPLETED date to be set in order to consider a task complete if ($event['status'] == 'COMPLETED' || $event['complete'] == 100) { $ve->add($this->datetime_prop('COMPLETED', $event['changed'] ?: new DateTime('now - 1 hour'), true)); } if ($event['valarms']) { foreach ($event['valarms'] as $alarm) { $va = VObject\Component::create('VALARM'); $va->action = $alarm['action']; if ($alarm['trigger'] instanceof DateTime) { $va->add($this->datetime_prop('TRIGGER', $alarm['trigger'], true)); } else { $alarm_props = array(); if (strtoupper($alarm['related']) == 'END') { $alarm_props['RELATED'] = 'END'; } $va->add('TRIGGER', $alarm['trigger'], $alarm_props); } if ($alarm['action'] == 'EMAIL') { foreach ((array) $alarm['attendees'] as $attendee) { $va->add('ATTENDEE', 'mailto:' . $attendee); } } if ($alarm['description']) { $va->add('DESCRIPTION', $alarm['description'] ?: $event['title']); } if ($alarm['summary']) { $va->add('SUMMARY', $alarm['summary']); } if ($alarm['duration']) { $va->add('DURATION', $alarm['duration']); $va->add('REPEAT', intval($alarm['repeat'])); } if ($alarm['uri']) { $va->add('ATTACH', $alarm['uri'], array('VALUE' => 'URI')); } $ve->add($va); } } else { if ($event['alarms']) { $va = VObject\Component::create('VALARM'); list($trigger, $va->action) = explode(':', $event['alarms']); $val = libcalendaring::parse_alarm_value($trigger); if ($val[3]) { $va->add('TRIGGER', $val[3]); } else { if ($val[0] instanceof DateTime) { $va->add($this->datetime_prop('TRIGGER', $val[0])); } } $ve->add($va); } } foreach ((array) $event['attendees'] as $attendee) { if ($attendee['role'] == 'ORGANIZER') { if (empty($event['organizer'])) { $event['organizer'] = $attendee; } } else { if (!empty($attendee['email'])) { if (isset($attendee['rsvp'])) { $attendee['rsvp'] = $attendee['rsvp'] ? 'TRUE' : null; } $ve->add('ATTENDEE', 'mailto:' . $attendee['email'], array_filter(self::map_keys($attendee, $this->attendee_keymap))); } } } if ($event['organizer']) { $ve->add('ORGANIZER', 'mailto:' . $event['organizer']['email'], self::map_keys($event['organizer'], array('name' => 'CN'))); } foreach ((array) $event['url'] as $url) { if (!empty($url)) { $ve->add('URL', $url); } } if (!empty($event['parent_id'])) { $ve->add('RELATED-TO', $event['parent_id'], array('RELTYPE' => 'PARENT')); } if ($event['comment']) { $ve->add('COMMENT', $event['comment']); } $memory_limit = parse_bytes(ini_get('memory_limit')); // export attachments if (!empty($event['attachments'])) { foreach ((array) $event['attachments'] as $attach) { // check available memory and skip attachment export if we can't buffer it // @todo: use rcube_utils::mem_check() if (is_callable($get_attachment) && $memory_limit > 0 && ($memory_used = function_exists('memory_get_usage') ? memory_get_usage() : 16 * 1024 * 1024) && $attach['size'] && $memory_used + $attach['size'] * 3 > $memory_limit) { continue; } // embed attachments using the given callback function if (is_callable($get_attachment) && ($data = call_user_func($get_attachment, $attach['id'], $event))) { // embed attachments for iCal $ve->add('ATTACH', base64_encode($data), array_filter(array('VALUE' => 'BINARY', 'ENCODING' => 'BASE64', 'FMTTYPE' => $attach['mimetype'], 'X-LABEL' => $attach['name']))); unset($data); // attempt to free memory } else { if (!empty($this->attach_uri)) { $ve->add('ATTACH', strtr($this->attach_uri, array('{{id}}' => urlencode($attach['id']), '{{name}}' => urlencode($attach['name']), '{{mimetype}}' => urlencode($attach['mimetype']))), array('FMTTYPE' => $attach['mimetype'], 'VALUE' => 'URI')); } } } } foreach ((array) $event['links'] as $uri) { $ve->add('ATTACH', $uri); } // add custom properties foreach ((array) $event['x-custom'] as $prop) { $ve->add($prop[0], $prop[1]); } // append to vcalendar container if ($vcal) { $vcal->add($ve); } else { // serialize and send to stdout echo $ve->serialize(); } // append recurrence exceptions if (is_array($event['recurrence']) && $event['recurrence']['EXCEPTIONS']) { foreach ($event['recurrence']['EXCEPTIONS'] as $ex) { $exdate = $ex['recurrence_date'] ?: $ex['start']; $recurrence_id = $this->datetime_prop('RECURRENCE-ID', $exdate, false, (bool) $event['allday']); if ($ex['thisandfuture']) { $recurrence_id->add('RANGE', 'THISANDFUTURE'); } $this->_to_ical($ex, $vcal, $get_attachment, $recurrence_id); } } }
/** * 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); }
/** * @depends testValues */ function testOverridenEventNoValuesExpected() { $vcal = Component::create('VCALENDAR'); $ev1 = Component::create('VEVENT'); $ev1->UID = 'overridden'; $ev1->RRULE = 'FREQ=WEEKLY;COUNT=3'; $ev1->DTSTART = '20120124T120000Z'; $ev1->SUMMARY = 'baseEvent'; $vcal->add($ev1); // ev2 overrides an event, and puts it 6 days earlier instead. $ev2 = Component::create('VEVENT'); $ev2->UID = 'overridden'; $ev2->{'RECURRENCE-ID'} = '20120131T120000Z'; $ev2->DTSTART = '20120125T120000Z'; $ev2->SUMMARY = 'Override!'; $vcal->add($ev2); $it = new RecurrenceIterator($vcal, 'overridden'); $dates = array(); $summaries = array(); // The reported problem was specifically related to the VCALENDAR // expansion. In this parcitular case, we had to forward to the 28th of // january. $it->fastForward(new DateTime('2012-01-28 23:00:00')); // We stop the loop when it hits the 6th of februari. Normally this // iterator would hit 24, 25 (overriden from 31) and 7 feb but because // we 'filter' from the 28th till the 6th, we should get 0 results. while ($it->valid() && $it->getDTSTart() < new DateTime('2012-02-06 23:00:00')) { $dates[] = $it->getDTStart(); $summaries[] = (string) $it->getEventObject()->SUMMARY; $it->next(); } $this->assertEquals(array(), $dates); $this->assertEquals(array(), $summaries); }
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; }
/** * 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; } }
/** * @brief converts a unique element into a owncloud VCard * @param $element the element to convert * @return VCard, all unconverted elements are stored in X-Unknown-Element parameters */ public function convertElementToVCard($element, $title = null) { $vcard = \Sabre\VObject\Component::create('VCARD'); $nbElt = count($element); for ($i = 0; $i < $nbElt; $i++) { if ($element[$i] != '') { //$importEntry = false; // Look for the right import_entry if (isset($this->configContent->import_core->base_parsing)) { if (strcasecmp((string) $this->configContent->import_core->base_parsing, 'position') == 0) { $importEntry = $this->getImportEntryFromPosition((string) $i); } else { if (strcasecmp((string) $this->configContent->import_core->base_parsing, 'name') == 0 && isset($title[$i])) { $importEntry = $this->getImportEntryFromName($title[$i]); } } } if ($importEntry) { // Create a new property and attach it to the vcard $value = $element[$i]; if (isset($importEntry['remove'])) { $value = str_replace($importEntry['remove'], '', $element[$i]); } $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'); $vcard->add($property); } else { $property = $this->getOrCreateVCardProperty($vcard, $importEntry->vcard_entry); $this->updateProperty($property, $importEntry, trim($oneValue)); } } } else { $property = $this->getOrCreateVCardProperty($vcard, $importEntry->vcard_entry); $this->updateProperty($property, $importEntry, trim($oneValue)); } } } else { if (isset($element[$i]) && isset($title[$i])) { $property = \Sabre\VObject\Property::create("X-Unknown-Element", StringUtil::convertToUTF8($element[$i])); $property->parameters[] = new \Sabre\VObject\Parameter('TYPE', '' . StringUtil::convertToUTF8($title[$i])); $vcard->add($property); } } } } $vcard->validate(\Sabre\VObject\Component\VCard::REPAIR); return $vcard; }