/**
  * (non-PHPdoc)
  * @see Addressbook_Convert_Contact_VCard_Abstract::_toTine20ModelParseTel()
  */
 protected function _toTine20ModelParseTel(&$data, \Sabre\VObject\Property $property)
 {
     if (!isset($property['TYPE'])) {
         // CardDAVSync sends OTHER just as TEL:12345678 without any TYPE
         $data['tel_other'] = $property->getValue();
     }
     parent::_toTine20ModelParseTel($data, $property);
 }
 /**
  * (non-PHPdoc)
  * @see Addressbook_Convert_Contact_VCard_Abstract::_toTine20ModelParseEmail()
  */
 protected function _toTine20ModelParseEmail(&$data, \Sabre\VObject\Property $property, \Sabre\VObject\Component\VCard $vcard)
 {
     if ($vcard->{'X-OUTLOOK-EMAIL-2'} && $vcard->{'X-OUTLOOK-EMAIL-2'}->getValue() == $property->getValue()) {
         $data['email_home'] = $property->getValue();
     } elseif ($vcard->{'X-OUTLOOK-EMAIL-3'} && $vcard->{'X-OUTLOOK-EMAIL-3'}->getValue() == $property->getValue()) {
         // we don't map email3
     } else {
         $data['email'] = $property->getValue();
     }
 }
 public function testGroupProperty()
 {
     $arr = array('Home', 'work', 'Friends, Family');
     $property = \Sabre\VObject\Property::create('CATEGORIES');
     $property->setParts($arr);
     // Test parsing and serializing
     $this->assertEquals('Home,work,Friends\\, Family', $property->value);
     $this->assertEquals('CATEGORIES:Home,work,Friends\\, Family' . "\r\n", $property->serialize());
     $this->assertEquals(3, count($property->getParts()));
     // Test add
     $property->addGroup('Coworkers');
     $this->assertTrue($property->hasGroup('coworkers'));
     $this->assertEquals(4, count($property->getParts()));
     $this->assertEquals('Home,work,Friends\\, Family,Coworkers', $property->value);
     // Test remove
     $this->assertTrue($property->hasGroup('Friends, fAmIlY'));
     $property->removeGroup('Friends, fAmIlY');
     $this->assertEquals(3, count($property->getParts()));
     $parts = $property->getParts();
     $this->assertEquals('Coworkers', $parts[2]);
     // Test rename
     $property->renameGroup('work', 'Work');
     $parts = $property->getParts();
     $this->assertEquals('Work', $parts[1]);
     //$this->assertEquals(true, false);
 }
示例#4
0
 /**
  * Hydrate data from a XML subtree, as it would appear in a xCard or xCal
  * object.
  *
  * @param array $value
  *
  * @return void
  */
 function setXmlValue(array $value)
 {
     $value = array_map(function ($value) {
         return 'true' === $value;
     }, $value);
     parent::setXmlValue($value);
 }
示例#5
0
 /**
  * Sets the json value, as it would appear in a jCard or jCal object.
  *
  * The value must always be an array.
  *
  * @param array $value
  * @return void
  */
 public function setJsonValue(array $value)
 {
     $value = array_map(function ($item) {
         return strtr(implode('/', $item), array(':' => '', '-' => ''));
     }, $value);
     parent::setJsonValue($value);
 }
 /**
  * (non-PHPdoc)
  * @see Addressbook_Convert_Contact_VCard_Abstract::_toTine20ModelParseTel()
  */
 protected function _toTine20ModelParseTel(&$data, \Sabre\VObject\Property $property)
 {
     $telField = null;
     if (isset($property['TYPE'])) {
         // CELL
         if ($property['TYPE']->has('cell') && $property['TYPE']->has('voice') && !$property['TYPE']->has('iphone')) {
             $telField = 'tel_cell';
         } elseif ($property['TYPE']->has('cell') && $property['TYPE']->has('iphone')) {
             $telField = 'tel_cell_private';
         }
     }
     if (!empty($telField)) {
         $data[$telField] = $property->getValue();
     } else {
         parent::_toTine20ModelParseTel($data, $property);
     }
 }
 /**
  * (non-PHPdoc)
  * @see Addressbook_Convert_Contact_VCard_Abstract::_toTine20ModelParseEmail()
  */
 protected function _toTine20ModelParseEmail(&$data, \Sabre\VObject\Property $property, \Sabre\VObject\Component\VCard $vcard)
 {
     $type = null;
     if ($property['TYPE']) {
         if ($property['TYPE']->has('pref')) {
             $type = 'work';
         }
     }
     switch ($type) {
         case 'work':
             $data['email'] = $property->getValue();
             break;
         default:
             $data['email_home'] = $property->getValue();
             break;
     }
 }
