Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

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