\n";
if (!$fd=@fopen($cal_file,"r")) {
$errormsg .= "Can't read temporary file: $cal_file\n";
exit();
} else {
// reflect the section where we are in the file:
// VCALENDAR, TZ/DAYLIGHT, VEVENT, ALARM
$state = "NONE";
$substate = "none"; // reflect the sub section
$subsubstate = ""; // reflect the sub-sub section
$error = false;
$line = 0;
$event = '';
while (!feof($fd) && !$error) {
$line++;
$buff = fgets($fd, 4096);
$buff = chop($buff);
// parser debugging code...
//echo "line = $line
";
//echo "state = $state
";
//echo "substate = $substate
";
//echo "subsubstate = $subsubstate
";
//echo "buff = " . htmlspecialchars ( $buff ) . "
\n";
if ($state == "VEVENT") {
if ( ! empty ( $subsubstate ) ) {
if (preg_match("/^END:(.+)$/i", $buff, $match)) {
if ( $match[1] == $subsubstate ) {
$subsubstate = '';
}
} else if ( $subsubstate == "VALARM" &&
preg_match ( "/TRIGGER:(.+)$/i", $buff, $match ) ) {
//echo "Set reminder to $match[1]
";
//reminder time is $match[1]
}
}
else if (preg_match("/^BEGIN:(.+)$/i", $buff, $match)) {
$subsubstate = $match[1];
}
// we suppose ":" is on the same line as property name, this can perhaps cause problems
else if (preg_match("/^SUMMARY.*:(.+)$/i", $buff, $match)) {
$substate = "summary";
$event[$substate] = $match[1];
} elseif (preg_match("/^DESCRIPTION:(.+)$/i", $buff, $match)) {
$substate = "description";
$event[$substate] = $match[1];
} elseif (preg_match("/^DESCRIPTION;ENCODING=QUOTED-PRINTABLE:(.+)$/i", $buff, $match)) {
// $substate = "description";
// $event[$substate] = quoted_printable_decode ( $match[1] );
$substate = "descriptionqp";
$event[$substate] = $match[1];
} elseif (preg_match("/^CLASS.*:(.+)$/i", $buff, $match)) {
$substate = "class";
$event[$substate] = $match[1];
} elseif (preg_match("/^PRIORITY.*:(.+)$/i", $buff, $match)) {
$substate = "priority";
$event[$substate] = $match[1];
} elseif (preg_match("/^DTSTART.*:(.+)$/i", $buff, $match)) {
$substate = "dtstart";
$event[$substate] = $match[1];
} elseif (preg_match("/^DTEND.*:(.+)$/i", $buff, $match)) {
$substate = "dtend";
$event[$substate] = $match[1];
} elseif (preg_match("/^RRULE.*:(.+)$/i", $buff, $match)) {
$substate = "rrule";
$event[$substate] = $match[1];
} elseif (preg_match("/^EXDATE.*:(.+)$/i", $buff, $match)) {
$substate = "exdate";
$event[$substate] = $match[1];
} elseif (preg_match("/^DALARM.*:(.+)$/i", $buff, $match)) {
$substate = "dalarm";
$event[$substate] = $match[1];
} elseif (preg_match("/^CATEGORIES.*:(.+)$/i", $buff, $match)) {
$substate = "categories";
$event[$substate] = $match[1];
} elseif (preg_match("/^UID.*:(.+)$/i", $buff, $match)) {
$substate = "uid";
$event[$substate] = $match[1];
} elseif (preg_match("/^END:VEVENT$/i", $buff, $match)) {
$state = "VCALENDAR";
$substate = "none";
$subsubstate = '';
if ($tmp_data = format_vcal($event)) $vcal_data[] = $tmp_data;
// clear out data for new event
$event = '';
// TODO: QUOTED-PRINTABLE descriptions
// folded lines
} elseif (preg_match("/^[ ]{1}(.+)$/", $buff, $match)) {
if ($substate != "none") {
$event[$substate] .= $match[1];
} else {
$errormsg .= "Error in file $cal_file line $line:
$buff\n";
$error = true;
}
// For unsupported properties
} else {
$substate = "none";
}
} elseif ($state == "VCALENDAR") {
if (preg_match("/^TZ.*:(.+)$/i", $buff, $match)) {
$event['tz'] = $match[1];
} elseif (preg_match("/^DAYLIGHT.*:(.+)$/i", $buff, $match)) {
$event['daylight'] = $match[1];
} elseif (preg_match("/^BEGIN:VEVENT$/i", $buff)) {
$state = "VEVENT";
} elseif (preg_match("/^END:VCALENDAR$/i", $buff)) {
$state = "NONE";
}
} elseif ($state == "NONE") {
if (preg_match("/^BEGIN:VCALENDAR$/i", $buff))
$state = "VCALENDAR";
else if (preg_match("/^BEGIN:ALARM$/i", $buff))
$state = "ALARM";
}
} //End while
fclose($fd);
}
return $vcal_data;
}
// Convert vcal format (yyyymmddThhmmssZ) to epoch time
function vcaldate_to_timestamp($vdate,$plus_d = '0',$plus_m = '0', $plus_y = '0') {
global $TZoffset;
$y = substr($vdate, 0, 4) + $plus_y;
$m = substr($vdate, 4, 2) + $plus_m;
$d = substr($vdate, 6, 2) + $plus_d;
$H = substr($vdate, 9, 2);
$M = substr($vdate, 11, 2);
$S = substr($vdate, 13, 2);
$Z = substr($vdate, 15, 1);
if ($Z == 'Z') {
$TS = gmmktime($H,$M,$S,$m,$d,$y);
} else {
// Problem here if server in different timezone
$TS = mktime($H,$M,$S,$m,$d,$y);
}
return $TS;
}
// Put all vcal data into import hash structure
function format_vcal($event) {
// Start and end time
$fevent['StartTime'] = vcaldate_to_timestamp($event['dtstart']);
if ($fevent['StartTime'] == '-1') return false;
$fevent['EndTime'] = vcaldate_to_timestamp($event['dtend']);
// Calculate duration in minutes
$fevent['Duration'] = ($fevent['EndTime'] - $fevent['StartTime']) / 60;
if ($fevent['Duration'] == '1440') { $fevent['Duration'] = '0'; $fevent['Untimed'] = 1; } //All day (untimed)
if (! empty($event['summary'])) $fevent['Summary'] = $event['summary'];
if (! empty($event['description'])) $fevent['Description'] = $event['description'];
if (! empty($event['descriptionqp'])) {
$fevent['Description'] = quoted_printable_decode ( $event['descriptionqp'] );
// hack for mozilla sunbird's extra = signs
$fevent['Description'] = preg_replace('/^=/', '', $fevent['Description']);
$fevent['Description'] = str_replace("\n=", "\n", $fevent['Description']);
}
if (! empty($event['class'])) {
$fevent['Private'] = preg_match("/private|confidential/i", $event['class']) ? '1' : '0';
} else {
$fevent['Private'] = '0';
}
if (! empty($fevent['UID'])) $fevent['UID'] = $event['uid'];
// Repeats
//
// vcal 1.0 repeats can be very complicated and the webcalendar doesn't
// actually support all of the ways repeats can be specified. We will
// focus on vcals dumped from Palm Desktop and Lotus Notes, which are simple
// and the ones webcalendar should fully support.
if (! empty($event['rrule'])) {
//split into pieces
$RR = explode(" ", $event['rrule']);
if (preg_match("/^D(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '1';
$fevent['Repeat']['Frequency'] = $match[1];
} elseif (preg_match("/^W(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '2';
$fevent['Repeat']['Frequency'] = $match[1];
$fevent['Repeat']['RepeatDays'] = rrule_repeat_days($RR);
} elseif (preg_match("/^MP(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '3';
$fevent['Repeat']['Frequency'] = $match[1];
if ($RR[1] == '5+') {
$fevent['Repeat']['Interval'] = '6'; // Last week (monthlyByDayR)
}
} elseif (preg_match("/^MD(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '4';
$fevent['Repeat']['Frequency'] = $match[1];
} elseif (preg_match("/^YM(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '5';
$fevent['Repeat']['Frequency'] = $match[1];
} elseif (preg_match("/^YD(.+)$/i", $RR[0], $match)) {
$fevent['Repeat']['Interval'] = '5';
$fevent['Repeat']['Frequency'] = $match[1];
}
$end = end($RR);
// No end in Palm is 12-31-2031
if (($end != '20311231') && ($end != '#0')) {
$fevent['Repeat']['EndTime'] = rrule_endtime($fevent['Repeat']['Interval'],$fevent['Repeat']['Frequency'],$event['dtstart'],$end);
}
// Repeating exceptions?
if (!empty($event['exdate'])) {
$fevent['Repeat']['Exceptions'] = array();
$EX = explode(",", $event['exdate']);
foreach ( $EX as $exdate ){
$fevent['Repeat']['Exceptions'][] = vcaldate_to_timestamp($exdate);
}
}
} // end if rrule
// TODO
// $fevent[Category];
// $fevent[AlarmSet];
// $fevent[AlarmAdvanceAmount];
// $fevent[AlarmAdvanceType];
return $fevent;
}
// Figure out days of week for weekly repeats
function rrule_repeat_days($RA) {
$T = count($RA);
$j = $T - 1;
$sun = $mon = $tue = $wed = $thu = $fri = $sat = 'n';
for ($i = 1; $i < $j; $i++) {
if ($RA[$i] == 'SU') {
$sun = 'y';
} elseif ($RA[$i] == 'MO') {
$mon = 'y';
} elseif ($RA[$i] == 'TU') {
$tue = 'y';
} elseif ($RA[$i] == 'WE') {
$wed = 'y';
} elseif ($RA[$i] == 'TH') {
$thu = 'y';
} elseif ($RA[$i] == 'FR') {
$fri = 'y';
} elseif ($RA[$i] == 'SA') {
$sat = 'y';
}
}
return $sun.$mon.$tue.$wed.$thu.$fri.$sat;
}
// Calculate repeating ending time
function rrule_endtime($int,$freq,$start,$end) {
// if # then we have to add the difference to the start time
if (preg_match("/^#(.+)$/i", $end, $M)) {
$T = $M[1] * $freq;
$plus_d = $plus_m = $plus_y = '0';
if ($int == '1') {
$plus_d = $T;
} elseif ($int == '2') {
$plus_d = $T * 7;
} elseif ($int == '3') {
$plus_m = $T;
} elseif ($int == '4') {
$plus_m = $T;
} elseif ($int == '5') {
$plus_y = $T;
} elseif ($int == '6') {
$plus_m = $T;
}
$endtime = vcaldate_to_timestamp($start,$plus_d,$plus_m,$plus_y);
// if we have the enddate
} else {
$endtime = vcaldate_to_timestamp($end);
}
return $endtime;
}
?>