示例#8
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"'));
 }
示例#9
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 = parent::validate($options);
     if (isset($this->minimumPropertyValues[$this->name])) {
         $minimum = $this->minimumPropertyValues[$this->name];
         $parts = $this->getParts();
         if (count($parts) < $minimum) {
             $warnings[] = array('level' => 1, 'message' => 'This property must have at least ' . $minimum . ' components. It only has ' . count($parts), 'node' => $this);
             if ($options & self::REPAIR) {
                 $parts = array_pad($parts, $minimum, '');
                 $this->setParts($parts);
             }
         }
     }
     return $warnings;
 }
示例#10
0
 /**
  * Sets the json value, as it would appear in a jCard or jCal object.
  *
  * The value must always be an array.
  *
  * @param array $value
  * @return void
  */
 public function setJsonValue(array $value)
 {
     $value = array_map('base64_decode', $value);
     parent::setJsonValue($value);
 }
 /**
  * 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)
 {
     $messages = parent::validate($options);
     $value = $this->getValue();
     try {
         DateTimeParser::parseVCardDateTime($value);
     } catch (\InvalidArgumentException $e) {
         $messages[] = array('level' => 3, 'message' => 'The supplied value (' . $value . ') is not a correct DATE-AND-OR-TIME property', 'node' => $this);
     }
     return $messages;
 }
 /**
  * get datetime from sabredav datetime property (user TZ is fallback)
  * 
  * @param  Sabre\VObject\Property  $dateTimeProperty
  * @param  boolean                 $_useUserTZ
  * @return Tinebase_DateTime
  * 
  * @todo try to guess some common timezones
  */
 protected function _convertToTinebaseDateTime(\Sabre\VObject\Property $dateTimeProperty, $_useUserTZ = FALSE)
 {
     $defaultTimezone = date_default_timezone_get();
     date_default_timezone_set((string) Tinebase_Core::getUserTimezone());
     if ($dateTimeProperty instanceof Sabre\VObject\Property\ICalendar\DateTime) {
         $dateTime = $dateTimeProperty->getDateTime();
         $tz = $_useUserTZ || isset($dateTimeProperty['VALUE']) && strtoupper($dateTimeProperty['VALUE']) == 'DATE' ? (string) Tinebase_Core::getUserTimezone() : $dateTime->getTimezone();
         $result = new Tinebase_DateTime($dateTime->format(Tinebase_Record_Abstract::ISO8601LONG), $tz);
     } else {
         $result = new Tinebase_DateTime($dateTimeProperty->getValue());
     }
     date_default_timezone_set($defaultTimezone);
     return $result;
 }
 /**
  * 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);
         }
     }
 }
示例#14
0
 /**
  * @brief Data structure of properties
  * @param object $property
  * @return associative array
  *
  * returns an associative array with
  * ['name'] name of property
  * ['value'] htmlspecialchars escaped value of property
  * ['parameters'] associative array name=>value
  * ['checksum'] checksum of whole property
  * NOTE: $value is not escaped anymore. It shouldn't make any difference
  * but we should look out for any problems.
  */
 public static function structureProperty(\Sabre\VObject\Property $property)
 {
     if (!in_array($property->name, App::$index_properties)) {
         return;
     }
     $value = $property->getValue();
     if ($property->name == 'ADR' || $property->name == 'N' || $property->name == 'ORG' || $property->name == 'CATEGORIES') {
         $value = $property->getParts();
         if ($property->name == 'CATEGORIES') {
             $value = str_replace(';', ',', $value);
         }
         if ($property->name == 'N') {
             //$value = stripslashes($value);
             //	\OCP\Util::writeLog('contactsplus','NAME VAL: '.$value, \OCP\Util::DEBUG);
         }
         $value = array_map('trim', $value);
     } elseif ($property->name == 'BDAY') {
         if (strlen($value) >= 8 && is_int(substr($value, 0, 4)) && is_int(substr($value, 4, 2)) && is_int(substr($value, 6, 2))) {
             $value = substr($value, 0, 4) . '-' . substr($value, 4, 2) . '-' . substr($value, 6, 2);
         } else {
             if ($value[5] !== '-' || $value[7] !== '-') {
                 try {
                     // Skype exports as e.g. Jan 14, 1996
                     $date = new \DateTime($value);
                     $value = $date->format('Y-m-d');
                 } catch (\Exception $e) {
                     \OCP\Util::writeLog('contactsplus', __METHOD__ . ' Error parsing date: ' . $value, \OCP\Util::DEBUG);
                     return;
                 }
             }
         }
     } elseif ($property->name == 'PHOTO') {
         $value = true;
     } elseif ($property->name == 'IMPP') {
         if (strpos($value, ':') !== false) {
             $value = explode(':', $value);
             $protocol = array_shift($value);
             if (!isset($property['X-SERVICE-TYPE'])) {
                 $property['X-SERVICE-TYPE'] = strtoupper($protocol);
             }
             $value = implode('', $value);
         }
     }
     if (is_string($value)) {
         $value = strtr($value, array('\\,' => ',', '\\;' => ';'));
     }
     $temp = array('value' => $value, 'parameters' => array());
     // This cuts around a 3rd off of the json response size.
     if (in_array($property->name, App::$multi_properties)) {
         $temp['checksum'] = substr(md5($property->serialize()), 0, 8);
     }
     foreach ($property->parameters as $parameter) {
         // Faulty entries by kaddressbook
         // Actually TYPE=PREF is correct according to RFC 2426
         // but this way is more handy in the UI. Tanghus.
         if ($parameter->name == 'TYPE' && strtoupper($parameter->getValue()) == 'PREF') {
             $parameter->name = 'PREF';
             $parameter->setValue('1');
         }
         // NOTE: Apparently Sabre_VObject_Reader can't always deal with value list parameters
         // like TYPE=HOME,CELL,VOICE. Tanghus.
         // TODO: Check if parameter is has commas and split + merge if so.
         if ($parameter->name == 'TYPE') {
             $pvalue = $parameter->getValue();
             if (is_string($pvalue) && strpos($pvalue, ',') !== false) {
                 $pvalue = array_map('trim', explode(',', $pvalue));
             }
             $pvalue = is_array($pvalue) ? $pvalue : array($pvalue);
             if (isset($temp['parameters'][$parameter->name])) {
                 $temp['parameters'][$parameter->name][] = \OCP\Util::sanitizeHTML($pvalue);
             } else {
                 $temp['parameters'][$parameter->name] = \OCP\Util::sanitizeHTML($pvalue);
             }
         } else {
             //$value = strtr($value, array('\,' => ',', '\;' => ';'));
             $temp['parameters'][$parameter->name] = \OCP\Util::sanitizeHTML($parameter->getValue());
         }
     }
     return $temp;
 }
