3 require_once(
'XMLElement.php');
4 require_once(
'AwlQuery.php');
61 $this->parameters = array();
62 unset($this->rendered);
63 if ( $propstring !=
null && gettype($propstring) ==
'string' ) {
78 $this->rendered = (strlen($propstring) < 72 ? $propstring :
null);
81 $unescaped = preg_replace(
'{\\\\[nN]}',
"\n", $propstring);
93 if (count($split) != 2) {
95 dbg_error_log(
'ERROR',
"iCalendar::ParseFrom(): Couldn't parse property from string: `%s`, skipping", $unescaped);
98 list($prop, $value) = $split;
101 $this->content = preg_replace(
"/\\\\([,;:\"\\\\])/",
'$1', $value);
105 $this->name = array_shift($parameters);
106 $this->parameters = array();
107 foreach ($parameters AS $k => $v) {
108 $pos = strpos($v,
'=');
109 $name = substr($v, 0, $pos);
110 $value = substr($v, $pos + 1);
111 $this->parameters[$name] = preg_replace(
'/^"(.+)"$/',
'$1', $value);
129 for($i = 0, $len = strlen($str); $i < $len; ++$i) {
132 $inquote = !$inquote;
134 if (!$inquote && $ch == $sep) {
138 if ($limit > 0 && $num == $limit) {
139 $result[] = substr($str, $cursor);
142 $result[] = substr($str, $cursor, $i - $cursor);
146 if ($i + 1 == $len) {
148 $result[] = substr($str, $cursor);
162 function Name( $newname =
null ) {
163 if ( $newname !=
null ) {
164 $this->name = $newname;
165 if ( isset($this->rendered) ) unset($this->rendered);
179 function Value( $newvalue =
null ) {
180 if ( $newvalue !=
null ) {
181 $this->content = $newvalue;
182 if ( isset($this->rendered) ) unset($this->rendered);
184 return $this->content;
196 if ( $newparams !=
null ) {
197 $this->parameters = $newparams;
198 if ( isset($this->rendered) ) unset($this->rendered);
200 return $this->parameters;
212 if ( isset($this->content) ) {
213 return (stristr( $this->content, $search ) !==
false);
227 if ( isset($this->parameters[$name]) )
return $this->parameters[$name];
238 if ( isset($this->rendered) ) unset($this->rendered);
239 $this->parameters[$name] = $value;
248 foreach( $this->parameters AS $k => $v ) {
249 $escaped = preg_replace(
"/([;:])/",
'\\\\$1', $v);
250 $rendered .= sprintf(
";%s=%s", $k, $escaped );
262 if ( isset($this->rendered) )
return $this->rendered;
264 $property = preg_replace(
'/[;].*$/',
'', $this->name );
265 $escaped = $this->content;
266 switch( $property ) {
268 case 'ATTACH':
case 'GEO':
case 'PERCENT-COMPLETE':
case 'PRIORITY':
269 case 'DURATION':
case 'FREEBUSY':
case 'TZOFFSETFROM':
case 'TZOFFSETTO':
270 case 'TZURL':
case 'ATTENDEE':
case 'ORGANIZER':
case 'RECURRENCE-ID':
271 case 'URL':
case 'EXRULE':
case 'SEQUENCE':
case 'CREATED':
272 case 'RRULE':
case 'REPEAT':
case 'TRIGGER':
275 case 'COMPLETED':
case 'DTEND':
276 case 'DUE':
case 'DTSTART':
277 case 'DTSTAMP':
case 'LAST-MODIFIED':
278 case 'CREATED':
case 'EXDATE':
280 if ( isset($this->parameters[
'VALUE']) && $this->parameters[
'VALUE'] ==
'DATE' ) {
281 $escaped = substr( $escaped, 0, 8);
287 $escaped = str_replace(
'\\',
'\\\\', $escaped);
288 $escaped = preg_replace(
'/\r?\n/',
'\\n', $escaped);
289 $escaped = preg_replace(
"/([,;])/",
'\\\\$1', $escaped);
292 if ( (strlen($property) + strlen($escaped)) <= 72 ) {
293 $this->rendered = $property . $escaped;
295 else if ( (strlen($property) + strlen($escaped)) > 72 && (strlen($property) < 72) && (strlen($escaped) < 72) ) {
296 $this->rendered = $property .
"\r\n " . $escaped;
299 $this->rendered = preg_replace(
'/(.{72})/u',
'$1'.
"\r\n ", $property . $escaped );
301 return $this->rendered;
356 $this->properties = array();
357 $this->components = array();
358 $this->rendered =
"";
359 if ( $content !=
null && (gettype($content) ==
'string' || gettype($content) ==
'array') ) {
371 $this->
AddProperty(
'PRODID',
'-//davical.org//NONSGML AWL Calendar//EN');
374 if ( is_array($extra_properties) ) {
375 foreach( $extra_properties AS $k => $v ) {
387 foreach( $this->components AS $k => $v ) {
388 $also = $v->CollectParameterValues($parameter_name);
389 $values = array_merge( $values, $also );
391 foreach( $this->properties AS $k => $v ) {
392 $also = $v->GetParameterValue($parameter_name);
393 if ( isset($also) && $also !=
"" ) {
407 $this->rendered = $content;
415 $length = strlen($content);
417 while( $linefrom < $length ) {
418 $lineto = strpos( $content,
"\n", $linefrom );
419 if ( $lineto ===
false ) {
420 $lineto = strpos( $content,
"\r", $linefrom );
423 $line = substr( $content, $linefrom, $lineto - $linefrom);
424 $linefrom = $lineto + 1;
427 $line = substr( $content, $linefrom );
430 if ( preg_match(
'/^\s*$/', $line ) )
continue;
431 $line = rtrim( $line,
"\r\n" );
434 if ( $type ===
false ) {
435 if ( preg_match(
'/^BEGIN:(.+)$/', $line, $matches ) ) {
438 $finish =
"END:$type";
440 dbg_error_log(
'iCalendar',
"::ParseFrom: Start component of type '%s'", $type);
443 dbg_error_log(
'iCalendar',
"::ParseFrom: Ignoring crap before start of component: $line");
445 if ( $line !=
"" ) $this->rendered =
null;
448 else if ( $type ==
null ) {
449 dbg_error_log(
'iCalendar',
"::ParseFrom: Ignoring crap after end of component");
450 if ( $line !=
"" ) $this->rendered =
null;
452 else if ( $line == $finish ) {
453 dbg_error_log(
'iCalendar',
"::ParseFrom: End of component");
457 if ( $subtype ===
false && preg_match(
'/^BEGIN:(.+)$/', $line, $matches ) ) {
459 $subtype = $matches[1];
460 $subfinish =
"END:$subtype";
461 $subcomponent = $line .
"\r\n";
462 dbg_error_log(
'iCalendar',
"::ParseFrom: Found a subcomponent '%s'", $subtype);
464 else if ( $subtype ) {
467 if ( $line == $subfinish ) {
468 dbg_error_log(
'iCalendar',
"::ParseFrom: End of subcomponent '%s'", $subtype);
479 $this->properties[] =
new iCalProp($line);
492 return preg_replace(
'/\r?\n[ \t]/',
'', $content );
504 $strs = preg_split(
"/\r?\n/", $content );
506 foreach ($strs as $str) {
507 $wrapped .= preg_replace(
'/(.{72})/u',
'$1'.
"\r\n ", $str ) .
"\r\n";
524 if ( isset($this->rendered) ) unset($this->rendered);
534 $properties = array();
535 foreach( $this->properties AS $k => $v ) {
536 if ( $type ==
null || $v->Name() == $type ) {
537 $properties[$k] = $v;
552 foreach( $this->properties AS $k => $v ) {
553 if ( $v->Name() == $type )
return $v->Value();
568 foreach( $this->properties AS $k => $v ) {
569 if ( $v->Name() == $type )
return $v->GetParameterValue($parameter_name);
580 if ( $type !=
null ) {
582 foreach( $this->properties AS $k => $v ) {
583 if ( $v->Name() == $type ) {
584 unset($this->properties[$k]);
585 if ( isset($this->rendered) ) unset($this->rendered);
588 $this->properties = array_values($this->properties);
591 if ( isset($this->rendered) ) unset($this->rendered);
592 $this->properties = array();
601 if ( isset($this->rendered) && count($new_properties) > 0 ) unset($this->rendered);
603 foreach( $new_properties AS $k => $v ) {
616 function AddProperty( $new_property, $value =
null, $parameters =
null ) {
617 if ( isset($this->rendered) ) unset($this->rendered);
618 if ( isset($value) && gettype($new_property) ==
'string' ) {
620 $new_prop->Name($new_property);
621 $new_prop->Value($value);
622 if ( $parameters !=
null ) $new_prop->Parameters($parameters);
623 dbg_error_log(
'iCalendar',
" Adding new property '%s'", $new_prop->Render() );
624 $this->properties[] = $new_prop;
626 else if ( gettype($new_property) ) {
627 $this->properties[] = $new_property;
637 foreach( $this->components AS $k => $v ) {
638 if ( $v->GetType() !=
'VTIMEZONE' )
return $this->components[$k];
652 if ( !preg_match(
'#^mailto:#', $email ) ) $email =
'mailto:'.$email;
654 foreach( $props AS $k => $prop ) {
655 if ( $prop->Value() == $email )
return true;
668 if ( !preg_match(
'#^mailto:#', $email ) ) $email =
'mailto:'.$email;
671 foreach( $props AS $k => $prop ) {
672 if ( $prop->Value() == $email )
return true;
687 $components = $this->components;
688 if ( $type !=
null ) {
689 foreach( $components AS $k => $v ) {
690 if ( ($v->GetType() != $type) === $normal_match ) {
691 unset($components[$k]);
694 $components = array_values($components);
705 if ( $type !=
null ) {
707 foreach( $this->components AS $k => $v ) {
708 if ( $v->GetType() == $type ) {
709 unset($this->components[$k]);
710 if ( isset($this->rendered) ) unset($this->rendered);
714 if ( isset($this->rendered) ) unset($this->rendered);
718 return isset($this->rendered);
721 if ( isset($this->rendered) ) unset($this->rendered);
722 $this->components = array();
734 if ( isset($this->rendered) ) unset($this->rendered);
736 foreach( $new_component AS $k => $v ) {
737 $this->components[] = $v;
748 if ( is_array($new_component) && count($new_component) == 0 )
return;
749 if ( isset($this->rendered) ) unset($this->rendered);
750 if ( is_array($new_component) ) {
751 foreach( $new_component AS $k => $v ) {
752 $this->components[] = $v;
756 $this->components[] = $new_component;
766 foreach( $this->components AS $k => $v ) {
767 if ( ! in_array( $v->GetType(), $keep ) ) {
768 unset($this->components[$k]);
769 if ( isset($this->rendered) ) unset($this->rendered);
772 $v->MaskComponents($keep);
784 foreach( $this->components AS $k => $v ) {
785 $v->MaskProperties($keep, $component_list);
788 if ( !isset($component_list) || in_array($this->
GetType(), $component_list) ) {
789 foreach( $this->properties AS $k => $v ) {
790 if ( ! in_array( $v->name, $keep ) ) {
791 unset($this->properties[$k]);
792 if ( isset($this->rendered) ) unset($this->rendered);
805 $confidential = clone($this);
806 $keep_properties = array(
'DTSTAMP',
'DTSTART',
'RRULE',
'DURATION',
'DTEND',
'DUE',
'UID',
'CLASS',
'TRANSP',
'CREATED',
'LAST-MODIFIED' );
807 $resource_components = array(
'VEVENT',
'VTODO',
'VJOURNAL' );
808 $confidential->MaskComponents(array(
'VTIMEZONE',
'STANDARD',
'DAYLIGHT',
'VEVENT',
'VTODO',
'VJOURNAL' ));
809 $confidential->MaskProperties($keep_properties, $resource_components );
811 if ( isset($confidential->rendered) )
812 unset($confidential->rendered);
814 if ( in_array( $confidential->GetType(), $resource_components ) ) {
815 $confidential->AddProperty(
'SUMMARY', translate(
'Busy') );
817 foreach( $confidential->components AS $k => $v ) {
818 if ( in_array( $v->GetType(), $resource_components ) ) {
819 $v->AddProperty(
'SUMMARY', translate(
'Busy') );
823 return $confidential;
837 return substr($this->
Render($restricted_properties), 0 , -2);
844 function Render( $restricted_properties =
null) {
846 $unrestricted = (!isset($restricted_properties) || count($restricted_properties) == 0);
848 if ( isset($this->rendered) && $unrestricted )
849 return $this->rendered;
851 $rendered =
"BEGIN:$this->type\r\n";
852 foreach( $this->properties AS $k => $v ) {
853 if ( method_exists($v,
'Render') ) {
854 if ( $unrestricted || isset($restricted_properties[$v]) ) $rendered .= $v->Render() .
"\r\n";
857 foreach( $this->components AS $v ) { $rendered .= $v->Render(); }
858 $rendered .=
"END:$this->type\r\n";
860 $rendered = preg_replace(
'{(?<!\r)\n}',
"\r\n", $rendered);
861 if ( $unrestricted ) $this->rendered = $rendered;
877 $properties = array();
878 dbg_error_log(
'iCalendar',
"GetPropertiesByPath: Querying within '%s' for path '%s'", $this->type, $path );
879 if ( !preg_match(
'#(/?)(!?)([^/]+)(/?.*)$#', $path, $matches ) )
return $properties;
881 $adrift = ($matches[1] ==
'');
882 $normal = ($matches[2] ==
'');
883 $ourtest = $matches[3];
884 $therest = $matches[4];
885 dbg_error_log(
'iCalendar',
"GetPropertiesByPath: Matches: %s -- %s -- %s -- %s\n", $matches[1], $matches[2], $matches[3], $matches[4] );
886 if ( $ourtest ==
'*' || (($ourtest == $this->type) === $normal) && $therest !=
'' ) {
887 if ( preg_match(
'#^/(!?)([^/]+)$#', $therest, $matches ) ) {
888 $normmatch = ($matches[1] ==
'');
889 $proptest = $matches[2];
890 foreach( $this->properties AS $k => $v ) {
891 if ( $proptest ==
'*' || (($v->Name() == $proptest) === $normmatch ) ) {
900 foreach( $this->components AS $k => $v ) {
901 $properties = array_merge( $properties, $v->GetPropertiesByPath($therest) );
910 foreach( $this->components AS $k => $v ) {
911 $properties = array_merge( $properties, $v->GetPropertiesByPath($path) );
914 dbg_error_log(
'iCalendar',
"GetPropertiesByPath: Found %d within '%s' for path '%s'\n", count($properties), $this->type, $path );
VCalendar( $extra_properties=null)
CollectParameterValues( $parameter_name)
AddProperty( $new_property, $value=null, $parameters=null)
MaskProperties( $keep, $component_list=null)
ClearComponents( $type=null)
__construct( $content=null)
SetComponents( $new_component, $type=null)
UnwrapComponent( $content)
& FirstNonTimezone( $type=null)
RenderWithoutWrap($restricted_properties=null)
GetPParamValue( $type, $parameter_name)
GetProperties( $type=null)
Render( $restricted_properties=null)
ClearProperties( $type=null)
SetProperties( $new_properties, $type=null)
GetPropertiesByPath( $path)
AddComponent( $new_component)
GetComponents( $type=null, $normal_match=true)
__construct( $propstring=null)
SetParameterValue( $name, $value)
SplitQuoted($str, $sep=',', $limit=0)
Parameters( $newparams=null)
GetParameterValue( $name)