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