示例#15
0
 /**
  * @brief returns the vcard property corresponding to the parameter
  * creates the property if it doesn't exists yet
  * @param $vcard the vcard to get or create the properties with
  * @param $importEntry the parameter to find
  * @return the property|false
  */
 protected function getOrCreateVCardProperty(&$vcard, $importEntry)
 {
     if (isset($vcard) && isset($importEntry)) {
         // looking for a property with the same name
         $properties = $vcard->select($importEntry['property']);
         foreach ($properties as $property) {
             if ($importEntry['type'] == null && !isset($importEntry->additional_property)) {
                 return $property;
             }
             foreach ($property->parameters as $parameter) {
                 // Filtering types
                 if ($parameter->name == 'TYPE' && !strcmp($parameter->value, $importEntry['type'])) {
                     $found = 0;
                     if (isset($importEntry->additional_property)) {
                         // Filtering additional properties if necessary (I know, there are a lot of inner loops, sorry)
                         foreach ($importEntry->additional_property as $additional_property) {
                             if ((string) $parameter->name == $additional_property['name']) {
                                 $found++;
                             }
                         }
                         if ($found == count($importEntry->additional_property)) {
                             return $property;
                         }
                     }
                     return $property;
                 }
             }
             if (isset($importEntry['group']) && $property->group == $importEntry['group']) {
                 return $property;
             }
         }
         // Property not found, creating one
         $property = \Sabre\VObject\Property::create($importEntry['property']);
         $vcard->add($property);
         if ($importEntry['type'] != null) {
             $property->parameters[] = new \Sabre\VObject\Parameter('TYPE', '' . StringUtil::convertToUTF8($importEntry['type']));
             switch ($importEntry['property']) {
                 case "ADR":
                     $property->setValue(";;;;;;");
                     break;
                 case "FN":
                     $property->setValue(";;;;");
                     break;
             }
         }
         if ($importEntry['group'] != null) {
             $property->group = $importEntry['group'];
         }
         return $property;
     } else {
         return false;
     }
 }
