-
Notifications
You must be signed in to change notification settings - Fork 111
/
CFType.php
742 lines (656 loc) · 22.2 KB
/
CFType.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
<?php
/**
* Data-Types for CFPropertyList as defined by Apple.
* {@link http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html Property Lists}
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
* @version $Id$
*/
/**
* Base-Class of all CFTypes used by CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
* @version $Id$
* @example example-create-01.php Using the CFPropertyList API
* @example example-create-02.php Using CFPropertyList::guess()
* @example example-create-03.php Using CFPropertyList::guess() with {@link CFDate} and {@link CFData}
*/
abstract class CFType {
/**
* CFType nodes
* @var array
*/
protected $value = null;
/**
* Create new CFType.
* @param mixed $value Value of CFType
*/
public function __construct($value=null) {
$this->setValue($value);
}
/************************************************************************************************
* M A G I C P R O P E R T I E S
************************************************************************************************/
/**
* Get the CFType's value
* @return mixed CFType's value
*/
public function getValue() {
return $this->value;
}
/**
* Set the CFType's value
* @return void
*/
public function setValue($value) {
$this->value = $value;
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName Name of element to create
* @return DOMNode Node created based on CType
* @uses $value as nodeValue
*/
public function toXML(DOMDocument $doc, $nodeName) {
$text = $doc->createTextNode($this->value);
$node = $doc->createElement($nodeName);
$node->appendChild($text);
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public abstract function toBinary(CFBinaryPropertyList &$bplist);
/**
* Get CFType's value.
* @return mixed primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
return $this->getValue();
}
}
/**
* String Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFString extends CFType {
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <string>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return parent::toXML($doc, 'string');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->stringToBinary($this->value);
}
}
/**
* Number Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFNumber extends CFType {
/**
* Get XML-Node.
* Returns <real> if $value is a float, <integer> if $value is an integer.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <real> or <integer>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$ret = 'real';
if(intval($this->value) == $this->value && !is_float($this->value) && strpos($this->value,'.') === false) {
$this->value = intval($this->value);
$ret = 'integer';
}
return parent::toXML($doc, $ret);
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->numToBinary($this->value);
}
}
/**
* Date Type of CFPropertyList
* Note: CFDate uses Unix timestamp (epoch) to store dates internally
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFDate extends CFType {
const TIMESTAMP_APPLE = 0;
const TIMESTAMP_UNIX = 1;
const DATE_DIFF_APPLE_UNIX = 978307200;
/**
* Create new Date CFType.
* @param integer $value timestamp to set
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_APPLE}
* @uses setValue() to convert the timestamp
*/
function __construct($value,$format=CFDate::TIMESTAMP_UNIX) {
$this->setValue($value,$format);
}
/**
* Set the Date CFType's value.
* @param integer $value timestamp to set
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX}
* @return void
* @uses TIMESTAMP_APPLE to determine timestamp type
* @uses TIMESTAMP_UNIX to determine timestamp type
* @uses DATE_DIFF_APPLE_UNIX to convert Apple-timestamp to Unix-timestamp
*/
function setValue($value,$format=CFDate::TIMESTAMP_UNIX) {
if($format == CFDate::TIMESTAMP_UNIX) $this->value = $value;
else $this->value = $value + CFDate::DATE_DIFF_APPLE_UNIX;
}
/**
* Get the Date CFType's value.
* @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX}
* @return integer Unix timestamp
* @uses TIMESTAMP_APPLE to determine timestamp type
* @uses TIMESTAMP_UNIX to determine timestamp type
* @uses DATE_DIFF_APPLE_UNIX to convert Unix-timestamp to Apple-timestamp
*/
function getValue($format=CFDate::TIMESTAMP_UNIX) {
if($format == CFDate::TIMESTAMP_UNIX) return $this->value;
else return $this->value - CFDate::DATE_DIFF_APPLE_UNIX;
}
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <date>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$text = $doc->createTextNode(gmdate("Y-m-d\TH:i:s\Z",$this->getValue()));
$node = $doc->createElement("date");
$node->appendChild($text);
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dateToBinary($this->value);
}
/**
* Create a UNIX timestamp from a PList date string
* @param string $val The date string (e.g. "2009-05-13T20:23:43Z")
* @return integer The UNIX timestamp
* @throws PListException when encountering an unknown date string format
*/
public static function dateValue($val) {
//2009-05-13T20:23:43Z
if(!preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/',$val,$matches)) throw new PListException("Unknown date format: $val");
return gmmktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
}
}
/**
* Boolean Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFBoolean extends CFType {
/**
* Get XML-Node.
* Returns <true> if $value is a true, <false> if $value is false.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <true> or <false>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return $doc->createElement($this->value ? 'true' : 'false');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->boolToBinary($this->value);
}
}
/**
* Data Type of CFPropertyList
* Note: Binary data is base64-encoded.
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFData extends CFType {
/**
* Create new Data CFType
* @param string $value data to be contained by new object
* @param boolean $already_coded if true $value will not be base64-encoded, defaults to false
*/
public function __construct($value=null,$already_coded=false) {
if($already_coded) $this->value = $value;
else $this->setValue($value);
}
/**
* Set the CFType's value and base64-encode it.
* <b>Note:</b> looks like base64_encode has troubles with UTF-8 encoded strings
* @return void
*/
public function setValue($value) {
//if(function_exists('mb_check_encoding') && mb_check_encoding($value, 'UTF-8')) $value = utf8_decode($value);
$this->value = base64_encode($value);
}
/**
* Get base64 encoded data
* @return string The base64 encoded data value
*/
public function getCodedValue() {
return $this->value;
}
/**
* Get the base64-decoded CFType's value.
* @return mixed CFType's value
*/
public function getValue() {
return base64_decode($this->value);
}
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <data>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
return parent::toXML($doc, 'data');
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dataToBinary($this->getValue());
}
}
/**
* Array Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFArray extends CFType implements Iterator, ArrayAccess {
/**
* Position of iterator {@link http://php.net/manual/en/class.iterator.php}
* @var integer
*/
protected $iteratorPosition = 0;
/**
* Create new CFType.
* @param array $value Value of CFType
*/
public function __construct($value=array()) {
$this->value = $value;
}
/**
* Set the CFType's value
* <b>Note:</b> this dummy does nothing
* @return void
*/
public function setValue($value) {
}
/**
* Add CFType to collection.
* @param CFType $value CFType to add to collection, defaults to null which results in an empty {@link CFString}
* @return void
* @uses $value for adding $value
*/
public function add(CFType $value=null) {
// anything but CFType is null, null is an empty string - sad but true
if( !$value )
$value = new CFString();
$this->value[] = $value;
}
/**
* Get CFType from collection.
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @uses $value for retrieving CFType of $key
*/
public function get($key) {
if(isset($this->value[$key])) return $this->value[$key];
return null;
}
/**
* Remove CFType from collection.
* @param integer $key Key of CFType to removes from collection
* @return CFType removed CFType, null else
* @uses $value for removing CFType of $key
*/
public function del($key) {
if(isset($this->value[$key])) unset($this->value[$key]);
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <array>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$node = $doc->createElement('array');
foreach($this->value as $value) $node->appendChild($value->toXML($doc));
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->arrayToBinary($this);
}
/**
* Get CFType's value.
* @return array primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
$a = array();
foreach($this->value as $value) $a[] = $value->toArray();
return $a;
}
/************************************************************************************************
* I T E R A T O R I N T E R F A C E
************************************************************************************************/
/**
* Rewind {@link $iteratorPosition} to first position (being 0)
* @link http://php.net/manual/en/iterator.rewind.php
* @return void
* @uses $iteratorPosition set to 0
*/
public function rewind() {
$this->iteratorPosition = 0;
}
/**
* Get Iterator's current {@link CFType} identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.current.php
* @return CFType current Item
* @uses $iteratorPosition identify current key
*/
public function current() {
return $this->value[$this->iteratorPosition];
}
/**
* Get Iterator's current key identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.key.php
* @return string key of the current Item
* @uses $iteratorPosition identify current key
*/
public function key() {
return $this->iteratorPosition;
}
/**
* Increment {@link $iteratorPosition} to address next {@see CFType}
* @link http://php.net/manual/en/iterator.next.php
* @return void
* @uses $iteratorPosition increment by 1
*/
public function next() {
$this->iteratorPosition++;
}
/**
* Test if {@link $iteratorPosition} addresses a valid element of {@link $value}
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean true if current position is valid, false else
* @uses $iteratorPosition test if within {@link $iteratorKeys}
* @uses $iteratorPosition test if within {@link $value}
*/
public function valid() {
return isset($this->value[$this->iteratorPosition]);
}
/************************************************************************************************
* ArrayAccess I N T E R F A C E
************************************************************************************************/
/**
* Determine if the array's key exists
* @param string $key the key to check
* @return bool true if the offset exists, false if not
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
* @uses $value to check if $key exists
* @author Sean Coates <sean@php.net>
*/
public function offsetExists($key) {
return isset($this->value[$key]);
}
/**
* Fetch a specific key from the CFArray
* @param string $key the key to check
* @return mixed the value associated with the key; null if the key is not found
* @link http://php.net/manual/en/arrayaccess.offsetget.php
* @uses get() to get the key's value
* @author Sean Coates <sean@php.net>
*/
public function offsetGet($key) {
return $this->get($key);
}
/**
* Set a value in the array
* @param string $key the key to set
* @param string $value the value to set
* @return void
* @link http://php.net/manual/en/arrayaccess.offsetset.php
* @uses setValue() to set the key's new value
* @author Sean Coates <sean@php.net>
*/
public function offsetSet($key, $value) {
return $this->setValue($value);
}
/**
* Unsets a value in the array
* <b>Note:</b> this dummy does nothing
* @param string $key the key to set
* @return void
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
* @author Sean Coates <sean@php.net>
*/
public function offsetUnset($key) {
}
}
/**
* Array Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
* @author Christian Kruse <cjk@wwwtech.de>
* @package plist
* @subpackage plist.types
*/
class CFDictionary extends CFType implements Iterator {
/**
* Position of iterator {@link http://php.net/manual/en/class.iterator.php}
* @var integer
*/
protected $iteratorPosition = 0;
/**
* List of Keys for numerical iterator access {@link http://php.net/manual/en/class.iterator.php}
* @var array
*/
protected $iteratorKeys = null;
/**
* Create new CFType.
* @param array $value Value of CFType
*/
public function __construct($value=array()) {
$this->value = $value;
}
/**
* Set the CFType's value
* <b>Note:</b> this dummy does nothing
* @return void
*/
public function setValue($value) {
}
/**
* Add CFType to collection.
* @param string $key Key to add to collection
* @param CFType $value CFType to add to collection, defaults to null which results in an empty {@link CFString}
* @return void
* @uses $value for adding $key $value pair
*/
public function add($key, CFType $value=null) {
// anything but CFType is null, null is an empty string - sad but true
if( !$value )
$value = new CFString();
$this->value[$key] = $value;
}
/**
* Get CFType from collection.
* @param string $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @uses $value for retrieving CFType of $key
*/
public function get($key) {
if(isset($this->value[$key])) return $this->value[$key];
return null;
}
/**
* Generic getter (magic)
* @param integer $key Key of CFType to retrieve from collection
* @return CFType CFType found at $key, null else
* @link http://php.net/oop5.overloading
* @uses get() to retrieve the key's value
* @author Sean Coates <sean@php.net>
*/
public function __get($key) {
return $this->get($key);
}
/**
* Remove CFType from collection.
* @param string $key Key of CFType to removes from collection
* @return CFType removed CFType, null else
* @uses $value for removing CFType of $key
*/
public function del($key) {
if(isset($this->value[$key])) unset($this->value[$key]);
}
/************************************************************************************************
* S E R I A L I Z I N G
************************************************************************************************/
/**
* Get XML-Node.
* @param DOMDocument $doc DOMDocument to create DOMNode in
* @param string $nodeName For compatibility reasons; just ignore it
* @return DOMNode <dict>-Element
*/
public function toXML(DOMDocument $doc,$nodeName="") {
$node = $doc->createElement('dict');
foreach($this->value as $key => $value) {
$node->appendChild($doc->createElement('key', $key));
$node->appendChild($value->toXML($doc));
}
return $node;
}
/**
* convert value to binary representation
* @param CFBinaryPropertyList The binary property list object
* @return The offset in the object table
*/
public function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->dictToBinary($this);
}
/**
* Get CFType's value.
* @return array primitive value
* @uses $value for retrieving primitive of CFType
*/
public function toArray() {
$a = array();
foreach($this->value as $key => $value) $a[$key] = $value->toArray();
return $a;
}
/************************************************************************************************
* I T E R A T O R I N T E R F A C E
************************************************************************************************/
/**
* Rewind {@link $iteratorPosition} to first position (being 0)
* @link http://php.net/manual/en/iterator.rewind.php
* @return void
* @uses $iteratorPosition set to 0
* @uses $iteratorKeys store keys of {@link $value}
*/
public function rewind() {
$this->iteratorPosition = 0;
$this->iteratorKeys = array_keys($this->value);
}
/**
* Get Iterator's current {@link CFType} identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.current.php
* @return CFType current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function current() {
return $this->value[$this->iteratorKeys[$this->iteratorPosition]];
}
/**
* Get Iterator's current key identified by {@link $iteratorPosition}
* @link http://php.net/manual/en/iterator.key.php
* @return string key of the current Item
* @uses $iteratorPosition identify current key
* @uses $iteratorKeys identify current value
*/
public function key() {
return $this->iteratorKeys[$this->iteratorPosition];
}
/**
* Increment {@link $iteratorPosition} to address next {@see CFType}
* @link http://php.net/manual/en/iterator.next.php
* @return void
* @uses $iteratorPosition increment by 1
*/
public function next() {
$this->iteratorPosition++;
}
/**
* Test if {@link $iteratorPosition} addresses a valid element of {@link $value}
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean true if current position is valid, false else
* @uses $iteratorPosition test if within {@link $iteratorKeys}
* @uses $iteratorPosition test if within {@link $value}
*/
public function valid() {
return isset($this->iteratorKeys[$this->iteratorPosition]) && isset($this->value[$this->iteratorKeys[$this->iteratorPosition]]);
}
}
?>