[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/bennu/ -> iCalendar_properties.php (source)

   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  


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1