Skip to content

Commit

Permalink
implementing uid type
Browse files Browse the repository at this point in the history
Some serialization framework seems to generate uid types in
plists. Should fix #30
  • Loading branch information
Christian Kruse committed Jan 28, 2015
1 parent 12a090a commit 2ea0483
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 0 deletions.
47 changes: 47 additions & 0 deletions classes/CFPropertyList/CFBinaryPropertyList.php
Expand Up @@ -422,6 +422,10 @@ function readBinaryObject() {
case '6': // unicode string (utf16be)
$retval = $this->readBinaryUnicodeString($object_length);
break;
case '8':
$num = $this->readBinaryInt($object_length);
$retval = new CFUid($num->getValue());
break;
case 'a': // array
$retval = $this->readBinaryArray($object_length);
break;
Expand Down Expand Up @@ -892,6 +896,49 @@ protected function realToBinary($val) {
return $bdata.strrev(pack("d", (float)$val));
}

public function uidToBinary($value) {
$saved_object_count = $this->writtenObjectCount++;

$val = "";

$nbytes = 0;
if($value > 0xFF) $nbytes = 1; // 1 byte integer
if($value > 0xFFFF) $nbytes += 1; // 4 byte integer
if($value > 0xFFFFFFFF) $nbytes += 1; // 8 byte integer
if($value < 0) $nbytes = 3; // 8 byte integer, since signed

$bdata = self::typeBytes("1000", $nbytes); // 1 is 0001, type indicator for integer
$buff = "";

if($nbytes < 3) {
if($nbytes == 0) $fmt = "C";
elseif($nbytes == 1) $fmt = "n";
else $fmt = "N";

$buff = pack($fmt, $value);
}
else {
if(PHP_INT_SIZE > 4) {
// 64 bit signed integer; we need the higher and the lower 32 bit of the value
$high_word = $value >> 32;
$low_word = $value & 0xFFFFFFFF;
}
else {
// since PHP can only handle 32bit signed, we can only get 32bit signed values at this point - values above 0x7FFFFFFF are
// floats. So we ignore the existance of 64bit on non-64bit-machines
if($value < 0) $high_word = 0xFFFFFFFF;
else $high_word = 0;
$low_word = $value;
}
$buff = pack("N", $high_word).pack("N", $low_word);
}

$val = $bdata.$buff;

$this->objectTable[$saved_object_count] = $val;
return $saved_object_count;
}

/**
* Converts a numeric value to binary and adds it to the object table
* @param numeric $value The numeric value
Expand Down
8 changes: 8 additions & 0 deletions classes/CFPropertyList/CFPropertyList.php
Expand Up @@ -319,6 +319,14 @@ protected function import(DOMNode $node, $parent) {
case 'dict':
$value = new $class();
$this->import($n, $value);

if($value instanceof CFDictionary) {
$hsh = $value->getValue();
if(isset($hsh['CF$UID']) && count($hsh) == 1) {
$value = new CFUid($hsh['CF$UID']->getValue());
}
}

break;
}

Expand Down
13 changes: 13 additions & 0 deletions classes/CFPropertyList/CFType.php
Expand Up @@ -121,6 +121,19 @@ public function toBinary(CFBinaryPropertyList &$bplist) {
}
}

class CFUid extends CFType {
public
function toXML(DOMDocument $doc,$nodeName="") {
$obj = new CFDictionary(array('CF$UID' => new CFNumber($this->value)));
return $obj->toXml($doc);
}

public
function toBinary(CFBinaryPropertyList &$bplist) {
return $bplist->uidToBinary($this->value);
}
}

/**
* Number Type of CFPropertyList
* @author Rodney Rehm <rodney.rehm@medialize.de>
Expand Down
10 changes: 10 additions & 0 deletions tests/BinaryParseTest.php
Expand Up @@ -11,6 +11,7 @@

if(!defined('TEST_BINARY_DATA_FILE')) {
define('TEST_BINARY_DATA_FILE',__DIR__.'/binary-data.plist');
define('TEST_UID_BPLIST', __DIR__ . '/uid-list.plist');
}

require_once(LIBDIR.'/CFPropertyList.php');
Expand Down Expand Up @@ -107,6 +108,15 @@ public function testInvalidString() {
$this->fail('No exception thrown for invalid string!');
}

public function testUidPlist() {
$plist = new CFPropertyList(TEST_UID_BPLIST);
$val = $plist->toArray();
$this->assertEquals(array('test' => 1), $val);

$v = $plist->getValue()->getValue();
$this->assertTrue($v['test'] instanceof CFUid);
}

}

# eof
8 changes: 8 additions & 0 deletions tests/ParseXMLTest.php
Expand Up @@ -11,6 +11,7 @@

if(!defined('TEST_XML_DATA_FILE')) {
define('TEST_XML_DATA_FILE',__DIR__.'/xml-data.plist');
define('TEST_UID_XML_PLIST', __DIR__ . '/uid-list.xml');
}

require_once(LIBDIR.'/CFPropertyList.php');
Expand Down Expand Up @@ -113,6 +114,13 @@ public function testInvalidString() {
$this->fail('No exception thrown for invalid string!');
}

public function testUidPlist() {
$plist = new CFPropertyList(TEST_UID_XML_PLIST);
$val = $plist->toArray();
$this->assertEquals(array('test' => 1), $val);
$v = $plist->getValue()->getValue();
$this->assertTrue($v['test'] instanceof CFUid);
}
}

# eof
10 changes: 10 additions & 0 deletions tests/WriteBinaryTest.php
Expand Up @@ -11,6 +11,7 @@

if(!defined('WRITE_BINARY_DATA_FILE')) {
define('WRITE_BINARY_DATA_FILE',__DIR__.'/binary.plist');
define('TEST_UID_BPLIST', __DIR__ . '/uid-list.plist');
}

require_once(LIBDIR.'/CFPropertyList.php');
Expand Down Expand Up @@ -71,6 +72,15 @@ public function testWriteString() {
$plist->parse($content);
}

public function testWriteUid() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$dict->add('test', new CFUid(1));
$plist->add($dict);

$plist1 = new CFPropertyList(TEST_UID_BPLIST);
$this->assertEquals($plist1->toBinary(), $plist->toBinary());
}
}


Expand Down
11 changes: 11 additions & 0 deletions tests/WriteXMLTest.php
Expand Up @@ -11,6 +11,7 @@

if(!defined('WRITE_XML_DATA_FILE')) {
define('WRITE_XML_DATA_FILE',__DIR__.'/binary.plist');
define('TEST_UID_XML_PLIST', __DIR__ . '/uid-list.xml');
}

require_once(LIBDIR.'/CFPropertyList.php');
Expand Down Expand Up @@ -68,6 +69,16 @@ public function testWriteString() {
$plist->parse($content);
}

public
function testWriteUid() {
$plist = new CFPropertyList();
$dict = new CFDictionary();
$dict->add('test', new CFUid(1));
$plist->add($dict);

$plist1 = new CFPropertyList(TEST_UID_XML_PLIST);
$this->assertEquals($plist1->toXml(), $plist->toXml());
}
}


Expand Down
Binary file added tests/uid-list.plist
Binary file not shown.
11 changes: 11 additions & 0 deletions tests/uid-list.xml
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>test</key>
<dict>
<key>CF$UID</key>
<integer>1</integer>
</dict>
</dict>
</plist>

0 comments on commit 2ea0483

Please sign in to comment.