示例#16
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)
 {
     $messages = parent::validate($options);
     $valueType = $this->getValueType();
     $value = $this->getValue();
     try {
         switch ($valueType) {
             case 'DATE':
                 $foo = DateTimeParser::parseDate($value);
                 break;
             case 'DATE-TIME':
                 $foo = DateTimeParser::parseDateTime($value);
                 break;
         }
     } catch (\LogicException $e) {
         $messages[] = array('level' => 3, 'message' => 'The supplied value (' . $value . ') is not a correct ' . $valueType, 'node' => $this);
     }
     return $messages;
 }
示例#17
0
        $vcard->add($property);
        $checksum = substr(md5($property->serialize()), 0, 8);
        try {
            VCard::edit($id, $vcard);
        } catch (Exception $e) {
            bailOut($e->getMessage());
        }
        \OCP\JSON::success(array('data' => array('checksum' => $checksum, 'oldchecksum' => $_POST['checksum'])));
        exit;
    }
} else {
    $element = $name;
    $property = $vcard->select($name);
    debug('propertylist: ' . get_class($property));
    if (count($property) === 0) {
        $property = VObject\Property::create($name);
        $vcard->add($property);
    } else {
        $property = array_shift($property);
    }
}
/* preprocessing value */
switch ($element) {
    case 'BDAY':
        $date = new \DateTime($value);
        $value = $date->format('Y-m-d');
        break;
    case 'FN':
        if (!$value) {
            // create a method thats returns an alternative for FN.
            //$value = getOtherValue();
示例#18
0
 /**
  * This method serializes only the value of a property. This is used to
  * create xCard or xCal documents.
  *
  * @param Xml\Writer $writer  XML writer.
  *
  * @return void
  */
 protected function xmlSerializeValue(Xml\Writer $writer)
 {
     // Special-casing the GEO property.
     //
     // See:
     // http://tools.ietf.org/html/rfc6321#section-3.4.1.2
     if ($this->name === 'GEO') {
         $value = array_map('floatval', $this->getParts());
         $writer->writeElement('latitude', $value[0]);
         $writer->writeElement('longitude', $value[1]);
     } else {
         parent::xmlSerializeValue($writer);
     }
 }
示例#19
0
 /**
  * Work around issue in older VObject sersions
  * https://github.com/fruux/sabre-vobject/issues/24
  *
  * @param \Sabre\VObject\Property $property Reference to a \Sabre\VObject\Property.
  */
 public function fixPropertyParameters(&$property)
 {
     // Work around issue in older VObject sersions
     // https://github.com/fruux/sabre-vobject/issues/24
     foreach ($property->parameters as $key => $parameter) {
         if (strpos($parameter->getValue(), ',') === false) {
             continue;
         }
         $values = explode(',', $parameter->getValue());
         $values = array_map('trim', $values);
         $parameter->setValue(array_shift($values));
         foreach ($values as $value) {
             $property->add($parameter->name, $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;
 }
	/**
	 * @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;
	}
 /**
  * parse birthday
  * 
  * @param array $data
  * @param Sabre\VObject\Property $property
  */
 protected function _toTine20ModelParseBday(&$_data, \Sabre\VObject\Property $_property)
 {
     $tzone = new DateTimeZone(Tinebase_Core::getUserTimezone());
     $_data['bday'] = new Tinebase_DateTime($_property->getValue(), $tzone);
     $_data['bday']->setTimezone(new DateTimeZone('UTC'));
 }
 /**
  * (non-PHPdoc)
  * @see Addressbook_Convert_Contact_VCard_Abstract::_toTine20ModelParseEmail()
  */
 protected function _toTine20ModelParseEmail(&$data, \Sabre\VObject\Property $property, \Sabre\VObject\Component\VCard $vcard)
 {
     /*
      *  eM Client supports three types of mail
      */
     if ($property['TYPE']->has('home')) {
         $data['email_home'] = $property->getValue();
     } elseif ($property['TYPE']->has('work') && $data['email'] == '') {
         $data['email'] = $property->getValue();
     } elseif ($property['TYPE']->has('pref') || $data['email'] == '') {
         $data['email'] = $property->getValue();
     }
 }
 /**
  * @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;
 }
示例#25
0
 /**
  * Colorizes a property.
  *
  * @param Property $property
  * @return void
  */
 protected function serializeProperty(Property $property)
 {
     if ($property->group) {
         $this->cWrite('default', $property->group);
         $this->cWrite('red', '.');
     }
     $str = '';
     $this->cWrite('yellow', $property->name);
     foreach ($property->parameters as $param) {
         $this->cWrite('red', ';');
         $this->cWrite('blue', $param->serialize());
     }
     $this->cWrite('red', ':');
     if ($property instanceof Property\Binary) {
         $this->cWrite('default', 'embedded binary stripped. (' . strlen($property->getValue()) . ' bytes)');
     } else {
         $parts = $property->getParts();
         $first1 = true;
         // Looping through property values
         foreach ($parts as $part) {
             if ($first1) {
                 $first1 = false;
             } else {
                 $this->cWrite('red', $property->delimiter);
             }
             $first2 = true;
             // Looping through property sub-values
             foreach ((array) $part as $subPart) {
                 if ($first2) {
                     $first2 = false;
                 } else {
                     // The sub-value delimiter is always comma
                     $this->cWrite('red', ',');
                 }
                 $subPart = strtr($subPart, ['\\' => $this->colorize('purple', '\\\\', 'green'), ';' => $this->colorize('purple', '\\;', 'green'), ',' => $this->colorize('purple', '\\,', 'green'), "\n" => $this->colorize('purple', "\\n\n\t", 'green'), "\r" => ""]);
                 $this->cWrite('green', $subPart);
             }
         }
     }
     $this->cWrite("default", "\n");
 }
示例#26
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
  */
 function validate($options = 0)
 {
     $messages = parent::validate($options);
     $valueType = $this->getValueType();
     $values = $this->getParts();
     try {
         foreach ($values as $value) {
             switch ($valueType) {
                 case 'DATE':
                     DateTimeParser::parseDate($value);
                     break;
                 case 'DATE-TIME':
                     DateTimeParser::parseDateTime($value);
                     break;
             }
         }
     } catch (InvalidDataException $e) {
         $messages[] = ['level' => 3, 'message' => 'The supplied value (' . $value . ') is not a correct ' . $valueType, 'node' => $this];
     }
     return $messages;
 }
 /**
  * @brief Get data structure of property.
  * @param \Sabre\VObject\Property $property
  * @return associative array
  *
  * returns an associative array with
  * ['name'] name of property
  * ['value'] htmlspecialchars escaped value of property
  * ['parameters'] associative array name=>value
  * ['checksum'] checksum of whole property
  * NOTE: $value is not escaped anymore. It shouldn't make any difference
  * but we should look out for any problems.
  */
 public static function serializeProperty(\Sabre\VObject\Property $property)
 {
     if (!in_array($property->name, Properties::$index_properties)) {
         return;
     }
     $value = $property->value;
     if ($property->name == 'ADR' || $property->name == 'N' || $property->name == 'ORG' || $property->name == 'CATEGORIES') {
         $value = $property->getParts();
         $value = array_map('trim', $value);
     } elseif ($property->name == 'BDAY') {
         if (strpos($value, '-') === false) {
             if (strlen($value) >= 8) {
                 $value = substr($value, 0, 4) . '-' . substr($value, 4, 2) . '-' . substr($value, 6, 2);
             } else {
                 return null;
                 // Badly malformed :-(
             }
         }
     } elseif ($property->name == 'PHOTO') {
         $value = true;
     } elseif ($property->name == 'IMPP') {
         if (strpos($value, ':') !== false) {
             $value = explode(':', $value);
             $protocol = array_shift($value);
             if (!isset($property['X-SERVICE-TYPE'])) {
                 $property['X-SERVICE-TYPE'] = strtoupper($protocol);
             }
             $value = implode('', $value);
         }
     }
     if (is_string($value)) {
         $value = strtr($value, array('\\,' => ',', '\\;' => ';'));
     }
     $temp = array('value' => $value, 'parameters' => array());
     // This cuts around a 3rd off of the json response size.
     if (in_array($property->name, Properties::$multi_properties)) {
         $temp['checksum'] = substr(md5($property->serialize()), 0, 8);
     }
     foreach ($property->parameters as $parameter) {
         // Faulty entries by kaddressbook
         // Actually TYPE=PREF is correct according to RFC 2426
         // but this way is more handy in the UI. Tanghus.
         if ($parameter->name == 'TYPE' && strtoupper($parameter->value) == 'PREF') {
             $parameter->name = 'PREF';
             $parameter->value = '1';
         }
         // NOTE: Apparently Sabre_VObject_Reader can't always deal with value list parameters
         // like TYPE=HOME,CELL,VOICE. Tanghus.
         // TODO: Check if parameter is has commas and split + merge if so.
         if ($parameter->name == 'TYPE') {
             $pvalue = $parameter->value;
             if (is_string($pvalue) && strpos($pvalue, ',') !== false) {
                 $pvalue = array_map('trim', explode(',', $pvalue));
             }
             $pvalue = is_array($pvalue) ? $pvalue : array($pvalue);
             if (isset($temp['parameters'][$parameter->name])) {
                 $temp['parameters'][$parameter->name][] = \OCP\Util::sanitizeHTML($pvalue);
             } else {
                 $temp['parameters'][$parameter->name] = \OCP\Util::sanitizeHTML($pvalue);
             }
         } else {
             $temp['parameters'][$parameter->name] = \OCP\Util::sanitizeHTML($parameter->value);
         }
     }
     return $temp;
 }
示例#28
0
 /**
  * Hydrate data from a XML subtree, as it would appear in a xCard or xCal
  * object.
  *
  * @param array $value
  *
  * @return void
  */
 function setXmlValue(array $value)
 {
     $value = array_map('intval', $value);
     parent::setXmlValue($value);
 }
示例#29
0
 /**
  * Set a property by the property name.
  * It is up to the caller to call ->save()
  *
  * @param string $name Property name
  * @param mixed $value
  * @param array $parameters
  * @return bool
  */
 public function setPropertyByName($name, $value, $parameters = array())
 {
     // TODO: parameters are ignored for now.
     switch ($name) {
         case 'BDAY':
             try {
                 $date = new \DateTime($value);
             } catch (\Exception $e) {
                 \OCP\Util::writeLog('contacts', __METHOD__ . ' DateTime exception: ' . $e->getMessage(), \OCP\Util::ERROR);
                 return false;
             }
             $value = $date->format('Y-m-d');
             $this->BDAY = $value;
             $this->BDAY->add('VALUE', 'DATE');
             //\OCP\Util::writeLog('contacts', __METHOD__.' BDAY: '.$this->BDAY->serialize(), \OCP\Util::DEBUG);
             break;
         case 'CATEGORIES':
         case 'N':
         case 'ORG':
             $property = $this->select($name);
             if (count($property) === 0) {
                 $property = \Sabre\VObject\Property::create($name);
                 $this->add($property);
             } else {
                 // Actually no idea why this works
                 $property = array_shift($property);
             }
             if (is_array($value)) {
                 $property->setParts($value);
             } else {
                 $this->{$name} = $value;
             }
             break;
         default:
             \OCP\Util::writeLog('contacts', __METHOD__ . ' adding: ' . $name . ' ' . $value, \OCP\Util::DEBUG);
             $this->{$name} = $value;
             break;
     }
     $this->setSaved(false);
     return true;
 }
	/**
	 * @brief converts an LDIF element into a VCard property
	 * and updates the VCard
	 * @param $value the LDIF value
	 * @param $importEntry the VCard entry to modify
	 * @param $dest the VCard to modify (for adding a X-FAVOURITE property)
	 */
	private function convertElementToProperty($value, $importEntry, &$dest) {
		if (isset($importEntry->vcard_favourites)) {
			foreach ($importEntry->vcard_favourites as $vcardFavourite) {
				if (strcasecmp((string)$vcardFavourite, trim($value)) == 0) {
					$property = \Sabre\VObject\Property::create("X-FAVOURITES", 'yes');
					$dest->add($property);
				} else {
					$property = $this->getOrCreateVCardProperty($dest, $importEntry->vcard_entry);
					if (isset($importEntry['image']) && $importEntry['image'] == "true") {
						$this->updateImageProperty($property, $value);
					} else {
						$this->updateProperty($property, $importEntry, $value);
					}
				}
			}
		} else {
			$property = $this->getOrCreateVCardProperty($dest, $importEntry->vcard_entry);
			if (isset($importEntry['image']) && $importEntry['image'] == "true") {
				$this->updateImageProperty($property, $value);
			} else {
				$this->updateProperty($property, $importEntry, $value);
			}
		}
	}