From 82112ffa928d9e55009c8a67028be7c970818f78 Mon Sep 17 00:00:00 2001 From: skeeter Date: Mon, 2 Jul 2001 03:31:13 +0000 Subject: [PATCH] Enhanced parsing of vCalendar's. More options. --- calendar/ical_test.php | 36 ++- calendar/inc/class.vCalendar.inc.php | 398 ++++++++++++++++++--------- calendar/inc/vcal1.ics | 5 +- 3 files changed, 299 insertions(+), 140 deletions(-) diff --git a/calendar/ical_test.php b/calendar/ical_test.php index b7ff013a10..b76ccb9161 100755 --- a/calendar/ical_test.php +++ b/calendar/ical_test.php @@ -33,19 +33,34 @@ { echo "
\nEVENT
\n"; echo "Summary = ".$vcalendar->event[$i]->summary."
\n"; - echo "Description = ".$vcalendar->event[$i]->description."
\n"; + if($vcalendar->event[$i]->description->value) + { + echo "Description (Value) = ".$vcalendar->event[$i]->description->value."
\n"; + } + if($vcalendar->event[$i]->description->altrep) + { + echo "Description (Alt Rep) = ".$vcalendar->event[$i]->description->altrep."
\n"; + } echo "Location = ".$vcalendar->event[$i]->location."
\n"; echo "Sequence = ".$vcalendar->event[$i]->sequence."
\n"; echo "Date Start : ".$phpgw->common->show_date(mktime($vcalendar->event[$i]->dtstart->hour,$vcalendar->event[$i]->dtstart->min,$vcalendar->event[$i]->dtstart->sec,$vcalendar->event[$i]->dtstart->month,$vcalendar->event[$i]->dtstart->mday,$vcalendar->event[$i]->dtstart->year) - $phpgw->calendar->datatime->tz_offset)."
\n"; echo "Class = ".$vcal->switch_class($vcalendar->event[$i]->class)."
\n"; echo "Organizer = ".$vcalendar->event[$i]->organizer->mailto->user.'@'.$vcalendar->event[$i]->organizer->mailto->host."
\n"; + if($vcalendar->event[$i]->organizer->dir) + { + echo "Organizer Dir = ".$vcalendar->event[$i]->organizer->dir."
\n"; + } for($j=0;$jevent[$i]->attendee);$j++) { - echo "Attendee[$j] CN = ".$vcalendar->event[$i]->attendee[$j]->cn."
\n"; - echo "Attendee[$j] Address= ".$vcalendar->event[$i]->attendee[$j]->mailto->user.'@'.$vcalendar->event[0]->attendee[$j]->mailto->host."
\n"; - echo "Attendee[$j] Role = ".$vcal->switch_role($vcalendar->event[$i]->attendee[$j]->role)."
\n"; - echo "Attendee[$j] RSVP = ".$vcal->switch_rsvp($vcalendar->event[$i]->attendee[$j]->rsvp)."
\n"; -// echo "Attendee[$j] RSVP = ".$vcalendar->event[$i]->attendee[$j]->rsvp."
\n"; + echo "
\nAttendee[$j] CN = ".$vcalendar->event[$i]->attendee[$j]->cn."
\n"; + if($vcalendar->event[$i]->attendee[$j]->dir) + { + echo "Attendee[$j] Dir = ".$vcalendar->event[$i]->attendee[$j]->dir."
\n"; + } + echo "Attendee[$j] Address = ".$vcalendar->event[$i]->attendee[$j]->mailto->user.'@'.$vcalendar->event[0]->attendee[$j]->mailto->host."
\n"; + echo "Attendee[$j] Role = ".$vcal->switch_role($vcalendar->event[$i]->attendee[$j]->role)."
\n"; + echo "Attendee[$j] RSVP = ".$vcal->switch_rsvp($vcalendar->event[$i]->attendee[$j]->rsvp)."
\n"; +// echo "Attendee[$j] RSVP = ".$vcalendar->event[$i]->attendee[$j]->rsvp."
\n"; if($vcalendar->event[$i]->attendee[$j]->delegated_from->user && $vcalendar->event[$i]->attendee[$j]->delegated_from->host) { echo "Attendee[$j] DELEGATED_FROM = ".$vcalendar->event[$i]->attendee[$j]->delegated_from->user.'@'.$vcalendar->event[$i]->attendee[$j]->delegated_from->host."
\n"; @@ -56,7 +71,14 @@ { echo "
\nTODO
\n"; echo "Summary = ".$vcalendar->todo[$i]->summary."
\n"; - echo "Description = ".$vcalendar->todo[$i]->description."
\n"; + if($vcalendar->todo[$i]->description->value) + { + echo "Description (Value) = ".$vcalendar->todo[$i]->description->value."
\n"; + } + if($vcalendar->todo[$i]->description->altrep) + { + echo "Description (Alt Rep) = ".$vcalendar->todo[$i]->description->altrep."
\n"; + } echo "Location = ".$vcalendar->todo[$i]->location."
\n"; echo "Sequence = ".$vcalendar->todo[$i]->sequence."
\n"; echo "Date Start : ".$phpgw->common->show_date(mktime($vcalendar->todo[$i]->dtstart->hour,$vcalendar->todo[$i]->dtstart->min,$vcalendar->todo[$i]->dtstart->sec,$vcalendar->todo[$i]->dtstart->month,$vcalendar->todo[$i]->dtstart->mday,$vcalendar->todo[$i]->dtstart->year) - $phpgw->calendar->datatime->tz_offset)."
\n"; diff --git a/calendar/inc/class.vCalendar.inc.php b/calendar/inc/class.vCalendar.inc.php index b3f059f6e5..ebb4fed979 100755 --- a/calendar/inc/class.vCalendar.inc.php +++ b/calendar/inc/class.vCalendar.inc.php @@ -12,7 +12,7 @@ /* $Id$ */ -define('FOLD_LENGTH',79); +define('FOLD_LENGTH',75); define('VEVENT',1); define('VTODO',2); @@ -44,6 +44,9 @@ define('CONFIDENTIAL',3); define('TRANSPARENT',0); define('OPAQUE',1); +define('_8BIT',0); +define('_BASE64',1); + define('OTHER',99); class mailto @@ -55,6 +58,7 @@ class mailto class attendee { var $cn = 'Unknown'; + var $dir; var $cutype = INDIVIDUAL; var $role = REQ_PARTICIPANT; var $rsvp = 0; @@ -66,18 +70,6 @@ class attendee var $partstat = NEEDS_ACTION; } -class organizer -{ - var $cn; - var $cutype = INDIVIDUAL; - var $delegated_from; - var $delegated_to; - var $member; - var $partstat = NEEDS_ACTION; - var $mailto; - var $sent_by; -} - class vCalendar_time { var $year; @@ -100,6 +92,15 @@ class rrule var $byday; } +class class_text +{ + var $cid; + var $fmttype; + var $encoding; + var $altrep; + var $value; +} + class vCalendar_item { var $type; @@ -110,6 +111,7 @@ class vCalendar_item var $location; var $transp = OPAQUE; var $sequence; + var $attach; var $uid; var $dtstamp; var $description; @@ -210,12 +212,7 @@ class vCalendar function fold($str) { -// $temp_str = $str; -// if(strlen($str) > FOLD_LENGTH) -// { - return chunk_split($str,FOLD_LENGTH,"\n"); -// } -// return $temp_str; + return chunk_split($str,FOLD_LENGTH,"\r\n"); } function strip_quotes($str) @@ -236,6 +233,146 @@ class vCalendar } } + function split_param(&$return_value,$str,$check_equal) + { + if($check_equal) + { + $str_len = strlen($str); + $i = 0; + $found = False; + while($i < $str_len) + { + $char = substr($str,$i,1); + if(ereg("^[\=\:]",$char)) + { + $found = True; + $ret_str = rawurldecode(substr($str,0,$i)); + $return_value[] = $ret_str; + $ret_array = $this->explode_param(substr($str,$i + 1),'"',False); + while(list($key,$value) = each($ret_array)) + { + $return_value[] = rawurldecode($value); + } + $i = $str_len; + } + $i++; + } + if(!$found) + { + $return_value[] = rawurldecode($str); + } + } + else + { + $return_value[] = rawurldecode($str); + } + } + + function explode_param($str,$enclosure,$check_equal) + { + $enclosure_found = 0; + $start = 0; + $return_value = Array(); + $str_len = strlen($str); + for($i=0;$i<$str_len;$i++) + { + $char = substr($str,$i,1); + if($char == $enclosure) + { + $enclosure_found = (~ $enclosure_found); + } + elseif(ereg("^[\;\:]",$char)) + { + if(! $enclosure_found) + { + $this->split_param($return_value,substr($str,$start,($i - $start)),$check_equal); + $start = $i + 1; + } + } + } + if(! $enclosure_found) + { + $this->split_param($return_value,substr($str,$start,($i - $start)),$check_equal); + } + return $return_value; + } + + function parse_text(&$event,$value) + { + echo "VALUE = ".$value."
\n"; + $return_value = $this->explode_param($value,'"',True); + if(count($return_value) > 0) + { + for($i=0;$istrip_quotes($return_value[$i+1]); + switch(strtolower($type[0])) + { + case 'altrep': + case 'fmttype': + case 'cid': + echo "Setting ".$type[0]." = ".$type[1]."
\n"; + $this->set_var($event,strtolower($type[0]),$type[1]); + break; + case 'encoding': + echo "Setting ".$type[0]." = ".$type[1]."
\n"; + $this->set_var($event,strtolower($type[0]),$this->switch_encoding($type[1])); + break; + case 'value': + break; + default: + echo "Setting value(0) = ".$type[0]."
\n"; + $this->set_var($event,'value',$type[0]); + break; + } + } + } + elseif($value <> '\n') + { + echo "Setting value(text) = ".$value."
\n"; + $this->set_var($event,'value',$value); + } + } + + function switch_encoding($var) + { + if(gettype($var) == 'string') + { + switch($var) + { + case '8BIT': + return _8BIT; + break; + case 'BASE64': + return _BASE64; + break; + default: + return OTHER; + break; + } + } + elseif(gettype($var) == 'integer') + { + switch($var) + { + case _8BIT: + return '8BIT'; + break; + case _BASE64: + return 'BASE64'; + break; + case OTHER: + return 'OTHER'; + break; + } + } + else + { + return $var; + } + } + function switch_role($var) { if(gettype($var) == 'string') @@ -456,90 +593,34 @@ class vCalendar function parse_attendee(&$event,$value) { - $param = explode(':',$value); -// Here down needs to be faster.... - $j = 0; - while($jexplode_param($value,'"',True); -// $j = 0; -// while(($j - 1)strip_quotes($param[$j+1]); + switch($type[0]) { - if(strpos($param_sub[$k],'=')) - { - $type = explode('=',$param_sub[$k]); - $type[0] = strtolower($type[0]); - $type[1] = $this->strip_quotes($type[1]); - switch($type[0]) - { - case 'role': - $val = $this->switch_role($type[1]); - break; - case 'partstat': - $val = $this->switch_partstat($type[1]); - break; - case 'rsvp': - $val = $this->switch_rsvp($type[1]); - break; - case 'delegated-from': - case 'delegated-to': - $type[0] = str_replace('-','_',$type[0]); - $val = $this->split_address($type[1]); - break; - default: - $val = $type[1]; - break; - } - $this->set_var($event,$type[0],$val); - } - else - { - if(strpos($param_sub[$k],'@')) - { - $this->set_var($event,'mailto',$this->split_address($param_sub[$k])); - } - else - { - switch(strtolower($param_sub[$k])) - { - case 'mailto': - $email_addy = $param_sub[$k + 1]; - $this->set_var($event,$param_sub[$k++],$this->split_address($email_addy)); - break; - default: - $var = $this->strip_param($this->strip_quotes($param_sub[$k + 1])); - $this->set_var($event,$param_sub[$k++],$var); - break; - } - } - } + case 'role': + $val = $this->switch_role($type[1]); + break; + case 'partstat': + $val = $this->switch_partstat($type[1]); + break; + case 'rsvp': + $val = $this->switch_rsvp($type[1]); + break; + case 'delegated-from': + case 'delegated-to': + case 'mailto': + $type[0] = str_replace('-','_',$type[0]); + $val = $this->split_address($type[1]); + break; + default: + $val = $type[1]; + break; } + $this->set_var($event,$type[0],$val); } } @@ -575,6 +656,8 @@ class vCalendar $this->unfold($vcal_text,$i); + $vcal_text[$i] = str_replace("\r\n",'',$vcal_text[$i]); + // Example #1 //vcal_text[$i] = 'BEGIN:VCALENDAR' @@ -585,7 +668,7 @@ class vCalendar //vcal_text[$i] = 'ATTENDEE;CN="John Doe";ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:john.doe@somewhere.com' // Example #4 - //vcal_text[$i] = 'ORGANIZER:MAILTO:jim.smith@elsewhere.com' + //vcal_text[$i] = 'ORGANIZER;DIR="ldap://host.com:6666/o=eDABC%20Industries,c=3DUS??(cn=3DBJim%20Dolittle)":MAILTO:John.Doe@somewhere.com' // Example #5 //vcal_text[$i] = 'DTSTART:20010302T150000Z' @@ -597,6 +680,7 @@ class vCalendar // When unfolded becomes, //vcal_text[$i] = 'UID:040000008200E00074C5B7101A82E0080000000040A12C0042A2C0010000000000000000100000009BDFF7C7650ED5118DD700805FA71291' + echo "LINE : ".$vcal_text[$i]."
\n"; $colon = strpos($vcal_text[$i],':'); if($colon == 0) { @@ -634,10 +718,6 @@ class vCalendar $event = new vCalendar_item; $event->type = strtolower($value); break; -// case 'vtodo': -// $event = new vCalendar_item; -// $event->type = strtolower($value); -// break; } break; case 'prodid': @@ -645,14 +725,26 @@ class vCalendar case 'method': $this->set_var($vcal,$majortype,$value); break; + case 'description': +echo "Setting Description!
\n"; + $event->$majortype = new class_text; + $this->parse_text($event->$majortype,$value); + break; + case 'attach': +echo "Setting Attachment!
\n"; + $attach = new class_text; + $this->parse_text($attach,$value); + $event->attach[] = $attach; + unset($attach); + break; case 'attendee': - $attendee = new $majortype; + $attendee = new attendee; $this->parse_attendee($attendee,$value); $event->attendee[] = $attendee; unset($attendee); break; case 'organizer': - $event->$majortype = new $majortype; + $event->$majortype = new attendee; $this->parse_attendee($event->$majortype,$value); break; case 'end': @@ -700,10 +792,14 @@ class vCalendar function out_organizer_attendee($event) { $str = ''; - if(!empty($event->cn)) + if(!empty($event->cn) && $event->cn <> 'Unknown') { $str .= ';CN="'.$event->cn.'"'; } + if(!empty($event->dir)) + { + $str .= ';DIR="'.str_replace(' ','%20',$event->dir).'"'; + } if(!empty($event->role)) { $str .= ';ROLE='.$this->switch_role($event->role); @@ -714,11 +810,11 @@ class vCalendar } if(!empty($event->delegated_from->user) && !empty($event->delegated_from->host)) { - $str .= ';DELEGATED-FROM:MAILTO:"'.$event->delegated_from->user.'@'.$event->delegated_from->host.'"'; + $str .= ';DELEGATED-FROM="MAILTO:'.$event->delegated_from->user.'@'.$event->delegated_from->host.'"'; } if(!empty($event->delegated_to->user) && !empty($event->delegated_to->host)) { - $str .= ';DELEGATED-TO:MAILTO:"'.$event->delegated_to->user.'@'.$event->delegated_to->host.'"'; + $str .= ';DELEGATED-TO="MAILTO:'.$event->delegated_to->user.'@'.$event->delegated_to->host.'"'; } if(!empty($event->mailto->user) && !empty($event->mailto->host)) { @@ -727,10 +823,42 @@ class vCalendar return $str; } + function build_text($event) + { + $str = ''; + if(!empty($event->cid)) + { + $str .= ';CID="'.$event->cid.'"'; + } + if(!empty($event->altrep)) + { + $str .= ';ALTREP="'.$event->altrep.'"'; + } + if(!empty($event->fmttype)) + { + $str .= ';FMTTYPE='.$event->fmttype; + } + if(!empty($event->encoding)) + { + $str .= ';ENCODING='.$this->switch_encoding($event->encoding); + } + if(!empty($event->value)) + { + $str .= ':'.$event->value; + } + else + { + $str .= ':\n'; + } + + echo "TEXT = ".$str."
\n"; + return $str; + } + function build_card_internals($event) { - $str .= 'DTSART:'.sprintf("%4d%02d%02dT%02d%02d%02dZ",$event->dtstart->year,$event->dtstart->month,$event->dtstart->mday,$event->dtstart->hour,$event->dtstart->min,$event->dtstart->sec)."\n"; - $str .= 'DTEND:'.sprintf("%4d%02d%02dT%02d%02d%02dZ",$event->dtend->year,$event->dtend->month,$event->dtend->mday,$event->dtend->hour,$event->dtend->min,$event->dtend->sec)."\n"; + $str = 'DTSART:'.sprintf("%4d%02d%02dT%02d%02d%02dZ",$event->dtstart->year,$event->dtstart->month,$event->dtstart->mday,$event->dtstart->hour,$event->dtstart->min,$event->dtstart->sec)."\r\n"; + $str .= 'DTEND:'.sprintf("%4d%02d%02dT%02d%02d%02dZ",$event->dtend->year,$event->dtend->month,$event->dtend->mday,$event->dtend->hour,$event->dtend->min,$event->dtend->sec)."\r\n"; // Still need to build recurrence portion...... iF(!empty($event->location)) { @@ -738,25 +866,25 @@ class vCalendar } else { - $str .= 'LOCATION:\n'."\n"; + $str .= 'LOCATION:\n'."\r\n"; } - $str .= 'TRANSP:'.$this->switch_transp($event->transp)."\n"; + $str .= 'TRANSP:'.$this->switch_transp($event->transp)."\r\n"; if(!empty($event->sequence)) { - $str .= 'SEQUENCE:'.$event->sequence."\n"; + $str .= 'SEQUENCE:'.$event->sequence."\r\n"; } if(!empty($event->uid)) { $str .= $this->fold('UID:'.$event->uid); } - $str .= 'DTSTAMP:'.gmdate('Ymd\THms\Z')."\n"; + $str .= 'DTSTAMP:'.gmdate('Ymd\THms\Z')."\r\n"; if(!empty($event->description)) { - $str .= $this->fold('DESCRIPTION:'.$event->description); + $str .= $this->fold('DESCRIPTION'.$this->build_text($event->description)); } else { - $str .= 'DESCRIPTION:\n'."\n"; + $str .= 'DESCRIPTION:\n'."\r\n"; } if(!empty($event->summary)) { @@ -764,55 +892,63 @@ class vCalendar } else { - $str .= 'SUMMARY:\n'."\n"; + $str .= 'SUMMARY:\n'."\r\n"; } if(!empty($event->priority)) { - $str .= 'PRIORITY:'.$event->priority."\n"; + $str .= 'PRIORITY:'.$event->priority."\r\n"; + } + $str .= 'CLASS:'.$this->switch_class($event->class)."\r\n"; + + if(!empty($event->attach)) + { + for($i=0;$iattach);$i++) + { + $str .= $this->fold('ATTACH'.$this->build_text($event->atttach[$i])); + } } - $str .= 'CLASS:'.$this->switch_class($event->class)."\n"; return $str; } function build_vcal($vcal) { - $str = 'BEGIN:VCALENDAR'."\n"; - $str .= 'PRODID:'.$vcal->prodid."\n"; - $str .= 'VERSION:'.$vcal->version."\n"; - $str .= 'METHOD:'.$vcal->method."\n"; + $str = 'BEGIN:VCALENDAR'."\r\n"; + $str .= 'PRODID:'.$vcal->prodid."\r\n"; + $str .= 'VERSION:'.$vcal->version."\r\n"; + $str .= 'METHOD:'.$vcal->method."\r\n"; if($vcal->event) { for($i=0;$ievent);$i++) { - $str .= 'BEGIN:VEVENT'."\n"; + $str .= 'BEGIN:VEVENT'."\r\n"; for($j=0;$jevent[$i]->attendee);$j++) { $temp_attendee = $this->out_organizer_attendee($vcal->event[$i]->attendee[$j]); if($temp_attendee) { - $str .= 'ATTENDEE'.$temp_attendee."\n"; + $str .= $this->fold('ATTENDEE'.$temp_attendee); } } if(!empty($vcal->event[$i]->organizer)) { - $str .= 'ORGANIZER'.$this->out_organizer_attendee($vcal->event[$i]->organizer)."\n"; + $str .= $this->fold('ORGANIZER'.$this->out_organizer_attendee($vcal->event[$i]->organizer)); } $str .= $this->build_card_internals($vcal->event[$i]); - $str .= 'END:VEVENT'."\n"; + $str .= 'END:VEVENT'."\r\n"; } } if($vcal->todo) { for($i=0;$itodo);$i++) { - $str .= 'BEGIN:VTODO'."\n"; + $str .= 'BEGIN:VTODO'."\r\n"; $str .= $this->build_card_internals($vcal->todo[$i]); - $str .= 'END:VTODO'."\n"; + $str .= 'END:VTODO'."\r\n"; } } - $str .= 'END:VCALENDAR'."\n"; + $str .= 'END:VCALENDAR'."\r\n"; return $str; } diff --git a/calendar/inc/vcal1.ics b/calendar/inc/vcal1.ics index 0f3b664de9..5e7044ea12 100755 --- a/calendar/inc/vcal1.ics +++ b/calendar/inc/vcal1.ics @@ -6,7 +6,7 @@ BEGIN:VEVENT ATTENDEE;CN="Doe John (Marketing)";ROLE=REQ-PARTICIPANT;RSVP=TRUE:MAILTO:John.Doe@somewhere.com ATTENDEE;CN="Jones Bill (IT)";ROLE=REQ-PARTICIPANT;RSVP=TRUE;DELEGATED-FROM="MAILTO:immud@host3.com":MAILTO:Bill.Jones@somewhere.com ATTENDEE;CN="Smith Mary (PR)";ROLE=NON-PARTICIPANT;RSVP=FALSE:MAILTO:Mary.Smith@elsewhere.com -ORGANIZER:MAILTO:John.Doe@somewhere.com +ORGANIZER;DIR="ldap://host.com:6666/o=eDABC%20Industries,c=3DUS??(cn=3DBJim%20Dolittle)":MAILTO:John.Doe@somewhere.com DTSTART:20010302T150000Z DTEND:20010302T153000Z LOCATION:Conference Room #2 @@ -15,9 +15,10 @@ SEQUENCE:0 UID:023007208203E60074C5B7107A82E00803730C0D40A12C0042A2C001009384EA000F00B100 184029BDFF7C7650ED5118DF7028059A01231 DTSTAMP:20010301T172312Z -DESCRIPTION:\n +DESCRIPTION;ALTREP="http://www.wiz.org":The Fall'98 Wild Wizards Conference - - Las Vegas, NV, USA SUMMARY:Web Site Redesign PRIORITY:5 +ATTACH;FMTTYPE=image/basic;ENCODING=BASE64:VALUE:TEST CLASS:PUBLIC END:VEVENT BEGIN:VEVENT