| [ Index ] |
PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008] |
[Summary view] [Print] [Text view]
1 <?php // $Id: iCalendar_properties.php,v 1.1 2006/01/13 15:06:25 defacer Exp $ 2 3 /** 4 * BENNU - PHP iCalendar library 5 * (c) 2005-2006 Ioannis Papaioannou (pj@moodle.org). All rights reserved. 6 * 7 * Released under the LGPL. 8 * 9 * See http://bennu.sourceforge.net/ for more information and downloads. 10 * 11 * @author Ioannis Papaioannou 12 * @version $Id: iCalendar_properties.php,v 1.1 2006/01/13 15:06:25 defacer Exp $ 13 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 14 */ 15 16 class iCalendar_property { 17 // Properties can have parameters, but cannot have other properties or components 18 19 var $parent_component = NULL; 20 var $value = NULL; 21 var $parameters = NULL; 22 var $valid_parameters = NULL; 23 24 // These are common for 95% of properties, so define them here and override as necessary 25 var $val_multi = false; 26 var $val_default = NULL; 27 28 function iCalendar_property() { 29 $this->construct(); 30 } 31 32 function construct() { 33 $this->parameters = array(); 34 } 35 36 // If some property needs extra care with its parameters, override this 37 // IMPORTANT: the parameter name MUST BE CAPITALIZED! 38 function is_valid_parameter($parameter, $value) { 39 40 if(is_array($value)) { 41 if(!iCalendar_parameter::multiple_values_allowed($parameter)) { 42 return false; 43 } 44 foreach($value as $item) { 45 if(!iCalendar_parameter::is_valid_value($this, $parameter, $item)) { 46 return false; 47 } 48 } 49 return true; 50 } 51 52 return iCalendar_parameter::is_valid_value($this, $parameter, $value); 53 } 54 55 function invariant_holds() { 56 return true; 57 } 58 59 // If some property is very picky about its values, it should do the work itself 60 // Only data type validation is done here 61 function is_valid_value($value) { 62 if(is_array($value)) { 63 if(!$this->val_multi) { 64 return false; 65 } 66 else { 67 foreach($value as $oneval) { 68 if(!rfc2445_is_valid_value($oneval, $this->val_type)) { 69 return false; 70 } 71 } 72 } 73 return true; 74 } 75 return rfc2445_is_valid_value($value, $this->val_type); 76 } 77 78 function default_value() { 79 return $this->val_default; 80 } 81 82 function set_parent_component($componentname) { 83 if(class_exists('iCalendar_'.strtolower(substr($componentname, 1)))) { 84 $this->parent_component = strtoupper($componentname); 85 return true; 86 } 87 88 return false; 89 } 90 91 function set_value($value) { 92 if($this->is_valid_value($value)) { 93 // This transparently formats any value type according to the iCalendar specs 94 if(is_array($value)) { 95 foreach($value as $key => $item) { 96 $value[$key] = rfc2445_do_value_formatting($item, $this->val_type); 97 } 98 $this->value = implode(',', $value); 99 } 100 else { 101 $this->value = rfc2445_do_value_formatting($value, $this->val_type); 102 } 103 104 return true; 105 } 106 return false; 107 } 108 109 function get_value() { 110 // First of all, assume that we have multiple values 111 $valarray = explode('\\,', $this->value); 112 113 // Undo transparent formatting 114 $replace_function = create_function('$a', 'return rfc2445_undo_value_formatting($a, '.$this->val_type.');'); 115 $valarray = array_map($replace_function, $valarray); 116 117 // Now, if this property cannot have multiple values, don't return as an array 118 if(!$this->val_multi) { 119 return $valarray[0]; 120 } 121 122 // Otherwise return an array even if it has one element, for uniformity 123 return $valarray; 124 125 } 126 127 function set_parameter($name, $value) { 128 129 // Uppercase 130 $name = strtoupper($name); 131 132 // Are we trying to add a valid parameter? 133 $xname = false; 134 if(!isset($this->valid_parameters[$name])) { 135 // If not, is it an x-name as per RFC 2445? 136 if(!rfc2445_is_xname($name)) { 137 return false; 138 } 139 // No more checks -- all components are supposed to allow x-name parameters 140 $xname = true; 141 } 142 143 if(!$this->is_valid_parameter($name, $value)) { 144 return false; 145 } 146 147 if(is_array($value)) { 148 foreach($value as $key => $element) { 149 $value[$key] = iCalendar_parameter::do_value_formatting($name, $element); 150 } 151 } 152 else { 153 $value = iCalendar_parameter::do_value_formatting($name, $value); 154 } 155 156 $this->parameters[$name] = $value; 157 158 // Special case: if we just changed the VALUE parameter, reflect this 159 // in the object's status so that it only accepts correct type values 160 if($name == 'VALUE') { 161 // TODO: what if this invalidates an already-set value? 162 $this->val_type = constant('RFC2445_TYPE_'.str_replace('-', '_', $value)); 163 } 164 165 return true; 166 167 } 168 169 function get_parameter($name) { 170 171 // Uppercase 172 $name = strtoupper($name); 173 174 if(isset($this->parameters[$name])) { 175 // If there are any double quotes in the value, invisibly strip them 176 if(is_array($this->parameters[$name])) { 177 foreach($this->parameters[$name] as $key => $value) { 178 if(substr($value, 0, 1) == '"') { 179 $this->parameters[$name][$key] = substr($value, 1, strlen($value) - 2); 180 } 181 } 182 return $this->parameters[$name]; 183 } 184 185 else { 186 if(substr($this->parameters[$name], 0, 1) == '"') { 187 return substr($this->parameters[$name], 1, strlen($this->parameters[$name]) - 2); 188 } 189 } 190 } 191 192 return NULL; 193 } 194 195 function serialize() { 196 $string = $this->name; 197 198 if(!empty($this->parameters)) { 199 foreach($this->parameters as $name => $value) { 200 $string .= ';'.$name.'='; 201 if(is_array($value)) { 202 $string .= implode(',', $value); 203 } 204 else { 205 $string .= $value; 206 } 207 } 208 } 209 210 $string .= ':'.$this->value; 211 212 return rfc2445_fold($string) . RFC2445_CRLF; 213 } 214 } 215 216 // 4.7 Calendar Properties 217 // ----------------------- 218 219 class iCalendar_property_calscale extends iCalendar_property { 220 221 var $name = 'CALSCALE'; 222 var $val_type = RFC2445_TYPE_TEXT; 223 224 function construct() { 225 $this->valid_parameters = array( 226 RFC2445_XNAME => RFC2445_OPTIONAL 227 ); 228 } 229 230 function is_valid_value($value) { 231 // This is case-sensitive 232 return ($value === 'GREGORIAN'); 233 } 234 } 235 236 class iCalendar_property_method extends iCalendar_property { 237 238 var $name = 'METHOD'; 239 var $val_type = RFC2445_TYPE_TEXT; 240 241 function construct() { 242 $this->valid_parameters = array( 243 RFC2445_XNAME => RFC2445_OPTIONAL 244 ); 245 } 246 247 function is_valid_value($value) { 248 // This is case-sensitive 249 // Methods from RFC 2446 250 $methods = array('PUBLISH', 'REQUEST', 'REPLY', 'ADD', 'CANCEL', 'REFRESH', 'COUNTER', 'DECLINECOUNTER'); 251 return in_array($value, $methods); 252 } 253 } 254 255 class iCalendar_property_prodid extends iCalendar_property { 256 257 var $name = 'PRODID'; 258 var $val_type = RFC2445_TYPE_TEXT; 259 var $val_default = NULL; 260 261 function construct() { 262 $this->val_default = '-//John Papaioannou/NONSGML Bennu '._BENNU_VERSION.'//EN'; 263 264 $this->valid_parameters = array( 265 RFC2445_XNAME => RFC2445_OPTIONAL 266 ); 267 } 268 } 269 270 class iCalendar_property_version extends iCalendar_property { 271 272 var $name = 'VERSION'; 273 var $val_type = RFC2445_TYPE_TEXT; 274 var $val_default = '2.0'; 275 276 function construct() { 277 $this->valid_parameters = array( 278 RFC2445_XNAME => RFC2445_OPTIONAL 279 ); 280 } 281 282 function is_valid_value($value) { 283 return($value === '2.0' || $value === 2.0); 284 } 285 286 } 287 288 // 4.8.1 Descriptive Component Properties 289 // -------------------------------------- 290 291 class iCalendar_property_attach extends iCalendar_property { 292 293 var $name = 'ATTACH'; 294 var $val_type = RFC2445_TYPE_URI; 295 296 function construct() { 297 $this->valid_parameters = array( 298 'FMTTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 299 'ENCODING' => RFC2445_OPTIONAL | RFC2445_ONCE, 300 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 301 RFC2445_XNAME => RFC2445_OPTIONAL 302 ); 303 } 304 305 function invariant_holds() { 306 if(isset($this->parameters['ENCODING']) && !isset($this->parameters['VALUE'])) { 307 return false; 308 } 309 if(isset($this->parameters['VALUE']) && !isset($this->parameters['ENCODING'])) { 310 return false; 311 } 312 313 return true; 314 } 315 316 function is_valid_parameter($parameter, $value) { 317 318 $parameter = strtoupper($parameter); 319 320 if(!parent::is_valid_parameter($parameter, $value)) { 321 return false; 322 } 323 324 if($parameter === 'ENCODING' && strtoupper($value) != 'BASE64') { 325 return false; 326 } 327 328 if($parameter === 'VALUE' && strtoupper($value) != 'BINARY') { 329 return false; 330 } 331 332 return true; 333 } 334 } 335 336 class iCalendar_property_categories extends iCalendar_property { 337 338 var $name = 'CATEGORIES'; 339 var $val_type = RFC2445_TYPE_TEXT; 340 var $val_multi = true; 341 342 function construct() { 343 $this->valid_parameters = array( 344 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 345 RFC2445_XNAME => RFC2445_OPTIONAL 346 ); 347 } 348 } 349 350 class iCalendar_property_class extends iCalendar_property { 351 352 var $name = 'CLASS'; 353 var $val_type = RFC2445_TYPE_TEXT; 354 var $val_default = 'PUBLIC'; 355 356 function construct() { 357 $this->valid_parameters = array( 358 RFC2445_XNAME => RFC2445_OPTIONAL 359 ); 360 } 361 362 function is_valid_value($value) { 363 // If this is not an xname, it is case-sensitive 364 return ($value === 'PUBLIC' || $value === 'PRIVATE' || $value === 'CONFIDENTIAL' || rfc2445_is_xname(strtoupper($value))); 365 } 366 } 367 368 class iCalendar_property_comment extends iCalendar_property { 369 370 var $name = 'COMMENT'; 371 var $val_type = RFC2445_TYPE_TEXT; 372 373 function construct() { 374 $this->valid_parameters = array( 375 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 376 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 377 RFC2445_XNAME => RFC2445_OPTIONAL 378 ); 379 } 380 } 381 382 class iCalendar_property_description extends iCalendar_property { 383 384 var $name = 'DESCRIPTION'; 385 var $val_type = RFC2445_TYPE_TEXT; 386 387 function construct() { 388 $this->valid_parameters = array( 389 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 390 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 391 RFC2445_XNAME => RFC2445_OPTIONAL 392 ); 393 } 394 } 395 396 class iCalendar_property_geo extends iCalendar_property { 397 398 var $name = 'GEO'; 399 var $val_type = RFC2445_TYPE_TEXT; 400 401 function construct() { 402 $this->valid_parameters = array( 403 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 404 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 405 RFC2445_XNAME => RFC2445_OPTIONAL 406 ); 407 } 408 409 function is_valid_value($value) { 410 // This MUST be two floats separated by a semicolon 411 if(!is_string($value)) { 412 return false; 413 } 414 415 $floats = explode(';', $value); 416 if(count($floats) != 2) { 417 return false; 418 } 419 420 return rfc2445_is_valid_value($floats[0], RFC2445_TYPE_FLOAT) && rfc2445_is_valid_value($floats[1], RFC2445_TYPE_FLOAT); 421 } 422 423 function set_value($value) { 424 // Must override this, otherwise the semicolon separating 425 // the two floats would get auto-quoted, which is illegal 426 if($this->is_valid_value($value)) { 427 $this->value = $value; 428 return true; 429 } 430 431 return false; 432 } 433 434 } 435 436 class iCalendar_property_location extends iCalendar_property { 437 438 var $name = 'LOCATION'; 439 var $val_type = RFC2445_TYPE_TEXT; 440 441 function construct() { 442 $this->valid_parameters = array( 443 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 444 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 445 RFC2445_XNAME => RFC2445_OPTIONAL 446 ); 447 } 448 } 449 450 class iCalendar_property_percent_complete extends iCalendar_property { 451 452 var $name = 'PERCENT-COMPLETE'; 453 var $val_type = RFC2445_TYPE_INTEGER; 454 455 function construct() { 456 $this->valid_parameters = array( 457 RFC2445_XNAME => RFC2445_OPTIONAL 458 ); 459 } 460 461 function is_valid_value($value) { 462 // Only integers between 0 and 100 inclusive allowed 463 if(!parent::is_valid_value($value)) { 464 return false; 465 } 466 $value = intval($value); 467 return ($value >= 0 && $value <= 100); 468 } 469 470 } 471 472 class iCalendar_property_priority extends iCalendar_property { 473 474 var $name = 'PRIORITY'; 475 var $val_type = RFC2445_TYPE_INTEGER; 476 477 function construct() { 478 $this->valid_parameters = array( 479 RFC2445_XNAME => RFC2445_OPTIONAL 480 ); 481 } 482 483 function is_valid_value($value) { 484 // Only integers between 0 and 9 inclusive allowed 485 if(!parent::is_valid_value($value)) { 486 return false; 487 } 488 489 $value = intval($value); 490 return ($value >= 0 && $value <= 9); 491 } 492 } 493 494 class iCalendar_property_resources extends iCalendar_property { 495 496 var $name = 'RESOURCES'; 497 var $val_type = RFC2445_TYPE_TEXT; 498 var $val_multi = true; 499 500 function construct() { 501 $this->valid_parameters = array( 502 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 503 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 504 RFC2445_XNAME => RFC2445_OPTIONAL 505 ); 506 } 507 } 508 509 class iCalendar_property_status extends iCalendar_property { 510 511 var $name = 'STATUS'; 512 var $val_type = RFC2445_TYPE_TEXT; 513 514 function construct() { 515 $this->valid_parameters = array( 516 RFC2445_XNAME => RFC2445_OPTIONAL 517 ); 518 } 519 520 function is_valid_value($value) { 521 // This is case-sensitive 522 switch ($this->parent_component) { 523 case 'VEVENT': 524 $allowed = array('TENTATIVE', 'CONFIRMED', 'CANCELLED'); 525 break; 526 case 'VTODO': 527 $allowed = array('NEEDS-ACTION', 'COMPLETED', 'IN-PROCESS', 'CANCELLED'); 528 break; 529 case 'VJOURNAL': 530 $allowed = array('DRAFT', 'FINAL', 'CANCELLED'); 531 break; 532 } 533 return in_array($value, $allowed); 534 535 } 536 537 } 538 539 class iCalendar_property_summary extends iCalendar_property { 540 541 var $name = 'SUMMARY'; 542 var $val_type = RFC2445_TYPE_TEXT; 543 544 function construct() { 545 $this->valid_parameters = array( 546 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 547 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 548 RFC2445_XNAME => RFC2445_OPTIONAL 549 ); 550 } 551 } 552 553 // 4.8.2 Date and Time Component Properties 554 // ---------------------------------------- 555 556 class iCalendar_property_completed extends iCalendar_property { 557 558 var $name = 'COMPLETED'; 559 var $val_type = RFC2445_TYPE_DATE_TIME; 560 561 function construct() { 562 $this->valid_parameters = array( 563 RFC2445_XNAME => RFC2445_OPTIONAL 564 ); 565 } 566 567 function is_valid_value($value) { 568 if(!parent::is_valid_value($value)) { 569 return false; 570 } 571 // Time MUST be in UTC format 572 return(substr($value, -1) == 'Z'); 573 } 574 } 575 576 class iCalendar_property_dtend extends iCalendar_property { 577 578 var $name = 'DTEND'; 579 var $val_type = RFC2445_TYPE_DATE_TIME; 580 581 function construct() { 582 $this->valid_parameters = array( 583 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 584 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 585 RFC2445_XNAME => RFC2445_OPTIONAL 586 ); 587 } 588 589 function is_valid_value($value) { 590 if(!parent::is_valid_value($value)) { 591 return false; 592 } 593 594 // If present in a FREEBUSY component, must be in UTC format 595 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 596 return false; 597 } 598 599 return true; 600 601 } 602 603 function is_valid_parameter($parameter, $value) { 604 605 $parameter = strtoupper($parameter); 606 607 if(!parent::is_valid_parameter($parameter, $value)) { 608 return false; 609 } 610 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 611 return false; 612 } 613 614 return true; 615 } 616 } 617 618 class iCalendar_property_due extends iCalendar_property { 619 620 var $name = 'DUE'; 621 var $val_type = RFC2445_TYPE_DATE_TIME; 622 623 function construct() { 624 $this->valid_parameters = array( 625 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 626 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 627 RFC2445_XNAME => RFC2445_OPTIONAL 628 ); 629 } 630 631 function is_valid_value($value) { 632 if(!parent::is_valid_value($value)) { 633 return false; 634 } 635 636 // If present in a FREEBUSY component, must be in UTC format 637 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 638 return false; 639 } 640 641 return true; 642 643 } 644 645 function is_valid_parameter($parameter, $value) { 646 647 $parameter = strtoupper($parameter); 648 649 if(!parent::is_valid_parameter($parameter, $value)) { 650 return false; 651 } 652 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 653 return false; 654 } 655 656 return true; 657 } 658 } 659 660 class iCalendar_property_dtstart extends iCalendar_property { 661 662 var $name = 'DTSTART'; 663 var $val_type = RFC2445_TYPE_DATE_TIME; 664 665 function construct() { 666 $this->valid_parameters = array( 667 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 668 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 669 RFC2445_XNAME => RFC2445_OPTIONAL 670 ); 671 } 672 673 // TODO: unimplemented stuff when parent is a VTIMEZONE component 674 675 function is_valid_value($value) { 676 if(!parent::is_valid_value($value)) { 677 return false; 678 } 679 680 // If present in a FREEBUSY component, must be in UTC format 681 if($this->parent_component == 'VFREEBUSY' && substr($value, -1) != 'Z') { 682 return false; 683 } 684 685 return true; 686 } 687 688 function is_valid_parameter($parameter, $value) { 689 690 $parameter = strtoupper($parameter); 691 692 if(!parent::is_valid_parameter($parameter, $value)) { 693 return false; 694 } 695 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 696 return false; 697 } 698 699 return true; 700 } 701 } 702 703 class iCalendar_property_duration extends iCalendar_property { 704 705 var $name = 'DURATION'; 706 var $val_type = RFC2445_TYPE_DURATION; 707 708 function construct() { 709 $this->valid_parameters = array( 710 RFC2445_XNAME => RFC2445_OPTIONAL 711 ); 712 } 713 714 function is_valid_value($value) { 715 if(!parent::is_valid_value($value)) { 716 return false; 717 } 718 719 // Value must be positive 720 return ($value{0} != '-'); 721 } 722 } 723 724 class iCalendar_property_freebusy extends iCalendar_property { 725 726 var $name = 'FREEBUSY'; 727 var $val_type = RFC2445_TYPE_PERIOD; 728 var $val_multi = true; 729 730 function construct() { 731 $this->valid_parameters = array( 732 'FBTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 733 RFC2445_XNAME => RFC2445_OPTIONAL 734 ); 735 } 736 737 function is_valid_value($value) { 738 if(!parent::is_valid_value($value)) { 739 return false; 740 } 741 742 $pos = strpos($value, '/'); // We know there's only one / in there 743 if($value{$pos - 1} != 'Z') { 744 // Start time MUST be in UTC 745 return false; 746 } 747 if($value{$pos + 1} != 'P' && $substr($value, -1) != 'Z') { 748 // If the second part is not a period, it MUST be in UTC 749 return false; 750 } 751 752 return true; 753 } 754 755 // TODO: these properties SHOULD be shorted in ascending order (by start time and end time as tiebreak) 756 } 757 758 class iCalendar_property_transp extends iCalendar_property { 759 760 var $name = 'TRANSP'; 761 var $val_type = RFC2445_TYPE_TEXT; 762 var $val_default = 'OPAQUE'; 763 764 function construct() { 765 $this->valid_parameters = array( 766 RFC2445_XNAME => RFC2445_OPTIONAL 767 ); 768 } 769 770 function is_valid_value($value) { 771 return ($value === 'TRANSPARENT' || $value === 'OPAQUE'); 772 } 773 } 774 775 // TODO: 4.8.3 timezone component properties 776 777 778 // 4.8.4 Relationship Component Properties 779 // --------------------------------------- 780 781 class iCalendar_property_attendee extends iCalendar_property { 782 783 var $name = 'ATTENDEE'; 784 var $val_type = RFC2445_TYPE_CAL_ADDRESS; 785 786 // TODO: MUST NOT be specified when the calendar object has METHOD=PUBLISH 787 // TODO: standard has lots of detail here, make triple sure that we eventually conform 788 789 function construct() { 790 $this->valid_parameters = array( 791 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 792 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE, 793 'ROLE' => RFC2445_OPTIONAL | RFC2445_ONCE, 794 'PARTSTAT' => RFC2445_OPTIONAL | RFC2445_ONCE, 795 'RSVP' => RFC2445_OPTIONAL | RFC2445_ONCE, 796 'CUTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 797 'MEMBER' => RFC2445_OPTIONAL | RFC2445_ONCE, 798 'DELEGATED-TO' => RFC2445_OPTIONAL | RFC2445_ONCE, 799 'DELEGATED-FROM' => RFC2445_OPTIONAL | RFC2445_ONCE, 800 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE, 801 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE, 802 RFC2445_XNAME => RFC2445_OPTIONAL 803 ); 804 } 805 806 function set_parent_component($componentname) { 807 if(!parent::set_parent_component($componentname)) { 808 return false; 809 } 810 811 if($this->parent_component == 'VFREEBUSY' || $this->parent_component == 'VALARM') { 812 // Most parameters become invalid in this case, the full allowed set is now: 813 $this->valid_parameters = array( 814 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 815 RFC2445_XNAME => RFC2445_OPTIONAL 816 ); 817 } 818 819 return false; 820 } 821 822 } 823 824 class iCalendar_property_contact extends iCalendar_property { 825 826 var $name = 'CONTACT'; 827 var $val_type = RFC2445_TYPE_TEXT; 828 829 function construct() { 830 $this->valid_parameters = array( 831 'ALTREP' => RFC2445_OPTIONAL | RFC2445_ONCE, 832 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 833 RFC2445_XNAME => RFC2445_OPTIONAL 834 ); 835 } 836 } 837 838 class iCalendar_property_organizer extends iCalendar_property { 839 840 var $name = 'ORGANIZER'; 841 var $val_type = RFC2445_TYPE_CAL_ADDRESS; 842 843 function construct() { 844 $this->valid_parameters = array( 845 'CN' => RFC2445_OPTIONAL | RFC2445_ONCE, 846 'DIR' => RFC2445_OPTIONAL | RFC2445_ONCE, 847 'SENT-BY' => RFC2445_OPTIONAL | RFC2445_ONCE, 848 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 849 RFC2445_XNAME => RFC2445_OPTIONAL 850 ); 851 } 852 853 // TODO: 854 /* 855 Conformance: This property MUST be specified in an iCalendar object 856 that specifies a group scheduled calendar entity. This property MUST 857 be specified in an iCalendar object that specifies the publication of 858 a calendar user's busy time. This property MUST NOT be specified in 859 an iCalendar object that specifies only a time zone definition or 860 that defines calendar entities that are not group scheduled entities, 861 but are entities only on a single user's calendar. 862 */ 863 864 } 865 866 class iCalendar_property_recurrence_id extends iCalendar_property { 867 868 // TODO: can only be specified when defining recurring components in the calendar 869 /* 870 Conformance: This property can be specified in an iCalendar object 871 containing a recurring calendar component. 872 873 Description: The full range of calendar components specified by a 874 recurrence set is referenced by referring to just the "UID" property 875 value corresponding to the calendar component. The "RECURRENCE-ID" 876 property allows the reference to an individual instance within the 877 recurrence set. 878 */ 879 880 var $name = 'RECURRENCE-ID'; 881 var $val_type = RFC2445_TYPE_DATE_TIME; 882 883 function construct() { 884 $this->valid_parameters = array( 885 'RANGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 886 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 887 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 888 RFC2445_XNAME => RFC2445_OPTIONAL 889 ); 890 } 891 892 function is_valid_parameter($parameter, $value) { 893 894 $parameter = strtoupper($parameter); 895 896 if(!parent::is_valid_parameter($parameter, $value)) { 897 return false; 898 } 899 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 900 return false; 901 } 902 903 return true; 904 } 905 906 } 907 908 class iCalendar_property_related_to extends iCalendar_property { 909 910 var $name = 'RELATED-TO'; 911 var $val_type = RFC2445_TYPE_TEXT; 912 913 // TODO: the value of this property must reference another component's UID 914 915 function construct() { 916 $this->valid_parameters = array( 917 'RELTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE, 918 RFC2445_XNAME => RFC2445_OPTIONAL 919 ); 920 } 921 } 922 923 class iCalendar_property_url extends iCalendar_property { 924 925 var $name = 'URL'; 926 var $val_type = RFC2445_TYPE_URI; 927 928 function construct() { 929 $this->valid_parameters = array( 930 RFC2445_XNAME => RFC2445_OPTIONAL 931 ); 932 } 933 } 934 935 class iCalendar_property_uid extends iCalendar_property { 936 937 var $name = 'UID'; 938 var $val_type = RFC2445_TYPE_TEXT; 939 940 function construct() { 941 $this->valid_parameters = array( 942 RFC2445_XNAME => RFC2445_OPTIONAL 943 ); 944 945 // The exception to the rule: this is not a static value, so we 946 // generate it on-the-fly here. Guaranteed to be different for 947 // each instance of this property, too. Nice. 948 $this->val_default = Bennu::generate_guid(); 949 } 950 } 951 952 // 4.8.5 Recurrence Component Properties 953 // ------------------------------------- 954 955 class iCalendar_property_exdate extends iCalendar_property { 956 957 var $name = 'EXDATE'; 958 var $val_type = RFC2445_TYPE_DATE_TIME; 959 var $val_multi = true; 960 961 function construct() { 962 $this->valid_parameters = array( 963 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 964 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 965 RFC2445_XNAME => RFC2445_OPTIONAL 966 ); 967 } 968 969 function is_valid_parameter($parameter, $value) { 970 971 $parameter = strtoupper($parameter); 972 973 if(!parent::is_valid_parameter($parameter, $value)) { 974 return false; 975 } 976 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME')) { 977 return false; 978 } 979 980 return true; 981 } 982 983 } 984 985 class iCalendar_property_exrule extends iCalendar_property { 986 987 var $name = 'EXRULE'; 988 var $val_type = RFC2445_TYPE_RECUR; 989 990 function construct() { 991 $this->valid_parameters = array( 992 RFC2445_XNAME => RFC2445_OPTIONAL 993 ); 994 } 995 } 996 997 class iCalendar_property_rdate extends iCalendar_property { 998 999 var $name = 'RDATE'; 1000 var $val_type = RFC2445_TYPE_DATE_TIME; 1001 var $val_multi = true; 1002 1003 function construct() { 1004 $this->valid_parameters = array( 1005 'TZID' => RFC2445_OPTIONAL | RFC2445_ONCE, 1006 'VALUE' => RFC2445_OPTIONAL | RFC2445_ONCE, 1007 RFC2445_XNAME => RFC2445_OPTIONAL 1008 ); 1009 } 1010 1011 function is_valid_parameter($parameter, $value) { 1012 1013 $parameter = strtoupper($parameter); 1014 1015 if(!parent::is_valid_parameter($parameter, $value)) { 1016 return false; 1017 } 1018 if($parameter == 'VALUE' && !($value == 'DATE' || $value == 'DATE-TIME' || $value == 'PERIOD')) { 1019 return false; 1020 } 1021 1022 return true; 1023 } 1024 1025 } 1026 1027 class iCalendar_property_rrule extends iCalendar_property { 1028 1029 var $name = 'RRULE'; 1030 var $val_type = RFC2445_TYPE_RECUR; 1031 1032 function construct() { 1033 $this->valid_parameters = array( 1034 RFC2445_XNAME => RFC2445_OPTIONAL 1035 ); 1036 } 1037 } 1038 1039 // TODO: 4.8.6 Alarm Component Properties 1040 1041 // 4.8.7 Change Management Component Properties 1042 // -------------------------------------------- 1043 1044 class iCalendar_property_created extends iCalendar_property { 1045 1046 var $name = 'CREATED'; 1047 var $val_type = RFC2445_TYPE_DATE_TIME; 1048 1049 function construct() { 1050 $this->valid_parameters = array( 1051 RFC2445_XNAME => RFC2445_OPTIONAL 1052 ); 1053 } 1054 1055 function is_valid_value($value) { 1056 if(!parent::is_valid_value($value)) { 1057 return false; 1058 } 1059 // Time MUST be in UTC format 1060 return(substr($value, -1) == 'Z'); 1061 } 1062 } 1063 1064 class iCalendar_property_dtstamp extends iCalendar_property { 1065 1066 var $name = 'DTSTAMP'; 1067 var $val_type = RFC2445_TYPE_DATE_TIME; 1068 1069 function construct() { 1070 $this->valid_parameters = array( 1071 RFC2445_XNAME => RFC2445_OPTIONAL 1072 ); 1073 } 1074 1075 function is_valid_value($value) { 1076 if(!parent::is_valid_value($value)) { 1077 return false; 1078 } 1079 // Time MUST be in UTC format 1080 return(substr($value, -1) == 'Z'); 1081 } 1082 } 1083 1084 class iCalendar_property_last_modified extends iCalendar_property { 1085 1086 var $name = 'LAST-MODIFIED'; 1087 var $val_type = RFC2445_TYPE_DATE_TIME; 1088 1089 function construct() { 1090 $this->valid_parameters = array( 1091 RFC2445_XNAME => RFC2445_OPTIONAL 1092 ); 1093 } 1094 1095 function is_valid_value($value) { 1096 if(!parent::is_valid_value($value)) { 1097 return false; 1098 } 1099 // Time MUST be in UTC format 1100 return(substr($value, -1) == 'Z'); 1101 } 1102 } 1103 1104 class iCalendar_property_sequence extends iCalendar_property { 1105 1106 var $name = 'SEQUENCE'; 1107 var $val_type = RFC2445_TYPE_INTEGER; 1108 var $val_default = 0; 1109 1110 function construct() { 1111 $this->valid_parameters = array( 1112 RFC2445_XNAME => RFC2445_OPTIONAL 1113 ); 1114 } 1115 1116 function is_valid_value($value) { 1117 if(!parent::is_valid_value($value)) { 1118 return false; 1119 } 1120 $value = intval($value); 1121 return ($value >= 0); 1122 } 1123 } 1124 1125 // 4.8.8 Miscellaneous Component Properties 1126 // ---------------------------------------- 1127 1128 class iCalendar_property_x extends iCalendar_property { 1129 1130 var $name = RFC2445_XNAME; 1131 var $val_type = NULL; 1132 1133 function construct() { 1134 $this->valid_parameters = array( 1135 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 1136 RFC2445_XNAME => RFC2445_OPTIONAL 1137 ); 1138 } 1139 1140 function set_name($name) { 1141 1142 $name = strtoupper($name); 1143 1144 if(rfc2445_is_xname($name)) { 1145 $this->name = $name; 1146 return true; 1147 } 1148 1149 return false; 1150 } 1151 } 1152 1153 class iCalendar_property_request_status extends iCalendar_property { 1154 1155 // IMPORTANT NOTE: This property value includes TEXT fields 1156 // separated by semicolons. Unfortunately, auto-value-formatting 1157 // cannot be used in this case. As an exception, the value passed 1158 // to this property MUST be already escaped. 1159 1160 var $name = 'REQUEST-STATUS'; 1161 var $val_type = RFC2445_TYPE_TEXT; 1162 1163 function construct() { 1164 $this->valid_parameters = array( 1165 'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE, 1166 RFC2445_XNAME => RFC2445_OPTIONAL 1167 ); 1168 } 1169 1170 function is_valid_value($value) { 1171 if(!is_string($value) || empty($value)) { 1172 return false; 1173 } 1174 1175 $len = strlen($value); 1176 $parts = array(); 1177 $from = 0; 1178 $escch = false; 1179 1180 for($i = 0; $i < $len; ++$i) { 1181 if($value{$i} == ';' && !$escch) { 1182 // Token completed 1183 $parts[] = substr($value, $from, $i - $from); 1184 $from = $i + 1; 1185 continue; 1186 } 1187 $escch = ($value{$i} == '\\'); 1188 } 1189 // Add one last token with the remaining text; if the value 1190 // ended with a ';' it was illegal, so check that this token 1191 // is not the empty string. 1192 $parts[] = substr($value, $from); 1193 1194 $count = count($parts); 1195 1196 // May have 2 or 3 tokens (last one is optional) 1197 if($count != 2 && $count != 3) { 1198 return false; 1199 } 1200 1201 // REMEMBER: if ANY part is empty, we have an illegal value 1202 1203 // First token must be hierarchical numeric status (3 levels max) 1204 if(strlen($parts[0]) == 0) { 1205 return false; 1206 } 1207 1208 if($parts[0]{0} < '1' || $parts[0]{0} > '4') { 1209 return false; 1210 } 1211 1212 $len = strlen($parts[0]); 1213 1214 // Max 3 levels, and can't end with a period 1215 if($len > 5 || $parts[0]{$len - 1} == '.') { 1216 return false; 1217 } 1218 1219 for($i = 1; $i < $len; ++$i) { 1220 if(($i & 1) == 1 && $parts[0]{$i} != '.') { 1221 // Even-indexed chars must be periods 1222 return false; 1223 } 1224 else if(($i & 1) == 0 && ($parts[0]{$i} < '0' || $parts[0]{$i} > '9')) { 1225 // Odd-indexed chars must be numbers 1226 return false; 1227 } 1228 } 1229 1230 // Second and third tokens must be TEXT, and already escaped, so 1231 // they are not allowed to have UNESCAPED semicolons, commas, slashes, 1232 // or any newlines at all 1233 1234 for($i = 1; $i < $count; ++$i) { 1235 if(strpos($parts[$i], "\n") !== false) { 1236 return false; 1237 } 1238 1239 $len = strlen($parts[$i]); 1240 if($len == 0) { 1241 // Cannot be empty 1242 return false; 1243 } 1244 1245 $parts[$i] .= '#'; // This guard token saves some conditionals in the loop 1246 1247 for($j = 0; $j < $len; ++$j) { 1248 $thischar = $parts[$i]{$j}; 1249 $nextchar = $parts[$i]{$j + 1}; 1250 if($thischar == '\\') { 1251 // Next char must now be one of ";,\nN" 1252 if($nextchar != ';' && $nextchar != ',' && $nextchar != '\\' && 1253 $nextchar != 'n' && $nextchar != 'N') { 1254 return false; 1255 } 1256 1257 // OK, this escaped sequence is correct, bypass next char 1258 ++$j; 1259 continue; 1260 } 1261 if($thischar == ';' || $thischar == ',' || $thischar == '\\') { 1262 // This wasn't escaped as it should 1263 return false; 1264 } 1265 } 1266 } 1267 1268 return true; 1269 } 1270 1271 function set_value($value) { 1272 // Must override this, otherwise the value would be quoted again 1273 if($this->is_valid_value($value)) { 1274 $this->value = $value; 1275 return true; 1276 } 1277 1278 return false; 1279 } 1280 1281 } 1282 1283 1284 ####################### 1285 /* 1286 class iCalendar_property_class extends iCalendar_property { 1287 1288 var $name = 'CLASS'; 1289 var $val_type = RFC2445_TYPE_TEXT; 1290 1291 function construct() { 1292 $this->valid_parameters = array( 1293 RFC2445_XNAME => RFC2445_OPTIONAL 1294 ); 1295 } 1296 } 1297 */ 1298 1299 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Jan 14 11:33:29 2009 | Cross-referenced by PHPXref 0.7 |