[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

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

   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  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7