function parse_outlookcsv($cal_file) { global $errormsg, $tz; $outlookcsv_data = array(); if (!($fd = @fopen($cal_file, 'r'))) { $errormsg .= 'Cannot read temporary file: ' . "{$cal_file}\n"; exit; } else { # Burn First Row of Headers $data = fgetcsv($fd, @filesize($cal_file), ','); while ($data = fgetcsv($fd, @filesize($cal_file))) { $subject = addslashes($data[0]); $start = icaldate_to_timestamp(date('Ymd\\THis', strtotime($data[1] . ' ' . $data[2]))); $end = icaldate_to_timestamp(date('Ymd\\THis', strtotime($data[3] . ' ' . $data[4]))); $all_day_event = (int) toBoolean($data[5]); $remind_on_off = (int) toBoolean($data[6]); $reminder = icaldate_to_timestamp(date('Ymd\\THis', strtotime($data[7] . ' ' . $data[8]))); $meeting_organizer = $data[9]; $required_attendies = $data[10]; $optional_attendies = $data[11]; $meeting_resources = $data[12]; $billing_information = $data[13]; $categories = addslashes(str_replace(';', ',', $data[14])); $description = addslashes($data[15]); $location = addslashes($data[16]); $mileage = $data[17]; $priority = $data[18]; $class = (int) toBoolean($data[19]); $sensitivity = $data[20]; $show_time_as = $data[21]; /* * Start New Section For Outlook CSV */ // $tmp_data['RecordID'] = ; $tmp_data['StartTime'] = $start; // In seconds since 1970 (Unix Epoch) $tmp_data['EndTime'] = $end; // In seconds since 1970 (Unix Epoch) $tmp_data['Summary'] = $subject; // Summary of event (string) $tmp_data['Duration'] = dateDifference($start, $end, 1); // How long the event lasts (in minutes) $tmp_data['Description'] = $description; // Full Description (string) $tmp_data['Location'] = $location; // Location (string) $tmp_data['AllDay'] = $all_day_event; // 1 = true 0 = false $tmp_data['Class'] = $class == 1 ? 'R' : 'P'; $tmp_data['Categories'] = get_categories_id_byname($categories); $tmp_data['AlarmSet'] = $remind_on_off; // 1 = true 0 = false $tmp_data['ADate'] = $reminder; // Date/Time of Alarm $tmp_data['AAction'] = 'EMAIL'; // The default action $tmp_data['CalendarType'] = 'VEVENT'; // The default type $outlookcsv_data[] = $tmp_data; } // End while fclose($fd); } return $outlookcsv_data; }
function format_ical($event) { global $login; // Set Product ID $fevent['Prodid'] = !empty($event['prodid']) ? $event['prodid'] : ''; // Set Calendar Type for easier processing later $fevent['CalendarType'] = $event['state']; $fevent['Untimed'] = $fevent['AllDay'] = 0; // Categories if (isset($event['categories'])) { // $fevent['Categories'] will contain an array of cat_id(s) that match the // category_names $fevent['Categories'] = get_categories_id_byname(utf8_decode($event['categories'])); } // Start and end time /* Snippet from RFC2445 For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE data type but no "DTEND" property, the events non-inclusive end is the end of the calendar date specified by the "DTSTART" property. For cases where a "VEVENT" calendar component specifies a "DTSTART" property with a DATE-TIME data type but no "DTEND" property, the event ends on the same calendar date and time of day specified by the "DTSTART" property. */ $dtstartTzid = !empty($event['dtstartTzid']) ? $event['dtstartTzid'] : ''; $fevent['StartTime'] = icaldate_to_timestamp($event['dtstart'], $dtstartTzid); if (isset($event['dtend'])) { $dtendTzid = !empty($event['dtendTzid']) ? $event['dtendTzid'] : ''; $fevent['EndTime'] = icaldate_to_timestamp($event['dtend'], $dtendTzid); if ($fevent['StartTime'] == $fevent['EndTime']) { $fevent['Untimed'] = 1; $fevent['Duration'] = 0; } else { $fevent['Duration'] = ($fevent['EndTime'] - $fevent['StartTime']) / 60; } } else { if (isset($event['duration'])) { $fevent['EndTime'] = $fevent['StartTime'] + $event['duration'] * 60; $fevent['Duration'] = $event['duration']; } else { if (isset($event['dtstartDATETIME'])) { // Untimed $fevent['EndTime'] = $fevent['StartTime']; $fevent['Untimed'] = 1; $fevent['Duration'] = 0; } } } if (isset($event['dtstartDATE']) && !isset($event['dtendDATE'])) { // Untimed $fevent['StartTime'] = icaldate_to_timestamp($event['dtstart'], 'GMT'); $fevent['EndTime'] = $fevent['StartTime']; $fevent['Untimed'] = 1; $fevent['Duration'] = 0; //$fevent['EndTime'] = $fevent['StartTime'] + 86400; //$fevent['AllDay'] = 1; //$fevent['Duration'] = 1440; } else { if (isset($event['dtstartDATE']) && isset($event['dtendDATE'])) { $fevent['StartTime'] = icaldate_to_timestamp($event['dtstart'], 'GMT'); // This is an untimed event if ($event['dtstart'] == $event['dtend']) { $fevent['EndTime'] = $fevent['StartTime']; $fevent['Untimed'] = 1; $fevent['Duration'] = 0; } else { $fevent['EndTime'] = icaldate_to_timestamp($event['dtend'], 'GMT'); $fevent['Duration'] = ($fevent['EndTime'] - $fevent['StartTime']) / 60; if ($fevent['Duration'] == 1440) { $fevent['AllDay'] = 1; } } } } // catch 22 if (!isset($fevent['EndTime'])) { $fevent['EndTime'] = $fevent['StartTime']; } if (!isset($fevent['Duration'])) { $fevent['Duration'] = 0; } if (empty($event['summary'])) { $event['summary'] = translate('Unnamed Event'); } $fevent['Summary'] = utf8_decode($event['summary']); if (!empty($event['description'])) { $fevent['Description'] = utf8_decode($event['description']); } else { $fevent['Description'] = $fevent['Summary']; } if (!empty($event['class'])) { // Added Confidential as new CLASS if (preg_match('/private/i', $event['class'])) { $fevent['Class'] = 'R'; } elseif (preg_match('/confidential/i', $event['class'])) { $fevent['Class'] = 'C'; } else { $fevent['Class'] = 'P'; } } $fevent['UID'] = $event['uid']; // Process VALARM stuff if (!empty($event['alarm_trigger'])) { $fevent['AlarmSet'] = 1; if (preg_match("/VALUE=DATE-TIME:(.*)\$/i", $event['alarm_trigger'], $match)) { $fevent['ADate'] = icaldate_to_timestamp($match[1]); } else { $duration = parse_ISO8601_duration($event['alarm_trigger']); $fevent['AOffset'] = abs($duration); $fevent['ABefore'] = $duration < 0 ? 'N' : 'Y'; } if (!empty($event['alarm_action'])) { $fevent['AAction'] = $event['alarm_action']; } if (!empty($event['alarm_repeat'])) { $fevent['ARepeat'] = $event['alarm_repeat']; } if (!empty($event['alarm_duration'])) { $fevent['ADuration'] = abs(parse_ISO8601_duration($event['alarm_duration'])); } if (!empty($event['alarm_related'])) { $fevent['ARelated'] = $event['alarm_related'] == 'END' ? 'E' : 'S'; } } if (!empty($event['status'])) { switch ($event['status']) { case 'TENTATIVE': // case 'NEEDS-ACTION': Sunbird sets this if you touch task without // changing anything else. Not sure about other clients yet $fevent['Status'] = 'W'; break; case 'CONFIRMED': case 'ACCEPTED': $fevent['Status'] = 'A'; break; case 'CANCELLED': $fevent['Status'] = 'D'; break; case 'DECLINED': $fevent['Status'] = 'R'; break; case 'COMPLETED': $fevent['Status'] = 'C'; break; case 'IN-PROGRESS': $fevent['Status'] = 'P'; break; default: $fevent['Status'] = 'A'; break; } //end switch } else { $fevent['Status'] = 'A'; } if (!empty($event['location'])) { $fevent['Location'] = utf8_decode($event['location']); } if (!empty($event['url'])) { $fevent['URL'] = utf8_decode($event['url']); } if (!empty($event['priority'])) { $fevent['PRIORITY'] = $event['priority']; } if (!empty($event['transparency'])) { if (preg_match('/TRANSPARENT/i', $event['transparency']) or $event['transparency'] == 1) { $fevent['Transparency'] = 1; } else { $fevent['Transparency'] = 0; } } else { $fevent['Transparency'] = 0; } // VTODO specific items if (!empty($event['due'])) { $fevent['Due'] = $event['due']; } if (!empty($event['completed'])) { $fevent['Completed'] = $event['completed']; } if (!empty($event['percent'])) { $fevent['Percent'] = $event['percent']; } // Repeating exceptions $fevent['Repeat']['Exceptions'] = array(); if (!empty($event['exdate']) && $event['exdate']) { $EX = explode(',', $event['exdate']); foreach ($EX as $exdate) { $fevent['Repeat']['Exceptions'][] = icaldate_to_timestamp($exdate); } $fevent['Repeat']['Frequency'] = 7; //manual, this can be changed later } // Repeating inclusions $fevent['Repeat']['Inclusions'] = array(); if (!empty($event['rdate']) && $event['rdate']) { $R = explode(',', $event['rdate']); foreach ($R as $rdate) { $fevent['Repeat']['Inclusions'][] = icaldate_to_timestamp($rdate); } $fevent['Repeat']['Frequency'] = 7; //manual, this can be changed later } /* Repeats Snippet from RFC2445 If multiple BYxxx rule parts are specified, then after evaluating the specified FREQ and INTERVAL rule parts, the BYxxx rule parts are applied to the current set of evaluated occurrences in the following order: BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND and BYSETPOS; then COUNT and UNTIL are evaluated. */ // Handle RRULE if (!empty($event['rrule'])) { // default value // first remove any UNTIL that may have been calculated above unset($fevent['Repeat']['Until']); // split into pieces // echo "RRULE line: $event[rrule]<br />\n"; $RR = explode(';', $event['rrule']); // create an associative array of key-value pairs in $RR2[] $rrcnt = count($RR); for ($i = 0; $i < $rrcnt; $i++) { $ar = explode('=', $RR[$i]); $RR2[$ar[0]] = $ar[1]; } for ($i = 0; $i < $rrcnt; $i++) { if (preg_match("/^FREQ=(.+)\$/i", $RR[$i], $match)) { if (preg_match("/YEARLY/i", $match[1], $submatch)) { $fevent['Repeat']['Frequency'] = 6; } else { if (preg_match("/MONTHLY/i", $match[1], $submatch)) { $fevent['Repeat']['Frequency'] = 3; //MonthByDay } else { if (preg_match("/WEEKLY/i", $match[1], $submatch)) { $fevent['Repeat']['Frequency'] = 2; } else { if (preg_match("/DAILY/i", $match[1], $submatch)) { $fevent['Repeat']['Frequency'] = 1; } else { // not supported :-( // but don't overwrite Manual setting from above if ($fevent['Repeat']['Frequency'] != 7) { $fevent['Repeat']['Frequency'] = 0; } echo "Unsupported iCal FREQ value \"{$match['1']}\"<br />\n"; // Abort this import return; } } } } } else { if (preg_match("/^INTERVAL=(.+)\$/i", $RR[$i], $match)) { $fevent['Repeat']['Interval'] = $match[1]; } else { if (preg_match("/^UNTIL=(.+)\$/i", $RR[$i], $match)) { // specifies an end date $fevent['Repeat']['Until'] = icaldate_to_timestamp($match[1]); } else { if (preg_match("/^COUNT=(.+)\$/i", $RR[$i], $match)) { // specifies the number of repeats // We convert this to a true UNTIL after we parse exceptions $fevent['Repeat']['Count'] = $match[1]; } else { if (preg_match("/^BYSECOND=(.+)\$/i", $RR[$i], $match)) { // NOT YET SUPPORTED -- TODO echo "Unsupported iCal BYSECOND value \"{$RR[$i]}\"<br />\n"; } else { if (preg_match("/^BYMINUTE=(.+)\$/i", $RR[$i], $match)) { // NOT YET SUPPORTED -- TODO echo "Unsupported iCal BYMINUTE value \"{$RR[$i]}\"<br />\n"; } else { if (preg_match("/^BYHOUR=(.+)\$/i", $RR[$i], $match)) { // NOT YET SUPPORTED -- TODO echo "Unsupported iCal BYHOUR value \"{$RR[$i]}\"<br />\n"; } else { if (preg_match("/^BYMONTH=(.+)\$/i", $RR[$i], $match)) { // this event repeats during the specified months $fevent['Repeat']['ByMonth'] = $match[1]; } else { if (preg_match("/^BYDAY=(.+)\$/i", $RR[$i], $match)) { // this array contains integer offset (i.e. 1SU,1MO,1TU) $fevent['Repeat']['ByDay'] = $match[1]; } else { if (preg_match("/^BYMONTHDAY=(.+)\$/i", $RR[$i], $match)) { $fevent['Repeat']['ByMonthDay'] = $match[1]; // $fevent['Repeat']['Frequency'] = 3; //MonthlyByDay } else { if (preg_match("/^BYSETPOS=(.+)\$/i", $RR[$i], $match)) { // if not already Yearly, mark as MonthlyBySetPos if ($fevent['Repeat']['Frequency'] != 6) { $fevent['Repeat']['Frequency'] = 5; } $fevent['Repeat']['BySetPos'] = $match[1]; } else { if (preg_match("/^BYWEEKNO=(.+)\$/i", $RR[$i], $match)) { $fevent['Repeat']['ByWeekNo'] = $match[1]; } else { if (preg_match("/^BYYEARDAY=(.+)\$/i", $RR[$i], $match)) { $fevent['Repeat']['ByYearDay'] = $match[1]; } else { if (preg_match("/^WKST=(.+)\$/i", $RR[$i], $match)) { $fevent['Repeat']['Wkst'] = $match[1]; } } } } } } } } } } } } } } } } // end if rrule return $fevent; }