|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00016 class iCalendar_property { 00017 // Properties can have parameters, but cannot have other properties or components 00018 00019 var $parent_component = NULL; 00020 var $value = NULL; 00021 var $parameters = NULL; 00022 var $valid_parameters = NULL; 00023 00024 // These are common for 95% of properties, so define them here and override as necessary 00025 var $val_multi = false; 00026 var $val_default = NULL; 00027 00028 function __construct() { 00029 $this->parameters = array(); 00030 } 00031 00032 // If some property needs extra care with its parameters, override this 00033 // IMPORTANT: the parameter name MUST BE CAPITALIZED! 00034 function is_valid_parameter($parameter, $value) { 00035 00036 if(is_array($value)) { 00037 if(!iCalendar_parameter::multiple_values_allowed($parameter)) { 00038 return false; 00039 } 00040 foreach($value as $item) { 00041 if(!iCalendar_parameter::is_valid_value($this, $parameter, $item)) { 00042 return false; 00043 } 00044 } 00045 return true; 00046 } 00047 00048 return iCalendar_parameter::is_valid_value($this, $parameter, $value); 00049 } 00050 00051 function invariant_holds() { 00052 return true; 00053 } 00054 00055 // If some property is very picky about its values, it should do the work itself 00056 // Only data type validation is done here 00057 function is_valid_value($value) { 00058 if(is_array($value)) { 00059 if(!$this->val_multi) { 00060 return false; 00061 } 00062 else { 00063 foreach($value as $oneval) { 00064 if(!rfc2445_is_valid_value($oneval, $this->val_type)) { 00065 return false; 00066 } 00067 } 00068 } 00069 return true; 00070 } 00071 return rfc2445_is_valid_value($value, $this->val_type); 00072 } 00073 00074 function default_value() { 00075 return $this->val_default; 00076 } 00077 00078 function set_parent_component($componentname) { 00079 if(class_exists('iCalendar_'.strtolower(substr($componentname, 1)))) { 00080 $this->parent_component = strtoupper($componentname); 00081 return true; 00082 } 00083 00084 return false; 00085 } 00086 00087 function set_value($value) { 00088 if($this->is_valid_value($value)) { 00089 // This transparently formats any value type according to the iCalendar specs 00090 if(is_array($value)) { 00091 foreach($value as $key => $item) { 00092 $value[$key] = rfc2445_do_value_formatting($item, $this->val_type); 00093 } 00094 $this->value = implode(',', $value); 00095 } 00096 else { 00097 $this->value = rfc2445_do_value_formatting($value, $this->val_type); 00098 } 00099 00100 return true; 00101 } 00102 return false; 00103 } 00104 00105 function get_value() { 00106 // First of all, assume that we have multiple values 00107 $valarray = explode('\\,', $this->value); 00108 00109 // Undo transparent formatting 00110 $replace_function = create_function('$a', 'return rfc2445_undo_value_formatting($a, '.$this->val_type.');'); 00111 $valarray = array_map($replace_function, $valarray); 00112 00113 // Now, if this property cannot have multiple values, don't return as an array 00114 if(!$this->val_multi) { 00115 return $valarray[0]; 00116 } 00117 00118 // Otherwise return an array even if it has one element, for uniformity 00119 return $valarray; 00120 00121 } 00122 00123 function set_parameter($name, $value) { 00124 00125 // Uppercase 00126 $name = strtoupper($name); 00127 00128 // Are we trying to add a valid parameter? 00129 $xname = false; 00130 if(!isset($this->valid_parameters[$name])) { 00131 // If not, is it an x-name as per RFC 2445? 00132 if(!rfc2445_is_xname($name)) { 00133 return false; 00134 } 00135 // No more checks -- all components are supposed to allow x-name parameters 00136 $xname = true; 00137 } 00138 00139 if(!$this->is_valid_parameter($name, $value)) { 00140 return false; 00141 } 00142 00143 if(is_array($value)) { 00144 foreach($value as $key => $element) { 00145 $value[$key] = iCalendar_parameter::do_value_formatting($name, $element); 00146 } 00147 } 00148 else { 00149 $value = iCalendar_parameter::do_value_formatting($name, $value); 00150 } 00151 00152 $this->parameters[$name] = $value; 00153 00154 // Special case: if we just changed the VALUE parameter, reflect this 00155 // in the object's status so that it only accepts correct type values 00156 if($name == 'VALUE') { 00157 // TODO: what if this invalidates an already-set value? 00158 $this->val_type = constant('RFC2445_TYPE_'.str_replace('-', '_', $value)); 00159 } 00160 00161 return true; 00162 00163 } 00164 00165 function get_parameter($name) { 00166 00167 // Uppercase 00168 $name = strtoupper($name); 00169 00170 if(isset($this->parameters[$name])) { 00171 // If there are any double quotes in the value, invisibly strip them 00172 if(is_array($this->parameters[$name])) { 00173 foreach($this->parameters[$name] as $key => $value) { 00174 if(substr($value, 0, 1) == '"') { 00175 $this->parameters[$name][$key] = substr($value, 1, strlen($value) - 2); 00176 } 00177 } 00178 return $this->parameters[$name]; 00179 } 00180 00181 else { 00182 if(substr($this->parameters[$name], 0, 1) == '"') { 00183 return substr($this->parameters[$name], 1, strlen($this->parameters[$name]) - 2); 00184 } 00185 } 00186 } 00187 00188 return NULL; 00189 } 00190 00191 function serialize() { 00192 $string = $this->name; 00193 00194 if(!empty($this->parameters)) { 00195 foreach($this->parameters as $name => $value) { 00196 $string .= ';'.$name.'='; 00197 if(is_array($value)) { 00198 $string .= implode(',', $value); 00199 } 00200 else { 00201 $string .= $value; 00202 } 00203 } 00204 } 00205 00206 $string .= ':'.$this->value; 00207 00208 return rfc2445_fold($string) . RFC2445_CRLF; 00209 } 00210 } 00211 00212 // 4.7 Calendar Properties 00213 // ----------------------- 00214 00215 class iCalendar_property_calscale extends iCalendar_property { 00216 00217 var $name = 'CALSCALE'; 00218 var $val_type = RFC2445_TYPE_TEXT; 00219 00220 function __construct() { 00221 parent::__construct(); 00222 $this->valid_parameters = array( 00223 RFC2445_XNAME => RFC2445_OPTIONAL 00224 ); 00225 } 00226 00227 function is_valid_value($value) { 00228 // This is case-sensitive 00229 return ($value === 'GREGORIAN'); 00230 } 00231 } 00232 00233 class iCalendar_property_method extends iCalendar_property { 00234 00235 var $name = 'METHOD'; 00236 var $val_type = RFC2445_TYPE_TEXT; 00237 00238 function __construct() { 00239 parent::__construct(); 00240 $this->valid_parameters = array( 00241 RFC2445_XNAME => RFC2445_OPTIONAL 00242 ); 00243 } 00244 00245 function is_valid_value($value) { 00246 // This is case-sensitive 00247 // Methods from RFC 2446 00248 $methods = array('PUBLISH', 'REQUEST', 'REPLY', 'ADD', 'CANCEL', 'REFRESH', 'COUNTER', 'DECLINECOUNTER'); 00249 return in_array($value, $methods); 00250 } 00251 } 00252 00253 class iCalendar_property_prodid extends iCalendar_property { 00254 00255 var $name = 'PRODID'; 00256 var $val_type = RFC2445_TYPE_TEXT; 00257 var $val_default = NULL; 00258 00259 function __construct() { 00260 parent::__construct(); 00261 $this->val_default = '-//John Papaioannou/NONSGML Bennu '._BENNU_VERSION.'//EN'; 00262 00263 $this->valid_parameters = array( 00264 RFC2445_XNAME => RFC2445_OPTIONAL 00265 ); 00266 } 00267 } 00268 00269 class iCalendar_property_version extends iCalendar_property { 00270 00271 var $name = 'VERSION'; 00272 var $val_type = RFC2445_TYPE_TEXT; 00273 var $val_default = '2.0'; 00274 00275 function __construct() { 00276 parent::__construct(); 00277 $this->valid_parameters = array( 00278 RFC2445_XNAME => RFC2445_OPTIONAL 00279 ); 00280 } 00281 00282 function is_valid_value($value) { 00283 return($value === '2.0' || $value === 2.0); 00284 } 00285 00286 } 00287 00288 // 4.8.1 Descriptive Component Properties 00289 // -------------------------------------- 00290 00291 class iCalendar_property_attach extends iCalendar_property { 00292 00293 var $name = 'ATTACH'; 00294 var $val_type = RFC2445_TYPE_URI; 00295 00296 function __construct() { 00297 parent::__construct(); 00298 $this->valid_parameters = array( 00299 'FMTTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00300 'ENCODING' => RFC2445_OPTIONAL | RFC2445_ONCE, 00301 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00302 RFC2445_XNAME => RFC2445_OPTIONAL 00303 ); 00304 } 00305 00306 function invariant_holds() { 00307 if(isset($this->parameters['ENCODING']) && !isset($this->parameters['VALUE'])) { 00308 return false; 00309 } 00310 if(isset($this->parameters['VALUE']) && !isset($this->parameters['ENCODING'])) { 00311 return false; 00312 } 00313 00314 return true; 00315 } 00316 00317 function is_valid_parameter($parameter, $value) { 00318 00319 $parameter = strtoupper($parameter); 00320 00321 if(!parent::is_valid_parameter($parameter, $value)) { 00322 return false; 00323 } 00324 00325 if($parameter === 'ENCODING' && strtoupper($value) != 'BASE64') { 00326 return false; 00327 } 00328 00329 if($parameter === 'VALUE' && strtoupper($value) != 'BINARY') { 00330 return false; 00331 } 00332 00333 return true; 00334 } 00335 } 00336 00337 class iCalendar_property_categories extends iCalendar_property { 00338 00339 var $name = 'CATEGORIES'; 00340 var $val_type = RFC2445_TYPE_TEXT; 00341 var $val_multi = true; 00342 00343 function __construct() { 00344 parent::__construct(); 00345 $this->valid_parameters = array( 00346 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00347 RFC2445_XNAME => RFC2445_OPTIONAL 00348 ); 00349 } 00350 } 00351 00352 class iCalendar_property_class extends iCalendar_property { 00353 00354 var $name = 'CLASS'; 00355 var $val_type = RFC2445_TYPE_TEXT; 00356 var $val_default = 'PUBLIC'; 00357 00358 function __construct() { 00359 parent::__construct(); 00360 $this->valid_parameters = array( 00361 RFC2445_XNAME => RFC2445_OPTIONAL 00362 ); 00363 } 00364 00365 function is_valid_value($value) { 00366 // If this is not an xname, it is case-sensitive 00367 return ($value === 'PUBLIC' || $value === 'PRIVATE' || $value === 'CONFIDENTIAL' || rfc2445_is_xname(strtoupper($value))); 00368 } 00369 } 00370 00371 class iCalendar_property_comment extends iCalendar_property { 00372 00373 var $name = 'COMMENT'; 00374 var $val_type = RFC2445_TYPE_TEXT; 00375 00376 function __construct() { 00377 parent::__construct(); 00378 $this->valid_parameters = array( 00379 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00380 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00381 RFC2445_XNAME => RFC2445_OPTIONAL 00382 ); 00383 } 00384 } 00385 00386 class iCalendar_property_description extends iCalendar_property { 00387 00388 var $name = 'DESCRIPTION'; 00389 var $val_type = RFC2445_TYPE_TEXT; 00390 00391 function __construct() { 00392 parent::__construct(); 00393 $this->valid_parameters = array( 00394 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00395 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00396 RFC2445_XNAME => RFC2445_OPTIONAL 00397 ); 00398 } 00399 } 00400 00401 class iCalendar_property_geo extends iCalendar_property { 00402 00403 var $name = 'GEO'; 00404 var $val_type = RFC2445_TYPE_TEXT; 00405 00406 function __construct() { 00407 parent::__construct(); 00408 $this->valid_parameters = array( 00409 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00410 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00411 RFC2445_XNAME => RFC2445_OPTIONAL 00412 ); 00413 } 00414 00415 function is_valid_value($value) { 00416 // This MUST be two floats separated by a semicolon 00417 if(!is_string($value)) { 00418 return false; 00419 } 00420 00421 $floats = explode(';', $value); 00422 if(count($floats) != 2) { 00423 return false; 00424 } 00425 00426 return rfc2445_is_valid_value($floats[0], RFC2445_TYPE_FLOAT) && rfc2445_is_valid_value($floats[1], RFC2445_TYPE_FLOAT); 00427 } 00428 00429 function set_value($value) { 00430 // Must override this, otherwise the semicolon separating 00431 // the two floats would get auto-quoted, which is illegal 00432 if($this->is_valid_value($value)) { 00433 $this->value = $value; 00434 return true; 00435 } 00436 00437 return false; 00438 } 00439 00440 } 00441 00442 class iCalendar_property_location extends iCalendar_property { 00443 00444 var $name = 'LOCATION'; 00445 var $val_type = RFC2445_TYPE_TEXT; 00446 00447 function __construct() { 00448 parent::__construct(); 00449 $this->valid_parameters = array( 00450 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00451 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00452 RFC2445_XNAME => RFC2445_OPTIONAL 00453 ); 00454 } 00455 } 00456 00457 class iCalendar_property_percent_complete extends iCalendar_property { 00458 00459 var $name = 'PERCENT-COMPLETE'; 00460 var $val_type = RFC2445_TYPE_INTEGER; 00461 00462 function __construct() { 00463 parent::__construct(); 00464 $this->valid_parameters = array( 00465 RFC2445_XNAME => RFC2445_OPTIONAL 00466 ); 00467 } 00468 00469 function is_valid_value($value) { 00470 // Only integers between 0 and 100 inclusive allowed 00471 if(!parent::is_valid_value($value)) { 00472 return false; 00473 } 00474 $value = intval($value); 00475 return ($value >= 0 && $value <= 100); 00476 } 00477 00478 } 00479 00480 class iCalendar_property_priority extends iCalendar_property { 00481 00482 var $name = 'PRIORITY'; 00483 var $val_type = RFC2445_TYPE_INTEGER; 00484 00485 function __construct() { 00486 parent::__construct(); 00487 $this->valid_parameters = array( 00488 RFC2445_XNAME => RFC2445_OPTIONAL 00489 ); 00490 } 00491 00492 function is_valid_value($value) { 00493 // Only integers between 0 and 9 inclusive allowed 00494 if(!parent::is_valid_value($value)) { 00495 return false; 00496 } 00497 00498 $value = intval($value); 00499 return ($value >= 0 && $value <= 9); 00500 } 00501 } 00502 00503 class iCalendar_property_resources extends iCalendar_property { 00504 00505 var $name = 'RESOURCES'; 00506 var $val_type = RFC2445_TYPE_TEXT; 00507 var $val_multi = true; 00508 00509 function __construct() { 00510 parent::__construct(); 00511 $this->valid_parameters = array( 00512 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00513 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00514 RFC2445_XNAME => RFC2445_OPTIONAL 00515 ); 00516 } 00517 } 00518 00519 class iCalendar_property_status extends iCalendar_property { 00520 00521 var $name = 'STATUS'; 00522 var $val_type = RFC2445_TYPE_TEXT; 00523 00524 function __construct() { 00525 parent::__construct(); 00526 $this->valid_parameters = array( 00527 RFC2445_XNAME => RFC2445_OPTIONAL 00528 ); 00529 } 00530 00531 function is_valid_value($value) { 00532 // This is case-sensitive 00533 switch ($this->parent_component) { 00534 case 'VEVENT': 00535 $allowed = array('TENTATIVE', 'CONFIRMED', 'CANCELLED'); 00536 break; 00537 case 'VTODO': 00538 $allowed = array('NEEDS-ACTION', 'COMPLETED', 'IN-PROCESS', 'CANCELLED'); 00539 break; 00540 case 'VJOURNAL': 00541 $allowed = array('DRAFT', 'FINAL', 'CANCELLED'); 00542 break; 00543 } 00544 return in_array($value, $allowed); 00545 00546 } 00547 00548 } 00549 00550 class iCalendar_property_summary extends iCalendar_property { 00551 00552 var $name = 'SUMMARY'; 00553 var $val_type = RFC2445_TYPE_TEXT; 00554 00555 function __construct() { 00556 parent::__construct(); 00557 $this->valid_parameters = array( 00558 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00559 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00560 RFC2445_XNAME => RFC2445_OPTIONAL 00561 ); 00562 } 00563 } 00564 00565 // 4.8.2 Date and Time Component Properties 00566 // ---------------------------------------- 00567 00568 class iCalendar_property_completed extends iCalendar_property { 00569 00570 var $name = 'COMPLETED'; 00571 var $val_type = RFC2445_TYPE_DATE_TIME; 00572 00573 function __construct() { 00574 parent::__construct(); 00575 $this->valid_parameters = array( 00576 RFC2445_XNAME => RFC2445_OPTIONAL 00577 ); 00578 } 00579 00580 function is_valid_value($value) { 00581 if(!parent::is_valid_value($value)) { 00582 return false; 00583 } 00584 // Time MUST be in UTC format 00585 return(substr($value, -1) == 'Z'); 00586 } 00587 } 00588 00589 class iCalendar_property_dtend extends iCalendar_property { 00590 00591 var $name = 'DTEND'; 00592 var $val_type = RFC2445_TYPE_DATE_TIME; 00593 00594 function __construct() { 00595 parent::__construct(); 00596 $this->valid_parameters = array( 00597 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00598 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 00599 RFC2445_XNAME => RFC2445_OPTIONAL 00600 ); 00601 } 00602 00603 function is_valid_value($value) { 00604 if(!parent::is_valid_value($value)) { 00605 return false; 00606 } 00607 00608 // If present in a FREEBUSY component, must be in UTC format 00609 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 00610 return false; 00611 } 00612 00613 return true; 00614 00615 } 00616 00617 function is_valid_parameter($parameter, $value) { 00618 00619 $parameter = strtoupper($parameter); 00620 00621 if(!parent::is_valid_parameter($parameter, $value)) { 00622 return false; 00623 } 00624 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 00625 return false; 00626 } 00627 00628 return true; 00629 } 00630 } 00631 00632 class iCalendar_property_due extends iCalendar_property { 00633 00634 var $name = 'DUE'; 00635 var $val_type = RFC2445_TYPE_DATE_TIME; 00636 00637 function __construct() { 00638 parent::__construct(); 00639 $this->valid_parameters = array( 00640 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00641 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 00642 RFC2445_XNAME => RFC2445_OPTIONAL 00643 ); 00644 } 00645 00646 function is_valid_value($value) { 00647 if(!parent::is_valid_value($value)) { 00648 return false; 00649 } 00650 00651 // If present in a FREEBUSY component, must be in UTC format 00652 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 00653 return false; 00654 } 00655 00656 return true; 00657 00658 } 00659 00660 function is_valid_parameter($parameter, $value) { 00661 00662 $parameter = strtoupper($parameter); 00663 00664 if(!parent::is_valid_parameter($parameter, $value)) { 00665 return false; 00666 } 00667 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 00668 return false; 00669 } 00670 00671 return true; 00672 } 00673 } 00674 00675 class iCalendar_property_dtstart extends iCalendar_property { 00676 00677 var $name = 'DTSTART'; 00678 var $val_type = RFC2445_TYPE_DATE_TIME; 00679 00680 function __construct() { 00681 parent::__construct(); 00682 $this->valid_parameters = array( 00683 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00684 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 00685 RFC2445_XNAME => RFC2445_OPTIONAL 00686 ); 00687 } 00688 00689 // TODO: unimplemented stuff when parent is a VTIMEZONE component 00690 00691 function is_valid_value($value) { 00692 if(!parent::is_valid_value($value)) { 00693 return false; 00694 } 00695 00696 // If present in a FREEBUSY component, must be in UTC format 00697 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 00698 return false; 00699 } 00700 00701 return true; 00702 } 00703 00704 function is_valid_parameter($parameter, $value) { 00705 00706 $parameter = strtoupper($parameter); 00707 00708 if(!parent::is_valid_parameter($parameter, $value)) { 00709 return false; 00710 } 00711 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 00712 return false; 00713 } 00714 00715 return true; 00716 } 00717 } 00718 00719 class iCalendar_property_duration extends iCalendar_property { 00720 00721 var $name = 'DURATION'; 00722 var $val_type = RFC2445_TYPE_DURATION; 00723 00724 function __construct() { 00725 parent::__construct(); 00726 $this->valid_parameters = array( 00727 RFC2445_XNAME => RFC2445_OPTIONAL 00728 ); 00729 } 00730 00731 function is_valid_value($value) { 00732 if(!parent::is_valid_value($value)) { 00733 return false; 00734 } 00735 00736 // Value must be positive 00737 return ($value{0} != '-'); 00738 } 00739 } 00740 00741 class iCalendar_property_freebusy extends iCalendar_property { 00742 00743 var $name = 'FREEBUSY'; 00744 var $val_type = RFC2445_TYPE_PERIOD; 00745 var $val_multi = true; 00746 00747 function __construct() { 00748 parent::__construct(); 00749 $this->valid_parameters = array( 00750 'FBTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00751 RFC2445_XNAME => RFC2445_OPTIONAL 00752 ); 00753 } 00754 00755 function is_valid_value($value) { 00756 if(!parent::is_valid_value($value)) { 00757 return false; 00758 } 00759 00760 $pos = strpos($value, '/'); // We know there's only one / in there 00761 if($value{$pos - 1} != 'Z') { 00762 // Start time MUST be in UTC 00763 return false; 00764 } 00765 if($value{$pos + 1} != 'P' && substr($value, -1) != 'Z') { 00766 // If the second part is not a period, it MUST be in UTC 00767 return false; 00768 } 00769 00770 return true; 00771 } 00772 00773 // TODO: these properties SHOULD be shorted in ascending order (by start time and end time as tiebreak) 00774 } 00775 00776 class iCalendar_property_transp extends iCalendar_property { 00777 00778 var $name = 'TRANSP'; 00779 var $val_type = RFC2445_TYPE_TEXT; 00780 var $val_default = 'OPAQUE'; 00781 00782 function __construct() { 00783 parent::__construct(); 00784 $this->valid_parameters = array( 00785 RFC2445_XNAME => RFC2445_OPTIONAL 00786 ); 00787 } 00788 00789 function is_valid_value($value) { 00790 return ($value === 'TRANSPARENT' || $value === 'OPAQUE'); 00791 } 00792 } 00793 00794 // TODO: 4.8.3 timezone component properties 00795 00796 00797 // 4.8.4 Relationship Component Properties 00798 // --------------------------------------- 00799 00800 class iCalendar_property_attendee extends iCalendar_property { 00801 00802 var $name = 'ATTENDEE'; 00803 var $val_type = RFC2445_TYPE_CAL_ADDRESS; 00804 00805 // TODO: MUST NOT be specified when the calendar object has METHOD=PUBLISH 00806 // TODO: standard has lots of detail here, make triple sure that we eventually conform 00807 00808 function __construct() { 00809 parent::__construct(); 00810 $this->valid_parameters = array( 00811 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00812 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE, 00813 'ROLE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00814 'PARTSTAT' => RFC2445_OPTIONAL | RFC2445_ONCE, 00815 'RSVP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00816 'CUTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00817 'MEMBER' => RFC2445_OPTIONAL | RFC2445_ONCE, 00818 'DELEGATED-TO' => RFC2445_OPTIONAL | RFC2445_ONCE, 00819 'DELEGATED-FROM' => RFC2445_OPTIONAL | RFC2445_ONCE, 00820 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE, 00821 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE, 00822 RFC2445_XNAME => RFC2445_OPTIONAL 00823 ); 00824 } 00825 00826 function set_parent_component($componentname) { 00827 if(!parent::set_parent_component($componentname)) { 00828 return false; 00829 } 00830 00831 if($this->parent_component == 'VFREEBUSY' || $this->parent_component == 'VALARM') { 00832 // Most parameters become invalid in this case, the full allowed set is now: 00833 $this->valid_parameters = array( 00834 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00835 RFC2445_XNAME => RFC2445_OPTIONAL 00836 ); 00837 } 00838 00839 return false; 00840 } 00841 00842 } 00843 00844 class iCalendar_property_contact extends iCalendar_property { 00845 00846 var $name = 'CONTACT'; 00847 var $val_type = RFC2445_TYPE_TEXT; 00848 00849 function __construct() { 00850 parent::__construct(); 00851 $this->valid_parameters = array( 00852 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 00853 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00854 RFC2445_XNAME => RFC2445_OPTIONAL 00855 ); 00856 } 00857 } 00858 00859 class iCalendar_property_organizer extends iCalendar_property { 00860 00861 var $name = 'ORGANIZER'; 00862 var $val_type = RFC2445_TYPE_CAL_ADDRESS; 00863 00864 function __construct() { 00865 parent::__construct(); 00866 $this->valid_parameters = array( 00867 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE, 00868 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE, 00869 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE, 00870 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00871 RFC2445_XNAME => RFC2445_OPTIONAL 00872 ); 00873 } 00874 00875 // TODO: 00876 /* 00877 Conformance: This property MUST be specified in an iCalendar object 00878 that specifies a group scheduled calendar entity. This property MUST 00879 be specified in an iCalendar object that specifies the publication of 00880 a calendar user's busy time. This property MUST NOT be specified in 00881 an iCalendar object that specifies only a time zone definition or 00882 that defines calendar entities that are not group scheduled entities, 00883 but are entities only on a single user's calendar. 00884 */ 00885 00886 } 00887 00888 class iCalendar_property_recurrence_id extends iCalendar_property { 00889 00890 // TODO: can only be specified when defining recurring components in the calendar 00891 /* 00892 Conformance: This property can be specified in an iCalendar object 00893 containing a recurring calendar component. 00894 00895 Description: The full range of calendar components specified by a 00896 recurrence set is referenced by referring to just the "UID" property 00897 value corresponding to the calendar component. The "RECURRENCE-ID" 00898 property allows the reference to an individual instance within the 00899 recurrence set. 00900 */ 00901 00902 var $name = 'RECURRENCE-ID'; 00903 var $val_type = RFC2445_TYPE_DATE_TIME; 00904 00905 function __construct() { 00906 parent::__construct(); 00907 $this->valid_parameters = array( 00908 'RANGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00909 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 00910 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00911 RFC2445_XNAME => RFC2445_OPTIONAL 00912 ); 00913 } 00914 00915 function is_valid_parameter($parameter, $value) { 00916 00917 $parameter = strtoupper($parameter); 00918 00919 if(!parent::is_valid_parameter($parameter, $value)) { 00920 return false; 00921 } 00922 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 00923 return false; 00924 } 00925 00926 return true; 00927 } 00928 00929 } 00930 00931 class iCalendar_property_related_to extends iCalendar_property { 00932 00933 var $name = 'RELATED-TO'; 00934 var $val_type = RFC2445_TYPE_TEXT; 00935 00936 // TODO: the value of this property must reference another component's UID 00937 00938 function __construct() { 00939 parent::__construct(); 00940 $this->valid_parameters = array( 00941 'RELTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00942 RFC2445_XNAME => RFC2445_OPTIONAL 00943 ); 00944 } 00945 } 00946 00947 class iCalendar_property_url extends iCalendar_property { 00948 00949 var $name = 'URL'; 00950 var $val_type = RFC2445_TYPE_URI; 00951 00952 function __construct() { 00953 parent::__construct(); 00954 $this->valid_parameters = array( 00955 RFC2445_XNAME => RFC2445_OPTIONAL 00956 ); 00957 } 00958 } 00959 00960 class iCalendar_property_uid extends iCalendar_property { 00961 00962 var $name = 'UID'; 00963 var $val_type = RFC2445_TYPE_TEXT; 00964 00965 function __construct() { 00966 parent::__construct(); 00967 $this->valid_parameters = array( 00968 RFC2445_XNAME => RFC2445_OPTIONAL 00969 ); 00970 00971 // The exception to the rule: this is not a static value, so we 00972 // generate it on-the-fly here. Guaranteed to be different for 00973 // each instance of this property, too. Nice. 00974 $this->val_default = Bennu::generate_guid(); 00975 } 00976 } 00977 00978 // 4.8.5 Recurrence Component Properties 00979 // ------------------------------------- 00980 00981 class iCalendar_property_exdate extends iCalendar_property { 00982 00983 var $name = 'EXDATE'; 00984 var $val_type = RFC2445_TYPE_DATE_TIME; 00985 var $val_multi = true; 00986 00987 function __construct() { 00988 parent::__construct(); 00989 $this->valid_parameters = array( 00990 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 00991 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 00992 RFC2445_XNAME => RFC2445_OPTIONAL 00993 ); 00994 } 00995 00996 function is_valid_parameter($parameter, $value) { 00997 00998 $parameter = strtoupper($parameter); 00999 01000 if(!parent::is_valid_parameter($parameter, $value)) { 01001 return false; 01002 } 01003 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 01004 return false; 01005 } 01006 01007 return true; 01008 } 01009 01010 } 01011 01012 class iCalendar_property_exrule extends iCalendar_property { 01013 01014 var $name = 'EXRULE'; 01015 var $val_type = RFC2445_TYPE_RECUR; 01016 01017 function __construct() { 01018 parent::__construct(); 01019 $this->valid_parameters = array( 01020 RFC2445_XNAME => RFC2445_OPTIONAL 01021 ); 01022 } 01023 } 01024 01025 class iCalendar_property_rdate extends iCalendar_property { 01026 01027 var $name = 'RDATE'; 01028 var $val_type = RFC2445_TYPE_DATE_TIME; 01029 var $val_multi = true; 01030 01031 function __construct() { 01032 parent::__construct(); 01033 $this->valid_parameters = array( 01034 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 01035 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 01036 RFC2445_XNAME => RFC2445_OPTIONAL 01037 ); 01038 } 01039 01040 function is_valid_parameter($parameter, $value) { 01041 01042 $parameter = strtoupper($parameter); 01043 01044 if(!parent::is_valid_parameter($parameter, $value)) { 01045 return false; 01046 } 01047 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME' || $value == 'PERIOD')) { 01048 return false; 01049 } 01050 01051 return true; 01052 } 01053 01054 } 01055 01056 class iCalendar_property_rrule extends iCalendar_property { 01057 01058 var $name = 'RRULE'; 01059 var $val_type = RFC2445_TYPE_RECUR; 01060 01061 function __construct() { 01062 parent::__construct(); 01063 $this->valid_parameters = array( 01064 RFC2445_XNAME => RFC2445_OPTIONAL 01065 ); 01066 } 01067 } 01068 01069 // 4.8.6 Alarm Component Properties 01070 // ------------------------------------------- 01071 class iCalendar_property_action extends iCalendar_property { 01072 var $name = 'ACTION'; 01073 var $val_type = RFC2445_TYPE_TEXT; 01074 01075 function __construct() { 01076 parent::__construct(); 01077 $this->valid_parameters = array( 01078 RFC2445_XNAME => RFC2445_OPTIONAL 01079 ); 01080 } 01081 01082 function is_valid_value($value) { 01083 if(!parent::is_valid_value($value)) { 01084 return false; 01085 } 01086 01087 // Value must be one of the following, or an x-name. 01088 $valid_values = array('ACTION', 'DISPLAY', 'EMAIL', 'PROCEDURE'); 01089 return(in_array($value, $valid_values) || rfc2445_is_xname($value)); 01090 01091 } 01092 } 01093 01094 class iCalendar_property_repeat extends iCalendar_property { 01095 var $name = 'REPEAT'; 01096 var $val_type = RFC2445_TYPE_INTEGER; 01097 01098 function __construct() { 01099 parent::__construct(); 01100 $this->valid_parameters = array( 01101 RFC2445_XNAME => RFC2445_OPTIONAL 01102 ); 01103 } 01104 } 01105 01106 class iCalendar_property_trigger extends iCalendar_property { 01107 var $name = 'TRIGGER'; 01108 var $val_type = RFC2445_TYPE_TEXT; 01109 01110 function __construct() { 01111 parent::__construct(); 01112 $this->valid_parameters = array( 01113 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 01114 'RELATED' => RFC2445_OPTIONAL | RFC2445_ONCE, 01115 RFC2445_XNAME => RFC2445_OPTIONAL 01116 ); 01117 } 01118 01119 function is_valid_value($value) { 01120 if(!parent::is_valid_value($value)) { 01121 return false; 01122 } 01123 // Must either be DURATION or DATE_TIME type 01124 return(rfc2445_is_valid_value($value, RFC2445_TYPE_DURATION) 01125 || rfc2445_is_valid_value($value, RFC2445_TYPE_DATE_TIME)); 01126 } 01127 } 01128 01129 01130 01131 // 4.8.7 Change Management Component Properties 01132 // -------------------------------------------- 01133 01134 class iCalendar_property_created extends iCalendar_property { 01135 01136 var $name = 'CREATED'; 01137 var $val_type = RFC2445_TYPE_DATE_TIME; 01138 01139 function __construct() { 01140 parent::__construct(); 01141 $this->valid_parameters = array( 01142 RFC2445_XNAME => RFC2445_OPTIONAL 01143 ); 01144 } 01145 01146 function is_valid_value($value) { 01147 if(!parent::is_valid_value($value)) { 01148 return false; 01149 } 01150 // Time MUST be in UTC format 01151 return(substr($value, -1) == 'Z'); 01152 } 01153 } 01154 01155 class iCalendar_property_dtstamp extends iCalendar_property { 01156 01157 var $name = 'DTSTAMP'; 01158 var $val_type = RFC2445_TYPE_DATE_TIME; 01159 01160 function __construct() { 01161 parent::__construct(); 01162 $this->valid_parameters = array( 01163 RFC2445_XNAME => RFC2445_OPTIONAL 01164 ); 01165 } 01166 01167 function is_valid_value($value) { 01168 if(!parent::is_valid_value($value)) { 01169 return false; 01170 } 01171 // Time MUST be in UTC format 01172 return(substr($value, -1) == 'Z'); 01173 } 01174 } 01175 01176 class iCalendar_property_last_modified extends iCalendar_property { 01177 01178 var $name = 'LAST-MODIFIED'; 01179 var $val_type = RFC2445_TYPE_DATE_TIME; 01180 01181 function __construct() { 01182 parent::__construct(); 01183 $this->valid_parameters = array( 01184 RFC2445_XNAME => RFC2445_OPTIONAL 01185 ); 01186 } 01187 01188 function is_valid_value($value) { 01189 if(!parent::is_valid_value($value)) { 01190 return false; 01191 } 01192 // Time MUST be in UTC format 01193 return(substr($value, -1) == 'Z'); 01194 } 01195 } 01196 01197 class iCalendar_property_sequence extends iCalendar_property { 01198 01199 var $name = 'SEQUENCE'; 01200 var $val_type = RFC2445_TYPE_INTEGER; 01201 var $val_default = 0; 01202 01203 function __construct() { 01204 parent::__construct(); 01205 $this->valid_parameters = array( 01206 RFC2445_XNAME => RFC2445_OPTIONAL 01207 ); 01208 } 01209 01210 function is_valid_value($value) { 01211 if(!parent::is_valid_value($value)) { 01212 return false; 01213 } 01214 $value = intval($value); 01215 return ($value >= 0); 01216 } 01217 } 01218 01219 // 4.8.8 Miscellaneous Component Properties 01220 // ---------------------------------------- 01221 01222 class iCalendar_property_x extends iCalendar_property { 01223 01224 var $name = RFC2445_XNAME; 01225 var $val_type = NULL; 01226 01227 function __construct() { 01228 parent::__construct(); 01229 $this->valid_parameters = array( 01230 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 01231 RFC2445_XNAME => RFC2445_OPTIONAL 01232 ); 01233 } 01234 01235 function set_name($name) { 01236 01237 $name = strtoupper($name); 01238 01239 if(rfc2445_is_xname($name)) { 01240 $this->name = $name; 01241 return true; 01242 } 01243 01244 return false; 01245 } 01246 } 01247 01248 class iCalendar_property_request_status extends iCalendar_property { 01249 01250 // IMPORTANT NOTE: This property value includes TEXT fields 01251 // separated by semicolons. Unfortunately, auto-value-formatting 01252 // cannot be used in this case. As an exception, the value passed 01253 // to this property MUST be already escaped. 01254 01255 var $name = 'REQUEST-STATUS'; 01256 var $val_type = RFC2445_TYPE_TEXT; 01257 01258 function __construct() { 01259 parent::__construct(); 01260 $this->valid_parameters = array( 01261 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 01262 RFC2445_XNAME => RFC2445_OPTIONAL 01263 ); 01264 } 01265 01266 function is_valid_value($value) { 01267 if(!is_string($value) || empty($value)) { 01268 return false; 01269 } 01270 01271 $len = strlen($value); 01272 $parts = array(); 01273 $from = 0; 01274 $escch = false; 01275 01276 for($i = 0; $i < $len; ++$i) { 01277 if($value{$i} == ';' && !$escch) { 01278 // Token completed 01279 $parts[] = substr($value, $from, $i - $from); 01280 $from = $i + 1; 01281 continue; 01282 } 01283 $escch = ($value{$i} == '\\'); 01284 } 01285 // Add one last token with the remaining text; if the value 01286 // ended with a ';' it was illegal, so check that this token 01287 // is not the empty string. 01288 $parts[] = substr($value, $from); 01289 01290 $count = count($parts); 01291 01292 // May have 2 or 3 tokens (last one is optional) 01293 if($count != 2 && $count != 3) { 01294 return false; 01295 } 01296 01297 // REMEMBER: if ANY part is empty, we have an illegal value 01298 01299 // First token must be hierarchical numeric status (3 levels max) 01300 if(strlen($parts[0]) == 0) { 01301 return false; 01302 } 01303 01304 if($parts[0]{0} < '1' || $parts[0]{0} > '4') { 01305 return false; 01306 } 01307 01308 $len = strlen($parts[0]); 01309 01310 // Max 3 levels, and can't end with a period 01311 if($len > 5 || $parts[0]{$len - 1} == '.') { 01312 return false; 01313 } 01314 01315 for($i = 1; $i < $len; ++$i) { 01316 if(($i & 1) == 1 && $parts[0]{$i} != '.') { 01317 // Even-indexed chars must be periods 01318 return false; 01319 } 01320 else if(($i & 1) == 0 && ($parts[0]{$i} < '0' || $parts[0]{$i} > '9')) { 01321 // Odd-indexed chars must be numbers 01322 return false; 01323 } 01324 } 01325 01326 // Second and third tokens must be TEXT, and already escaped, so 01327 // they are not allowed to have UNESCAPED semicolons, commas, slashes, 01328 // or any newlines at all 01329 01330 for($i = 1; $i < $count; ++$i) { 01331 if(strpos($parts[$i], "\n") !== false) { 01332 return false; 01333 } 01334 01335 $len = strlen($parts[$i]); 01336 if($len == 0) { 01337 // Cannot be empty 01338 return false; 01339 } 01340 01341 $parts[$i] .= '#'; // This guard token saves some conditionals in the loop 01342 01343 for($j = 0; $j < $len; ++$j) { 01344 $thischar = $parts[$i]{$j}; 01345 $nextchar = $parts[$i]{$j + 1}; 01346 if($thischar == '\\') { 01347 // Next char must now be one of ";,\nN" 01348 if($nextchar != ';' && $nextchar != ',' && $nextchar != '\\' && 01349 $nextchar != 'n' && $nextchar != 'N') { 01350 return false; 01351 } 01352 01353 // OK, this escaped sequence is correct, bypass next char 01354 ++$j; 01355 continue; 01356 } 01357 if($thischar == ';' || $thischar == ',' || $thischar == '\\') { 01358 // This wasn't escaped as it should 01359 return false; 01360 } 01361 } 01362 } 01363 01364 return true; 01365 } 01366 01367 function set_value($value) { 01368 // Must override this, otherwise the value would be quoted again 01369 if($this->is_valid_value($value)) { 01370 $this->value = $value; 01371 return true; 01372 } 01373 01374 return false; 01375 } 01376 01377 } 01378 01379 class iCalendar_property_tzid extends iCalendar_property { 01380 01381 var $name = 'TZID'; 01382 var $val_type = RFC2445_TYPE_TEXT; 01383 01384 function __construct() { 01385 parent::__construct(); 01386 $this->valid_parameters = array( 01387 RFC2445_XNAME => RFC2445_OPTIONAL 01388 ); 01389 } 01390 01391 function is_valid_value($value) { 01392 if(!parent::is_valid_value($value)) { 01393 return false; 01394 } else { 01395 return true; 01396 } 01397 } 01398 } 01399 01400 class iCalendar_property_tzname extends iCalendar_property { 01401 01402 var $name = 'TZNAME'; 01403 var $val_type = RFC2445_TYPE_TEXT; 01404 01405 function __construct() { 01406 parent::__construct(); 01407 $this->valid_parameters = array( 01408 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 01409 RFC2445_XNAME => RFC2445_OPTIONAL 01410 ); 01411 } 01412 01413 function is_valid_value($value) { 01414 if(!parent::is_valid_value($value)) { 01415 return false; 01416 } else { 01417 return true; 01418 } 01419 } 01420 } 01421 01422 class iCalendar_property_tzoffsetfrom extends iCalendar_property { 01423 01424 var $name = 'TZOFFSETFROM'; 01425 var $val_type = RFC2445_TYPE_UTC_OFFSET; 01426 01427 function __construct() { 01428 parent::__construct(); 01429 $this->valid_parameters = array( 01430 RFC2445_XNAME => RFC2445_OPTIONAL 01431 ); 01432 } 01433 01434 function is_valid_value($value) { 01435 if(!parent::is_valid_value($value)) { 01436 return false; 01437 } else { 01438 return true; 01439 } 01440 } 01441 } 01442 01443 class iCalendar_property_tzoffsetto extends iCalendar_property { 01444 01445 var $name = 'TZOFFSETTO'; 01446 var $val_type = RFC2445_TYPE_UTC_OFFSET; 01447 01448 function __construct() { 01449 parent::__construct(); 01450 $this->valid_parameters = array( 01451 RFC2445_XNAME => RFC2445_OPTIONAL 01452 ); 01453 } 01454 01455 function is_valid_value($value) { 01456 if(!parent::is_valid_value($value)) { 01457 return false; 01458 } else { 01459 return true; 01460 } 01461 } 01462 } 01463 01464 01465 01466 ####################### 01467 /* 01468 class iCalendar_property_class extends iCalendar_property { 01469 01470 var $name = 'CLASS'; 01471 var $val_type = RFC2445_TYPE_TEXT; 01472 01473 function __construct() { 01474 parent::__construct(); 01475 $this->valid_parameters = array( 01476 RFC2445_XNAME => RFC2445_OPTIONAL 01477 ); 01478 } 01479 } 01480 */ 01481