Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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