Fix bugs and apply new code as described in issue 11

git-svn-id: http://php-reader.googlecode.com/svn/trunk@105 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
svollbehr
2008-07-30 14:56:47 +00:00
parent c747c406d8
commit 809bf58885
34 changed files with 1002 additions and 555 deletions

View File

@@ -54,8 +54,8 @@ interface ID3_Encoding
/** The UTF-16 Unicode encoding with BOM. */ /** The UTF-16 Unicode encoding with BOM. */
const UTF16 = 1; const UTF16 = 1;
/** The UTF-16 Unicode encoding with BOM. */ /** The UTF-16LE Unicode encoding without BOM. */
const UTF16LE = 1; const UTF16LE = 4;
/** The UTF-16BE Unicode encoding without BOM. */ /** The UTF-16BE Unicode encoding without BOM. */
const UTF16BE = 2; const UTF16BE = 2;

View File

@@ -47,6 +47,7 @@ require_once("ID3/Object.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -114,7 +115,7 @@ final class ID3_ExtendedHeader extends ID3_Object
return; return;
$offset = $this->_reader->getOffset(); $offset = $this->_reader->getOffset();
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE()); $this->_size = $this->_reader->readUInt32BE();
/* ID3v2.3.0 ExtendedHeader */ /* ID3v2.3.0 ExtendedHeader */
if ($this->getOption("version", 4) < 4) { if ($this->getOption("version", 4) < 4) {
@@ -127,6 +128,7 @@ final class ID3_ExtendedHeader extends ID3_Object
/* ID3v2.4.0 ExtendedHeader */ /* ID3v2.4.0 ExtendedHeader */
else { else {
$this->_size = $this->decodeSynchsafe32($this->_size);
$this->_reader->skip(1); $this->_reader->skip(1);
$this->_flags = $this->_reader->readInt8(); $this->_flags = $this->_reader->readInt8();
if ($this->hasFlag(self::UPDATE)) if ($this->hasFlag(self::UPDATE))
@@ -313,7 +315,7 @@ final class ID3_ExtendedHeader extends ID3_Object
($this->hasFlag(self::UPDATE) ? "\0" : "") . ($this->hasFlag(self::UPDATE) ? "\0" : "") .
($this->hasFlag(self::CRC32) ? Transform::toInt8(5) . ($this->hasFlag(self::CRC32) ? Transform::toInt8(5) .
Transform::toInt8($this->_crc & 0xf0000000 >> 28 & 0xf /*eq >>> 28*/) . Transform::toInt8($this->_crc & 0xf0000000 >> 28 & 0xf /*eq >>> 28*/) .
Transform::toUInt32BE(encodeSynchsafe32($this->_crc)) : "") . Transform::toUInt32BE($this->encodeSynchsafe32($this->_crc)) : "") .
($this->hasFlag(self::RESTRICTED) ? ($this->hasFlag(self::RESTRICTED) ?
Transform::toInt8(1) . Transform::toInt8($this->_restrictions) : ""); Transform::toInt8(1) . Transform::toInt8($this->_restrictions) : "");
} }

View File

@@ -53,6 +53,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -83,10 +84,10 @@ final class ID3_Frame_AENC extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2);
$this->_previewStart = substr($this->_data, 0, 2); $this->_previewStart = Transform::fromUInt16BE(substr($this->_data, 0, 2));
$this->_previewLength = substr($this->_data, 2, 2); $this->_previewLength = Transform::fromUInt16BE(substr($this->_data, 2, 2));
$this->_encryptionInfo = substr($this->_data, 4); $this->_encryptionInfo = substr($this->_data, 4);
} }
@@ -163,8 +164,8 @@ final class ID3_Frame_AENC extends ID3_Frame
public function __toString() public function __toString()
{ {
$this->setData $this->setData
($this->_owner . "\0" . Transform::toInt16BE($this->_previewStart) . ($this->_owner . "\0" . Transform::toUInt16BE($this->_previewStart) .
Transform::toInt16BE($this->_previewLength) . $this->_encryptionInfo); Transform::toUInt16BE($this->_previewLength) . $this->_encryptionInfo);
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -56,6 +56,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -93,6 +94,9 @@ final class ID3_Frame_APIC extends ID3_Frame
/** @var string */ /** @var string */
private $_imageData; private $_imageData;
/** @var integer */
private $_imageSize = 0;
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
@@ -106,27 +110,29 @@ final class ID3_Frame_APIC extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_mimeType = substr $this->_mimeType = substr
($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1); ($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1);
$this->_imageType = Transform::fromInt8($this->_data[$pos++]); $this->_imageType = Transform::fromUInt8($this->_data[++$pos]);
$this->_data = substr($this->_data, $pos); $this->_data = substr($this->_data, $pos + 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list ($this->_description, $this->_data) = list ($this->_description, $this->_imageData) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
break; break;
case self::UTF16BE: case self::UTF16BE:
list ($this->_description, $this->_data) = list ($this->_description, $this->_imageData) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
break; break;
default: default:
list ($this->_description, $this->_data) = list ($this->_description, $this->_imageData) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
} }
$this->_imageSize = strlen($this->_imageData);
} }
/** /**
@@ -197,14 +203,26 @@ final class ID3_Frame_APIC extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_imageData; } public function getImageData() { return $this->_imageData; }
/** /**
* Sets the embedded image data. * Sets the embedded image data. Also updates the image size field to
* correspond the new data.
* *
* @param string $imageData The image data. * @param string $imageData The image data.
*/ */
public function setData($imageData) { $this->_imageData = $imageData; } public function setImageData($imageData)
{
$this->_imageData = $imageData;
$this->_imageSize = strlen($imageData);
}
/**
* Returns the size of the embedded image data.
*
* @return integer
*/
public function getImageSize() { return $this->_imageSize; }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
@@ -213,18 +231,19 @@ final class ID3_Frame_APIC extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_mimeType . "\0" . $data = Transform::toUInt8($this->_encoding) . $this->_mimeType . "\0" .
Transform::toInt8($this->_imageType); Transform::toUInt8($this->_imageType);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0"; case self::UTF16LE:
$data .= Transform::toString16
($this->_description, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) .
"\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0"; $data .= Transform::toString16BE($this->_description) . "\0\0";
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0";
break;
default: default:
$data .= $this->_description . "\0"; $data .= $this->_description . "\0";
} }

View File

@@ -45,6 +45,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -65,7 +66,7 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame
parent::__construct($reader, $options); parent::__construct($reader, $options);
if ($reader !== null) if ($reader !== null)
$this->_link = implode(preg_split("/\\x00/", $this->_data, 1), ""); $this->_link = implode($this->explodeString8($this->_data, 1), "");
} }
/** /**

View File

@@ -46,6 +46,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -80,20 +81,20 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_data = substr($this->_data, 1); $this->_data = substr($this->_data, 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$this->_text = $this->_text =
preg_split("/\\x00\\x00/", Transform::fromString16($this->_data)); $this->explodeString16(Transform::fromString16($this->_data));
break; break;
case self::UTF16BE: case self::UTF16BE:
$this->_text = $this->_text =
preg_split("/\\x00\\x00/", Transform::fromString16BE($this->_data)); $this->explodeString16(Transform::fromString16BE($this->_data));
break; break;
default: default:
$this->_text = $this->_text =
preg_split("/\\x00/", Transform::fromString8($this->_data)); $this->explodeString8(Transform::fromString8($this->_data));
} }
} }
@@ -146,17 +147,20 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding); $data = Transform::toUInt8($this->_encoding);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16(implode("\0\0", $this->_text)); case self::UTF16LE:
$array = $this->_text;
foreach ($array as &$text)
$text = Transform::toString16($str);
$data .= Transform::toString16
(implode("\0\0", $array), $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE(implode("\0\0", $this->_text)); $data .= Transform::toString16BE(implode("\0\0", $this->_text));
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE(implode("\0\0", $this->_text));
break;
default: default:
$data .= implode("\0", $this->_text); $data .= implode("\0", $this->_text);
} }

View File

@@ -53,6 +53,7 @@ require_once("ID3/Exception.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -64,7 +65,7 @@ final class ID3_Frame_COMM extends ID3_Frame
private $_encoding = ID3_Encoding::UTF8; private $_encoding = ID3_Encoding::UTF8;
/** @var string */ /** @var string */
private $_language = "eng"; private $_language = "und";
/** @var string */ /** @var string */
private $_description; private $_description;
@@ -85,26 +86,28 @@ final class ID3_Frame_COMM extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_language = substr($this->_data, 1, 3); $this->_language = substr($this->_data, 1, 3);
if ($this->_language == "XXX")
$this->_language = "und";
$this->_data = substr($this->_data, 4); $this->_data = substr($this->_data, 4);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
$this->_text = Transform::fromString16($this->_text); $this->_text = Transform::fromString16($this->_text);
break; break;
case self::UTF16BE: case self::UTF16BE:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
$this->_text = Transform::fromString16BE($this->_text); $this->_text = Transform::fromString16BE($this->_text);
break; break;
default: default:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
$this->_description = Transform::fromString8($this->_description); $this->_description = Transform::fromString8($this->_description);
$this->_text = Transform::fromString8($this->_text); $this->_text = Transform::fromString8($this->_text);
} }
@@ -140,7 +143,12 @@ final class ID3_Frame_COMM extends ID3_Frame
* @see ID3_Language * @see ID3_Language
* @param string $language The language code. * @param string $language The language code.
*/ */
public function setLanguage($language) { $this->_language = $language; } public function setLanguage($language)
{
if ($language == "XXX")
$language = "und";
$this->_language = substr($language, 0, 3);
}
/** /**
* Returns the short content description. * Returns the short content description.
@@ -162,9 +170,9 @@ final class ID3_Frame_COMM extends ID3_Frame
{ {
$this->_description = $description; $this->_description = $description;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
@@ -186,9 +194,9 @@ final class ID3_Frame_COMM extends ID3_Frame
{ {
$this->_text = $text; $this->_text = $text;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
@@ -198,19 +206,18 @@ final class ID3_Frame_COMM extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_language; $data = Transform::toUInt8($this->_encoding) . $this->_language;
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_text); $order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
$data .= Transform::toString16($this->_description, $order) . "\0\0" .
Transform::toString16($this->_text, $order);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0" . $data .= Transform::toString16BE
Transform::toString16BE($this->_text); ($this->_description . "\0\0" . $this->_text);
break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0" .
Transform::toString16LE($this->_text);
break; break;
default: default:
$data .= $this->_description . "\0" . $this->_text; $data .= $this->_description . "\0" . $this->_text;

View File

@@ -52,6 +52,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -100,6 +101,9 @@ final class ID3_Frame_COMR extends ID3_Frame
/** @var string */ /** @var string */
private $_imageData; private $_imageData;
/** @var integer */
private $_imageSize = 0;
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
@@ -113,33 +117,33 @@ final class ID3_Frame_COMR extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
list($pricing, $this->_data) = list($pricing, $this->_data) =
preg_split("/\\x00/", substr($this->_data, 1), 2); $this->explodeString8(substr($this->_data, 1), 2);
$this->_currency = substr($pricing, 0, 3); $this->_currency = substr($pricing, 0, 3);
$this->_price = substr($pricing, 3); $this->_price = substr($pricing, 3);
$this->_date = substr($this->_data, 0, 8); $this->_date = substr($this->_data, 0, 8);
list($this->_contact, $this->_data) = list($this->_contact, $this->_data) =
preg_split("/\\x00/", substr($this->_data, 8), 2); $this->explodeString8(substr($this->_data, 8), 2);
$this->_delivery = Transform::fromInt8($this->_data[0]); $this->_delivery = Transform::fromUInt8($this->_data[0]);
$this->_data = substr($this->_data, 1); $this->_data = substr($this->_data, 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list ($this->_seller, $this->_description, $this->_data) = list ($this->_seller, $this->_description, $this->_data) =
preg_split("/\\x00\\x00/", $this->_data, 3); $this->explodeString16($this->_data, 3);
$this->_seller = Transform::fromString16($this->_seller); $this->_seller = Transform::fromString16($this->_seller);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
break; break;
case self::UTF16BE: case self::UTF16BE:
list ($this->_seller, $this->_description, $this->_data) = list ($this->_seller, $this->_description, $this->_data) =
preg_split("/\\x00\\x00/", $this->_data, 3); $this->explodeString16($this->_data, 3);
$this->_seller = Transform::fromString16BE($this->_seller); $this->_seller = Transform::fromString16BE($this->_seller);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
break; break;
default: default:
list ($this->_seller, $this->_description, $this->_data) = list ($this->_seller, $this->_description, $this->_data) =
preg_split("/\\x00/", $this->_data, 3); $this->explodeString8($this->_data, 3);
$this->_seller = Transform::fromString8($this->_seller); $this->_seller = Transform::fromString8($this->_seller);
$this->_description = Transform::fromString8($this->_description); $this->_description = Transform::fromString8($this->_description);
} }
@@ -148,7 +152,9 @@ final class ID3_Frame_COMR extends ID3_Frame
return; return;
list($this->_mimeType, $this->_imageData) = list($this->_mimeType, $this->_imageData) =
preg_split("/\\x00/", $this->_imageData, 2); $this->explodeString8($this->_data, 2);
$this->_imageSize = strlen($this->_imageData);
} }
/** /**
@@ -211,7 +217,7 @@ final class ID3_Frame_COMR extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getDate() { return $this->_price; } public function getDate() { return $this->_date; }
/** /**
* Sets the date describing for how long the price is valid for. The date must * Sets the date describing for how long the price is valid for. The date must
@@ -313,14 +319,26 @@ final class ID3_Frame_COMR extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_imageData; } public function getImageData() { return $this->_imageData; }
/** /**
* Sets the embedded image data. * Sets the embedded image data. Also updates the image size to correspond the
* new data.
* *
* @param string $imageData The image data. * @param string $imageData The image data.
*/ */
public function setData($imageData) { $this->_imageData = $imageData; } public function setImageData($imageData)
{
$this->_imageData = $imageData;
$this->_imageSize = strlen($imageData);
}
/**
* Returns the size of the embedded image data.
*
* @return integer
*/
public function getImageSize() { return $this->_imageSize; }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
@@ -329,28 +347,27 @@ final class ID3_Frame_COMR extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_price . "\0" . $data = Transform::toUInt8($this->_encoding) . $this->_currency .
$this->_date . $this->_contact . "\0" . $this->_price . "\0" . $this->_date . $this->_contact . "\0" .
Transform::toInt8($this->_delivery); Transform::toUInt8($this->_delivery);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_seller) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_description) . "\0\0"; $order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
$data .= Transform::toString16($this->_seller, $order) . "\0\0" .
Transform::toString16($this->_description, $order) . "\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_seller) . "\0\0"; $data .= Transform::toString16BE
Transform::toString16($this->_description) . "\0\0"; ($this->_seller . "\0\0" . $this->_description . "\0\0");
break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_seller) . "\0\0";
Transform::toString16($this->_description) . "\0\0";
break; break;
default: default:
$data .= $this->_seller . "\0" . $this->_description . "\0"; $data .= $this->_seller . "\0" . $this->_description . "\0";
} }
parent::setData parent::setData
($data . ($this->_mimeType ? ($data . ($this->_mimeType ?
$this->_mimeType . "\0" . $this->_imageData : 0)); $this->_mimeType . "\0" . $this->_imageData : ""));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -62,6 +62,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -90,7 +91,7 @@ final class ID3_Frame_ENCR extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2);
$this->_method = Transform::fromInt8($this->_data[0]); $this->_method = Transform::fromInt8($this->_data[0]);
$this->_encryptionData = substr($this->_data, 1); $this->_encryptionData = substr($this->_data, 1);
} }
@@ -128,14 +129,14 @@ final class ID3_Frame_ENCR extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_encryptionData; } public function getEncryptionData() { return $this->_encryptionData; }
/** /**
* Sets the encryption data. * Sets the encryption data.
* *
* @param string $encryptionData The encryption data string. * @param string $encryptionData The encryption data string.
*/ */
public function setData($encryptionData) public function setEncryptionData($encryptionData)
{ {
$this->_encryptionData = $encryptionData; $this->_encryptionData = $encryptionData;
} }

View File

@@ -49,6 +49,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -93,13 +94,13 @@ final class ID3_Frame_EQU2 extends ID3_Frame
$this->_interpolation = Transform::fromInt8($this->_data[0]); $this->_interpolation = Transform::fromInt8($this->_data[0]);
list ($this->_device, $this->_data) = list ($this->_device, $this->_data) =
preg_split("/\\x00/", substr($this->_data, 1), 2); $this->explodeString8(substr($this->_data, 1), 2);
for ($i = 0; $i < strlen($this->_data); $i += 8) for ($i = 0; $i < strlen($this->_data); $i += 4)
$this->_adjustments $this->_adjustments
[Transform::fromInt16BE(substr($this->_data, $i, 2)) / 2] = [(int)(Transform::fromUInt16BE(substr($this->_data, $i, 2)) / 2)] =
Transform::fromInt16BE(substr($this->_data, $i + 2, 2)) / 512; Transform::fromInt16BE(substr($this->_data, $i + 2, 2)) / 512.0;
sort($this->_adjustments); ksort($this->_adjustments);
} }
/** /**
@@ -149,7 +150,7 @@ final class ID3_Frame_EQU2 extends ID3_Frame
/** /**
* Adds a volume adjustment setting for given frequency. The frequency can * Adds a volume adjustment setting for given frequency. The frequency can
* have a value from 0 to 32767 Hz, and the adjustment +/- 64 dB with a * have a value from 0 to 32767 Hz, and the adjustment </> +/- 64 dB with a
* precision of 0.001953125 dB. * precision of 0.001953125 dB.
* *
* @param integer $frequency The frequency, in hertz. * @param integer $frequency The frequency, in hertz.
@@ -157,23 +158,22 @@ final class ID3_Frame_EQU2 extends ID3_Frame
*/ */
public function addAdjustment($frequency, $adjustment) public function addAdjustment($frequency, $adjustment)
{ {
$this->_adjustments[$frequency * 2] = $adjustment * 512; $this->_adjustments[$frequency] = $adjustment;
sort($this->_adjustments); ksort($this->_adjustments);
} }
/** /**
* Sets the adjustments array. The array must have frequencies as keys and * Sets the adjustments array. The array must have frequencies as keys and
* their corresponding adjustments as values. The frequency can have a value * their corresponding adjustments as values. The frequency can have a value
* from 0 to 32767 Hz, and the adjustment +/- 64 dB with a precision of * from 0 to 32767 Hz, and the adjustment </> +/- 64 dB with a precision of
* 0.001953125 dB. One frequency should only be described once in the frame. * 0.001953125 dB. One frequency should only be described once in the frame.
* *
* @param Array $adjustments The adjustments array. * @param Array $adjustments The adjustments array.
*/ */
public function setAdjustments($adjustments) public function setAdjustments($adjustments)
{ {
foreach ($adjustments as $frequency => $adjustment) $this->_adjustments = $adjustments;
$this->_adjustments[$frequency * 2] = $adjustment * 512; ksort($this->_adjustments);
sort($this->_adjustments);
} }
/** /**
@@ -185,8 +185,8 @@ final class ID3_Frame_EQU2 extends ID3_Frame
{ {
$data = Transform::toInt8($this->_interpolation) . $this->_device . "\0"; $data = Transform::toInt8($this->_interpolation) . $this->_device . "\0";
foreach ($this->_adjustments as $frequency => $adjustment) foreach ($this->_adjustments as $frequency => $adjustment)
$data .= $data .= Transform::toUInt16BE($frequency * 2) .
Transform::toInt16BE($frequency) . Transform::toInt16BE($adjustment); Transform::toInt16BE($adjustment * 512);
$this->setData($data); $this->setData($data);
return parent::__toString(); return parent::__toString();
} }

View File

@@ -48,6 +48,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -71,14 +72,19 @@ final class ID3_Frame_EQUA extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$adjustmentBits = Transform::fromInt8($this->_data[0]); //16 $adjustmentBits = Transform::fromInt8($this->_data[0]);
if ($adjustmentBits <= 8 || $adjustmentBits > 16)
throw new ID3_Exception
("Unsupported adjustment bit size of: " . $adjustmentBits);
for ($i = 1; $i < strlen($this->_data); $i += 4) { for ($i = 1; $i < strlen($this->_data); $i += 4) {
$frequency = Transform::fromInt16BE(substr($this->_data, $i, 2)); $frequency = Transform::fromUInt16BE(substr($this->_data, $i, 2));
$this->_adjustments[($frequency & 0x7fff)] = $this->_adjustments[($frequency & 0x7fff)] =
($frequency & 0x2000) == 0x2000 ? ($frequency & 0x8000) == 0x8000 ?
Transform::fromInt16BE(substr($this->_data, $j + 2, 2)) : Transform::fromUInt16BE(substr($this->_data, $i + 2, 2)) :
-Transform::fromInt16BE(substr($this->_data, $j + 2, 2)); -Transform::fromUInt16BE(substr($this->_data, $i + 2, 2));
} }
ksort($this->_adjustments);
} }
/** /**
@@ -99,8 +105,9 @@ final class ID3_Frame_EQUA extends ID3_Frame
public function addAdjustment($frequency, $adjustment) public function addAdjustment($frequency, $adjustment)
{ {
$this->_adjustments[$frequency] = $adjustment; $this->_adjustments[$frequency] = $adjustment;
ksort($this->_adjustments);
} }
/** /**
* Sets the adjustments array. The array must have frequencies as keys and * Sets the adjustments array. The array must have frequencies as keys and
* their corresponding adjustments as values. The frequency can have a value * their corresponding adjustments as values. The frequency can have a value
@@ -112,6 +119,7 @@ final class ID3_Frame_EQUA extends ID3_Frame
public function setAdjustments($adjustments) public function setAdjustments($adjustments)
{ {
$this->_adjustments = $adjustments; $this->_adjustments = $adjustments;
ksort($this->_adjustments);
} }
/** /**
@@ -123,9 +131,9 @@ final class ID3_Frame_EQUA extends ID3_Frame
{ {
$data = Transform::toInt8(16); $data = Transform::toInt8(16);
foreach ($this->_adjustments as $frequency => $adjustment) foreach ($this->_adjustments as $frequency => $adjustment)
$data .= Transform::toInt16BE $data .= Transform::toUInt16BE
($adjustment > 0 ? $frequency | 0x2000 : $frequency & ~0x2000) . ($adjustment > 0 ? $frequency | 0x8000 : $frequency & ~0x8000) .
Transform::toInt16BE(abs($adjustment)); Transform::toUInt16BE(abs($adjustment));
$this->setData($data); $this->setData($data);
return parent::__toString(); return parent::__toString();
} }

View File

@@ -57,6 +57,7 @@ require_once("ID3/Timing.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -85,7 +86,7 @@ final class ID3_Frame_ETCO extends ID3_Frame
"One more byte of events follows"); "One more byte of events follows");
/** @var integer */ /** @var integer */
private $_format = 1; private $_format = ID3_Timing::MPEG_FRAMES;
/** @var Array */ /** @var Array */
private $_events = array(); private $_events = array();
@@ -103,14 +104,14 @@ final class ID3_Frame_ETCO extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_format = Transform::fromInt8($this->_data[0]); $this->_format = Transform::fromUInt8($this->_data[0]);
for ($i = 1; $i < $this->getSize(); $i += 5) { for ($i = 1; $i < $this->getSize(); $i += 5) {
$this->_events[Transform::fromInt32BE(substr($this->_data, $i + 1, 4))] = $this->_events[Transform::fromUInt32BE(substr($this->_data, $i + 1, 4))] =
$data = Transform::fromInt8($this->_data[$i]); $data = Transform::fromUInt8($this->_data[$i]);
if ($data == 0xff) if ($data == 0xff)
break; break;
} }
sort($this->_events); ksort($this->_events);
} }
/** /**
@@ -145,9 +146,10 @@ final class ID3_Frame_ETCO extends ID3_Frame
*/ */
public function setEvents($events, $format = false) public function setEvents($events, $format = false)
{ {
$this->_events = events; $this->_events = $events;
if ($format !== false) if ($format !== false)
$this->_format = $format; $this->_format = $format;
ksort($this->_events);
} }
/** /**
@@ -157,10 +159,9 @@ final class ID3_Frame_ETCO extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_format); $data = Transform::toUInt8($this->_format);
sort($this->_events);
foreach ($this->_events as $timestamp => $type) foreach ($this->_events as $timestamp => $type)
$data .= Transform::toInt8($type) . Transform::toInt32BE($timestamp); $data .= Transform::toUInt8($type) . Transform::toUInt32BE($timestamp);
$this->setData($data); $this->setData($data);
return parent::__toString(); return parent::__toString();
} }

View File

@@ -47,6 +47,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -82,27 +83,27 @@ final class ID3_Frame_GEOB extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_mimeType = substr $this->_mimeType = substr
($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1); ($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1);
$this->_data = substr($this->_data, $pos); $this->_data = substr($this->_data, $pos + 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list ($this->_filename, $this->_description, $this->_data) = list ($this->_filename, $this->_description, $this->_objectData) =
preg_split("/\\x00\\x00/", $this->_data, 3); $this->explodeString16($this->_data, 3);
$this->_filename = Transform::fromString16($this->_filename); $this->_filename = Transform::fromString16($this->_filename);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
break; break;
case self::UTF16BE: case self::UTF16BE:
list ($this->_filename, $this->_description, $this->_data) = list ($this->_filename, $this->_description, $this->_objectData) =
preg_split("/\\x00\\x00/", $this->_data, 3); $this->explodeString16($this->_data, 3);
$this->_filename = Transform::fromString16BE($this->_filename); $this->_filename = Transform::fromString16BE($this->_filename);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
break; break;
default: default:
list ($this->_filename, $this->_description, $this->_data) = list ($this->_filename, $this->_description, $this->_objectData) =
preg_split("/\\x00/", $this->_data, 3); $this->explodeString8($this->_data, 3);
$this->_filename = Transform::fromString8($this->_filename); $this->_filename = Transform::fromString8($this->_filename);
$this->_description = Transform::fromString8($this->_description); $this->_description = Transform::fromString8($this->_description);
} }
@@ -184,14 +185,17 @@ final class ID3_Frame_GEOB extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_objectData; } public function getObjectData() { return $this->_objectData; }
/** /**
* Sets the embedded object binary data. * Sets the embedded object binary data.
* *
* @param string $objectData The object data. * @param string $objectData The object data.
*/ */
public function setData($objectData) { $this->_objectData = $objectData; } public function setObjectData($objectData)
{
$this->_objectData = $objectData;
}
/** /**
* Returns the frame raw data. * Returns the frame raw data.
@@ -200,19 +204,18 @@ final class ID3_Frame_GEOB extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_mimeType . "\0"; $data = Transform::toUInt8($this->_encoding) . $this->_mimeType . "\0";
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_filename) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_description) . "\0\0"; $order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
$data .= Transform::toString16($this->_filename, $order) . "\0\0" .
Transform::toString16($this->_description, $order) . "\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_filename) . "\0\0" . $data .= Transform::toString16BE
Transform::toString16BE($this->_description) . "\0\0"; ($this->_filename . "\0\0" . $this->_description . "\0\0");
break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_filename) . "\0\0" .
Transform::toString16LE($this->_description) . "\0\0";
break; break;
default: default:
$data .= $this->_filename . "\0" . $this->_description . "\0"; $data .= $this->_filename . "\0" . $this->_description . "\0";

View File

@@ -61,6 +61,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -89,8 +90,8 @@ final class ID3_Frame_GRID extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2);
$this->_group = Transform::fromInt8($this->_data[0]); $this->_group = Transform::fromUInt8($this->_data[0]);
$this->_groupData = substr($this->_data, 1); $this->_groupData = substr($this->_data, 1);
} }
@@ -127,14 +128,14 @@ final class ID3_Frame_GRID extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_groupData; } public function getGroupData() { return $this->_groupData; }
/** /**
* Sets the group dependent data. * Sets the group dependent data.
* *
* @param string $groupData The data. * @param string $groupData The data.
*/ */
public function setData($groupData) { $this->_groupData = $groupData; } public function setGroupData($groupData) { $this->_groupData = $groupData; }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
@@ -144,7 +145,7 @@ final class ID3_Frame_GRID extends ID3_Frame
public function __toString() public function __toString()
{ {
parent::setData parent::setData
($this->_owner . "\0" . Transform::toInt8($this->_group) . ($this->_owner . "\0" . Transform::toUInt8($this->_group) .
$this->_groupData); $this->_groupData);
return parent::__toString(); return parent::__toString();
} }

View File

@@ -49,6 +49,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -59,10 +60,10 @@ final class ID3_Frame_IPLS extends ID3_Frame
{ {
/** @var integer */ /** @var integer */
private $_encoding = ID3_Encoding::UTF8; private $_encoding = ID3_Encoding::UTF8;
/** @var Array */ /** @var Array */
private $_people = array(); private $_people = array();
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
@@ -72,71 +73,75 @@ final class ID3_Frame_IPLS extends ID3_Frame
public function __construct($reader = null, &$options = array()) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader, $options); parent::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$data = array(); $data = substr($this->_data, 1);
$order = Transform::MACHINE_ENDIAN_ORDER;
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data = preg_split $data = $this->explodeString16($data);
("/\\x00\\x00/", Transform::fromString16($this->_data)); foreach ($data as &$str)
$str = Transform::fromString16($str, $order);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data = preg_split $data = $this->explodeString16($data);
("/\\x00\\x00/", Transform::fromString16BE($this->_data)); foreach ($data as &$str)
$str = Transform::fromString16BE($str);
break; break;
default: default:
$data = preg_split("/\\x00/", $this->_data); $data = $this->explodeString8($data);
} }
for ($i = 0; $i < count($data); $i+=2)
for ($i = 0; $i < count($data) - 1; $i += 2)
$this->_people[] = array($data[$i] => @$data[$i + 1]); $this->_people[] = array($data[$i] => @$data[$i + 1]);
} }
/** /**
* Returns the text encoding. * Returns the text encoding.
* *
* @return integer * @return integer
*/ */
public function getEncoding() { return $this->_encoding; } public function getEncoding() { return $this->_encoding; }
/** /**
* Sets the text encoding. * Sets the text encoding.
* *
* @see ID3_Encoding * @see ID3_Encoding
* @param integer $encoding The text encoding. * @param integer $encoding The text encoding.
*/ */
public function setEncoding($encoding) { $this->_encoding = $encoding; } public function setEncoding($encoding) { $this->_encoding = $encoding; }
/** /**
* Returns the involved people list as an array. For each person, the array * Returns the involved people list as an array. For each person, the array
* contains an entry, which too is an associate array with involvement as its * contains an entry, which too is an associate array with involvement as its
* key and involvee as its value. * key and involvee as its value.
* *
* @return Array * @return Array
*/ */
public function getPeople() { return $this->_people; } public function getPeople() { return $this->_people; }
/** /**
* Adds a person with his involvement. * Adds a person with his involvement.
* *
* @return string * @return string
*/ */
public function addPerson($involvement, $person) public function addPerson($involvement, $person)
{ {
$this->_people[] = array($involvement => $person); $this->_people[] = array($involvement => $person);
} }
/** /**
* Sets the involved people list array. For each person, the array must * Sets the involved people list array. For each person, the array must
* contain an associate array with involvement as its key and involvee as its * contain an associate array with involvement as its key and involvee as its
* value. * value.
* *
* @param Array $people The involved people list. * @param Array $people The involved people list.
*/ */
public function setPeople($people) { $this->_people = $people; } public function setPeople($people) { $this->_people = $people; }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
* *
@@ -144,19 +149,20 @@ final class ID3_Frame_IPLS extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding); $data = Transform::toUInt8($this->_encoding);
$order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
foreach ($this->_people as $entry) { foreach ($this->_people as $entry) {
foreach ($entry as $key => $val) { foreach ($entry as $key => $val) {
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($key . "\0\0" . $val . "\0\0"); case self::UTF16LE:
$data .= Transform::toString16($key, $order) . "\0\0" .
Transform::toString16($val, $order) . "\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($key . "\0\0" . $val . "\0\0"); $data .= Transform::toString16BE($key . "\0\0" . $val . "\0\0");
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($key . "\0\0" . $val . "\0\0");
break;
default: default:
$data .= $key . "\0" . $val . "\0"; $data .= $key . "\0" . $val . "\0";
} }

View File

@@ -79,6 +79,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -109,7 +110,7 @@ final class ID3_Frame_LINK extends ID3_Frame
$this->_target = substr($this->_data, 0, 4); $this->_target = substr($this->_data, 0, 4);
list($this->_url, $this->_qualifier) = list($this->_url, $this->_qualifier) =
preg_split("/\\x00/", substr($this->_data, 4), 2); $this->explodeString8(substr($this->_data, 4), 2);
} }
/** /**

View File

@@ -50,6 +50,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -85,9 +86,9 @@ final class ID3_Frame_OWNE extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
list($tmp, $this->_data) = list($tmp, $this->_data) =
preg_split("/\\x00/", substr($this->_data, 1), 2); $this->explodeString8(substr($this->_data, 1), 2);
$this->_currency = substr($tmp, 0, 3); $this->_currency = substr($tmp, 0, 3);
$this->_price = substr($tmp, 3); $this->_price = substr($tmp, 3);
$this->_date = substr($this->_data, 0, 8); $this->_date = substr($this->_data, 0, 8);
@@ -197,18 +198,18 @@ final class ID3_Frame_OWNE extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_currency . $data = Transform::toUInt8($this->_encoding) . $this->_currency .
$this->_price . "\0" . $this->_date; $this->_price . "\0" . $this->_date;
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_seller); case self::UTF16LE:
$data .= Transform::toString16
($this->_seller, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_seller); $data .= Transform::toString16BE($this->_seller);
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_seller);
break;
default: default:
$data .= $this->_seller; $data .= $this->_seller;
} }

View File

@@ -47,6 +47,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -70,7 +71,7 @@ final class ID3_Frame_PCNT extends ID3_Frame
return; return;
if (strlen($this->_data) > 4) if (strlen($this->_data) > 4)
$this->_counter = Transform::fromInt64BE($this->_data); $this->_counter = Transform::fromInt64BE($this->_data); // UInt64
else else
$this->_counter = Transform::fromUInt32BE($this->_data); $this->_counter = Transform::fromUInt32BE($this->_data);
} }
@@ -103,8 +104,8 @@ final class ID3_Frame_PCNT extends ID3_Frame
{ {
$this->setData $this->setData
($this->_counter > 4294967295 ? ($this->_counter > 4294967295 ?
Transform::toInt64BE($this->_counter) : Transform::toInt64BE($this->_counter) : // UInt64
Transform::toInt32BE($this->_counter)); Transform::toUInt32BE($this->_counter));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -58,6 +58,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -66,13 +67,13 @@ final class ID3_Frame_POPM extends ID3_Frame
{ {
/** @var string */ /** @var string */
private $_owner; private $_owner;
/** @var integer */ /** @var integer */
private $_rating = 0; private $_rating = 0;
/** @var integer */ /** @var integer */
private $_counter = 0; private $_counter = 0;
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
@@ -82,67 +83,67 @@ final class ID3_Frame_POPM extends ID3_Frame
public function __construct($reader = null, &$options = array()) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader, $options); parent::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2);
$this->_rating = Transform::fromInt8($this->_data[0]); $this->_rating = Transform::fromUInt8($this->_data[0]);
$this->_data = substr($this->_data, 1); $this->_data = substr($this->_data, 1);
if (strlen($this->_data) > 4) if (strlen($this->_data) > 4)
$this->_counter = Transform::fromInt64BE($this->_data); $this->_counter = Transform::fromInt64BE($this->_data); // UInt64
else if (strlen($this->_data) > 0) else if (strlen($this->_data) > 0)
$this->_counter = Transform::fromUInt32BE($this->_data); $this->_counter = Transform::fromUInt32BE($this->_data);
} }
/** /**
* Returns the owner identifier string. * Returns the owner identifier string.
* *
* @return string * @return string
*/ */
public function getOwner() { return $this->_owner; } public function getOwner() { return $this->_owner; }
/** /**
* Sets the owner identifier string. * Sets the owner identifier string.
* *
* @param string $owner The owner identifier string. * @param string $owner The owner identifier string.
*/ */
public function setOwner($owner) { return $this->_owner = $owner; } public function setOwner($owner) { return $this->_owner = $owner; }
/** /**
* Returns the user rating. * Returns the user rating.
* *
* @return integer * @return integer
*/ */
public function getRating() { return $this->_rating; } public function getRating() { return $this->_rating; }
/** /**
* Sets the user rating. * Sets the user rating.
* *
* @param integer $rating The user rating. * @param integer $rating The user rating.
*/ */
public function setRating($rating) { $this->_rating = $rating; } public function setRating($rating) { $this->_rating = $rating; }
/** /**
* Returns the counter. * Returns the counter.
* *
* @return integer * @return integer
*/ */
public function getCounter() { return $this->_counter; } public function getCounter() { return $this->_counter; }
/** /**
* Adds counter by one. * Adds counter by one.
*/ */
public function addCounter() { $this->_counter++; } public function addCounter() { $this->_counter++; }
/** /**
* Sets the counter value. * Sets the counter value.
* *
* @param integer $counter The counter value. * @param integer $counter The counter value.
*/ */
public function setCounter($counter) { $this->_counter = $counter; } public function setCounter($counter) { $this->_counter = $counter; }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
* *
@@ -152,9 +153,9 @@ final class ID3_Frame_POPM extends ID3_Frame
{ {
$this->setData $this->setData
($this->_owner . "\0" . Transform::toInt8($this->_rating) . ($this->_owner . "\0" . Transform::toInt8($this->_rating) .
($this->_counter > 4294967295 ? ($this->_counter > 0xffffffff ?
Transform::toInt64BE($this->_counter) : Transform::toInt64BE($this->_counter) :
($this->_counter > 0 ? Transform::toInt32BE($this->_counter) : 0))); ($this->_counter > 0 ? Transform::toUInt32BE($this->_counter) : 0)));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -49,6 +49,7 @@ require_once("ID3/Timing.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -57,9 +58,9 @@ final class ID3_Frame_POSS extends ID3_Frame
implements ID3_Timing implements ID3_Timing
{ {
/** @var integer */ /** @var integer */
private $_format = 1; private $_format = ID3_Timing::MPEG_FRAMES;
/** @var string */ /** @var integer */
private $_position; private $_position;
/** /**
@@ -74,8 +75,8 @@ final class ID3_Frame_POSS extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_format = Transform::fromInt8($this->_data[0]); $this->_format = Transform::fromUInt8($this->_data[0]);
$this->_position = Transform::fromUInt32BE(substr($this->_data, 1, 4)); $this->_position = Transform::fromUInt32BE(substr($this->_data, 1, 4));
} }
@@ -124,8 +125,8 @@ final class ID3_Frame_POSS extends ID3_Frame
public function __toString() public function __toString()
{ {
$this->setData $this->setData
(Transform::toInt8($this->_format) . (Transform::toUInt8($this->_format) .
Transform::toUInt32($this->_position)); Transform::toUInt32BE($this->_position));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -52,6 +52,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -78,7 +79,7 @@ final class ID3_Frame_PRIV extends ID3_Frame
return; return;
list($this->_owner, $this->_privateData) = list($this->_owner, $this->_privateData) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
} }
/** /**
@@ -100,14 +101,17 @@ final class ID3_Frame_PRIV extends ID3_Frame
* *
* @return string * @return string
*/ */
public function getData() { return $this->_privateData; } public function getPrivateData() { return $this->_privateData; }
/** /**
* Sets the private binary data associated with the frame. * Sets the private binary data associated with the frame.
* *
* @param string $privateData The private binary data string. * @param string $privateData The private binary data string.
*/ */
public function setData($privateData) { $this->_privateData = $privateData; } public function setPrivateData($privateData)
{
$this->_privateData = $privateData;
}
/** /**
* Returns the frame raw data. * Returns the frame raw data.

View File

@@ -66,6 +66,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -79,13 +80,13 @@ final class ID3_Frame_RBUF extends ID3_Frame
const EMBEDDED = 0x1; const EMBEDDED = 0x1;
/** @var integer */ /** @var integer */
private $_size; private $_bufferSize;
/** @var integer */ /** @var integer */
private $_flags; private $_infoFlags;
/** @var integer */ /** @var integer */
private $_offset; private $_offset = 0;
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
@@ -99,10 +100,12 @@ final class ID3_Frame_RBUF extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_size = Transform::fromInt32BE(substr($this->_data, 0, 3)); $this->_bufferSize =
$this->_flags = Transform::fromInt8($this->_data[3]); Transform::fromUInt32BE("\0" . substr($this->_data, 0, 3));
$this->_offset = Transform::fromInt32BE(substr($this->_data, 4, 4)); $this->_infoFlags = Transform::fromInt8($this->_data[3]);
if ($this->getSize() > 4)
$this->_offset = Transform::fromInt32BE(substr($this->_data, 4, 4));
} }
/** /**
@@ -110,14 +113,17 @@ final class ID3_Frame_RBUF extends ID3_Frame
* *
* @return integer * @return integer
*/ */
public function getSize() { return $this->_size; } public function getBufferSize() { return $this->_bufferSize; }
/** /**
* Sets the buffer size. * Sets the buffer size.
* *
* @param integer $size The buffer size. * @param integer $size The buffer size.
*/ */
public function setSize($size) { $this->_size = $size; } public function setBufferSize($bufferSize)
{
$this->_bufferSize = $bufferSize;
}
/** /**
* Checks whether or not the flag is set. Returns <var>true</var> if the flag * Checks whether or not the flag is set. Returns <var>true</var> if the flag
@@ -126,21 +132,24 @@ final class ID3_Frame_RBUF extends ID3_Frame
* @param integer $flag The flag to query. * @param integer $flag The flag to query.
* @return boolean * @return boolean
*/ */
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; } public function hasInfoFlag($flag)
{
return ($this->_infoFlags & $flag) == $flag;
}
/** /**
* Returns the flags byte. * Returns the flags byte.
* *
* @return integer * @return integer
*/ */
public function getFlags($flags) { return $this->_flags; } public function getInfoFlags() { return $this->_infoFlags; }
/** /**
* Sets the flags byte. * Sets the flags byte.
* *
* @param string $flags The flags byte. * @param string $flags The flags byte.
*/ */
public function setFlags($flags) { $this->_flags = $flags; } public function setInfoFlags($infoFlags) { $this->_infoFlags = $infoFlags; }
/** /**
* Returns the offset to next tag. * Returns the offset to next tag.
@@ -164,8 +173,9 @@ final class ID3_Frame_RBUF extends ID3_Frame
public function __toString() public function __toString()
{ {
$this->setData $this->setData
(substr(Transform::toInt32BE($this->_size) << 8, 0, 3) . (substr(Transform::toUInt32BE($this->_bufferSize), 1, 3) .
Transform::toInt8($this->_flags) . Transform::toInt32BE($this->_offset)); Transform::toInt8($this->_infoFlags) .
Transform::toInt32BE($this->_offset));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -57,6 +57,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -64,6 +65,29 @@ require_once("ID3/Frame.php");
*/ */
final class ID3_Frame_RVA2 extends ID3_Frame final class ID3_Frame_RVA2 extends ID3_Frame
{ {
/**
* The channel type key.
*
* @see $types
* @var string
*/
const channelType = "channelType";
/**
* The volume adjustment key. Adjustments are +/- 64 dB with a precision of
* 0.001953125 dB.
*
* @var string
*/
const volumeAdjustment = "volumeAdjustment";
/**
* The peak volume key.
*
* @var string
*/
const peakVolume = "peakVolume";
/** /**
* The list of channel types. * The list of channel types.
* *
@@ -72,13 +96,13 @@ final class ID3_Frame_RVA2 extends ID3_Frame
public static $types = array public static $types = array
("Other", "Master volume", "Front right", "Front left", "Back right", ("Other", "Master volume", "Front right", "Front left", "Back right",
"Back left", "Front centre", "Back centre", "Subwoofer"); "Back left", "Front centre", "Back centre", "Subwoofer");
/** @var string */ /** @var string */
private $_device; private $_device;
/** @var Array */ /** @var Array */
private $_adjustments; private $_adjustments;
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
@@ -88,45 +112,43 @@ final class ID3_Frame_RVA2 extends ID3_Frame
public function __construct($reader = null, &$options = array()) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader, $options); parent::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
list ($this->_device, $this->_data) = list ($this->_device, $this->_data) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
for ($i = $j = 0; $i < 9; $i++) { for ($i = $j = 0; $i < 9; $i++) {
$this->_adjustments[$i] = array $this->_adjustments[$i] = array
("channelType" => Transform::fromInt8($this->_data[$j++]), (self::channelType => Transform::fromInt8($this->_data[$j++]),
"volumeAdjustment" => self::volumeAdjustment =>
Transform::fromInt16BE(substr($this->_data, $j++, 2))); Transform::fromInt16BE(substr($this->_data, $j++, 2)) / 512.0);
$bitsInPeak = Transform::fromInt8($this->_data[(++$j)++]); $j++;
$bitsInPeak = Transform::fromInt8($this->_data[$j++]);
$bytesInPeak = $bitsInPeak > 0 ? ceil($bitsInPeak / 8) : 0; $bytesInPeak = $bitsInPeak > 0 ? ceil($bitsInPeak / 8) : 0;
switch ($bytesInPeak) { switch ($bytesInPeak) {
case 8: case 8:
case 7: case 7:
case 6: case 6:
case 5: case 5:
$this->_adjustments[$i]["peakVolume"] = $this->_adjustments[$i][self::peakVolume] =
Transform::fromInt64BE(substr($this->_data, $j, $bytesInPeak)); Transform::fromInt64BE(substr($this->_data, $j, $bytesInPeak));
$j += $bytesInPeak;
break; break;
case 4: case 4:
case 3: case 3:
$this->_adjustments[$i]["peakVolume"] = $this->_adjustments[$i][self::peakVolume] =
Transform::fromUInt32BE(substr($this->_data, $j, $bytesInPeak)); Transform::fromUInt32BE(substr($this->_data, $j, $bytesInPeak));
$j += $bytesInPeak;
break; break;
case 2: case 2:
$this->_adjustments[$i]["peakVolume"] = $this->_adjustments[$i][self::peakVolume] =
Transform::fromUInt16BE(substr($this->_data, $j, $bytesInPeak)); Transform::fromUInt16BE(substr($this->_data, $j, $bytesInPeak));
$j += $bytesInPeak;
break; break;
case 1: case 1:
$this->_adjustments[$i]["peakVolume"] = $this->_adjustments[$i][self::peakVolume] =
Transform::fromInt8(substr($this->_data, $j, $bytesInPeak)); Transform::fromUInt8(substr($this->_data, $j, $bytesInPeak));
$j += $bytesInPeak;
} }
$j += $bytesInPeak;
} }
} }
@@ -136,35 +158,35 @@ final class ID3_Frame_RVA2 extends ID3_Frame
* @return string * @return string
*/ */
public function getDevice() { return $this->_device; } public function getDevice() { return $this->_device; }
/** /**
* Sets the device where the adjustments should apply. * Sets the device where the adjustments should apply.
* *
* @param string $device The device. * @param string $device The device.
*/ */
public function setDevice($device) { $this->_device = $device; } public function setDevice($device) { $this->_device = $device; }
/** /**
* Returns the array containing volume adjustments for each channel. Volume * Returns the array containing volume adjustments for each channel. Volume
* adjustments are arrays themselves containing the following keys: * adjustments are arrays themselves containing the following keys:
* channelType, volumeAdjustment, peakVolume. * channelType, volumeAdjustment, peakVolume.
* *
* @return Array * @return Array
*/ */
public function getAdjustments() { return $this->_adjustments; } public function getAdjustments() { return $this->_adjustments; }
/** /**
* Sets the array of volume adjustments for each channel. Each volume * Sets the array of volume adjustments for each channel. Each volume
* adjustment is an array too containing the following keys: channelType, * adjustment is an array too containing the following keys: channelType,
* volumeAdjustment, peakVolume. * volumeAdjustment, peakVolume.
* *
* @param Array $adjustments The volume adjustments array. * @param Array $adjustments The volume adjustments array.
*/ */
public function setAdjustments($adjustments) public function setAdjustments($adjustments)
{ {
$this->_adjustments = $adjustments; $this->_adjustments = $adjustments;
} }
/** /**
* Returns the frame raw data. * Returns the frame raw data.
* *
@@ -174,20 +196,20 @@ final class ID3_Frame_RVA2 extends ID3_Frame
{ {
$data = $this->_device . "\0"; $data = $this->_device . "\0";
foreach ($this->_adjustments as $channel) { foreach ($this->_adjustments as $channel) {
$data .= Transform::toInt8($channel["channelType"]) . $data .= Transform::toInt8($channel[self::channelType]) .
Transform::toInt16BE($channel["volumeAdjustment"]); Transform::toInt16BE($channel[self::volumeAdjustment] * 512);
if ($channel["peakVolume"] < 255) if (abs($channel[self::peakVolume]) <= 0xff)
$data .= Transform::toInt8(8) . $data .= Transform::toInt8(8) .
Transform::toInt8($channel["peakVolume"]); Transform::toUInt8($channel[self::peakVolume]);
else if ($channel["peakVolume"] < 65535) else if (abs($channel[self::peakVolume]) <= 0xffff)
$data .= Transform::toInt8(16) . $data .= Transform::toInt8(16) .
Transform::toUInt16BE($channel["peakVolume"]); Transform::toUInt16BE($channel[self::peakVolume]);
else if ($channel["peakVolume"] < 4294967295) else if (abs($channel[self::peakVolume]) <= 0xffffffff)
$data .= Transform::toInt8(32) . $data .= Transform::toInt8(32) .
Transform::toUInt32BE($channel["peakVolume"]); Transform::toUInt32BE($channel[self::peakVolume]);
else else
$data .= Transform::toInt8(64) . $data .= Transform::toInt8(64) .
Transform::toUInt64BE($channel["peakVolume"]); Transform::toInt64BE($channel[self::peakVolume]); // UInt64
} }
$this->setData($data); $this->setData($data);
return parent::__toString(); return parent::__toString();

View File

@@ -53,6 +53,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -60,6 +61,46 @@ require_once("ID3/Frame.php");
*/ */
final class ID3_Frame_RVAD extends ID3_Frame final class ID3_Frame_RVAD extends ID3_Frame
{ {
/* The required keys. */
/** @var string */
const right = "right";
/** @var string */
const left = "left";
/** @var string */
const peakRight = "peakRight";
/** @var string */
const peakLeft = "peakLeft";
/* The optional keys. */
/** @var string */
const rightBack = "rightBack";
/** @var string */
const leftBack = "leftBack";
/** @var string */
const peakRightBack = "peakRightBack";
/** @var string */
const peakLeftBack = "peakLeftBack";
/** @var string */
const center = "center";
/** @var string */
const peakCenter = "peakCenter";
/** @var string */
const bass = "bass";
/** @var string */
const peakBass = "peakBass";
/** @var Array */ /** @var Array */
private $_adjustments; private $_adjustments;
@@ -77,56 +118,59 @@ final class ID3_Frame_RVAD extends ID3_Frame
return; return;
$flags = Transform::fromInt8($this->_data[0]); $flags = Transform::fromInt8($this->_data[0]);
$descriptionBits = Transform::fromInt8($this->_data[0]); //16 $descriptionBits = Transform::fromInt8($this->_data[1]);
if ($descriptionBits <= 8 || $descriptionBits > 16)
throw new ID3_Exception
("Unsupported description bit size of: " . $descriptionBits);
$this->_adjustments["right"] = $this->_adjustments[self::right] =
($flags & 0x20) == 0x20 ? ($flags & 0x1) == 0x1 ?
Transform::fromUInt16BE(substr($this->_data, 0, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 0, 2));
$this->_adjustments["left"] =
($flags & 0x10) == 0x10 ?
Transform::fromUInt16BE(substr($this->_data, 2, 2)) : Transform::fromUInt16BE(substr($this->_data, 2, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 2, 2)); -Transform::fromUInt16BE(substr($this->_data, 2, 2));
$this->_adjustments["peakRight"] = $this->_adjustments[self::left] =
Transform::fromUInt16BE(substr($this->_data, 4, 2)); ($flags & 0x2) == 0x2 ?
$this->_adjustments["peakLeft"] = Transform::fromUInt16BE(substr($this->_data, 4, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 4, 2));
$this->_adjustments[self::peakRight] =
Transform::fromUInt16BE(substr($this->_data, 6, 2)); Transform::fromUInt16BE(substr($this->_data, 6, 2));
$this->_adjustments[self::peakLeft] =
Transform::fromUInt16BE(substr($this->_data, 8, 2));
if ($this->getSize() <= 8) if ($this->getSize() <= 10)
return; return;
$this->_adjustments["rightBack"] = $this->_adjustments[self::rightBack] =
($flags & 0x8) == 0x8 ?
Transform::fromUInt16BE(substr($this->_data, 8, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 8, 2));
$this->_adjustments["leftBack"] =
($flags & 0x4) == 0x4 ? ($flags & 0x4) == 0x4 ?
Transform::fromUInt16BE(substr($this->_data, 10, 2)) : Transform::fromUInt16BE(substr($this->_data, 10, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 10, 2)); -Transform::fromUInt16BE(substr($this->_data, 10, 2));
$this->_adjustments["peakRightBack"] = $this->_adjustments[self::leftBack] =
Transform::fromUInt16BE(substr($this->_data, 12, 2)); ($flags & 0x8) == 0x8 ?
$this->_adjustments["peakLeftBack"] = Transform::fromUInt16BE(substr($this->_data, 12, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 12, 2));
$this->_adjustments[self::peakRightBack] =
Transform::fromUInt16BE(substr($this->_data, 14, 2)); Transform::fromUInt16BE(substr($this->_data, 14, 2));
$this->_adjustments[self::peakLeftBack] =
Transform::fromUInt16BE(substr($this->_data, 16, 2));
if ($this->getSize() <= 16) if ($this->getSize() <= 18)
return; return;
$this->_adjustments["center"] = $this->_adjustments[self::center] =
($flags & 0x2) == 0x2 ? ($flags & 0x10) == 0x10 ?
Transform::fromUInt16BE(substr($this->_data, 16, 2)) : Transform::fromUInt16BE(substr($this->_data, 18, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 16, 2)); -Transform::fromUInt16BE(substr($this->_data, 18, 2));
$this->_adjustments["peakCenter"] = $this->_adjustments[self::peakCenter] =
Transform::fromUInt16BE(substr($this->_data, 18, 2)); Transform::fromUInt16BE(substr($this->_data, 20, 2));
if ($this->getSize() <= 20) if ($this->getSize() <= 22)
return; return;
$this->_adjustments["bass"] = $this->_adjustments[self::bass] =
($flags & 0x1) == 0x1 ? ($flags & 0x20) == 0x20 ?
Transform::fromUInt16BE(substr($this->_data, 20, 2)) : Transform::fromUInt16BE(substr($this->_data, 22, 2)) :
-Transform::fromUInt16BE(substr($this->_data, 20, 2)); -Transform::fromUInt16BE(substr($this->_data, 22, 2));
$this->_adjustments["peakBass"] = $this->_adjustments[self::peakBass] =
Transform::fromUInt16BE(substr($this->_data, 22, 2)); Transform::fromUInt16BE(substr($this->_data, 24, 2));
} }
/** /**
@@ -160,47 +204,47 @@ final class ID3_Frame_RVAD extends ID3_Frame
public function __toString() public function __toString()
{ {
$flags = 0; $flags = 0;
if ($this->_adjustments["right"] > 0) if ($this->_adjustments[self::right] > 0)
$flags = $flags | 0x20; $flags = $flags | 0x1;
if ($this->_adjustments["left"] > 0) if ($this->_adjustments[self::left] > 0)
$flags = $flags | 0x10; $flags = $flags | 0x2;
$data = Transform::toInt8(16) . $data = Transform::toInt8(16) .
Transform::toUInt16BE(abs($this->_adjustments["right"])) . Transform::toUInt16BE(abs($this->_adjustments[self::right])) .
Transform::toUInt16BE(abs($this->_adjustments["left"])) . Transform::toUInt16BE(abs($this->_adjustments[self::left])) .
Transform::toUInt16BE(abs($this->_adjustments["peakRight"])) . Transform::toUInt16BE(abs($this->_adjustments[self::peakRight])) .
Transform::toUInt16BE(abs($this->_adjustments["peakLeft"])); Transform::toUInt16BE(abs($this->_adjustments[self::peakLeft]));
if (isset($this->_adjustments["rightBack"]) && if (isset($this->_adjustments[self::rightBack]) &&
isset($this->_adjustments["leftBack"]) && isset($this->_adjustments[self::leftBack]) &&
isset($this->_adjustments["peakRightBack"]) && isset($this->_adjustments[self::peakRightBack]) &&
isset($this->_adjustments["peakLeftBack"])) { isset($this->_adjustments[self::peakLeftBack])) {
if ($this->_adjustments["rightBack"] > 0) if ($this->_adjustments[self::rightBack] > 0)
$flags = $flags | 0x8;
if ($this->_adjustments["leftBack"] > 0)
$flags = $flags | 0x4; $flags = $flags | 0x4;
if ($this->_adjustments[self::leftBack] > 0)
$flags = $flags | 0x8;
$data .= $data .=
Transform::toUInt16BE(abs($this->_adjustments["rightBack"])) . Transform::toUInt16BE(abs($this->_adjustments[self::rightBack])) .
Transform::toUInt16BE(abs($this->_adjustments["leftBack"])) . Transform::toUInt16BE(abs($this->_adjustments[self::leftBack])) .
Transform::toUInt16BE(abs($this->_adjustments["peakRightBack"])) . Transform::toUInt16BE(abs($this->_adjustments[self::peakRightBack])) .
Transform::toUInt16BE(abs($this->_adjustments["peakLeftBack"])); Transform::toUInt16BE(abs($this->_adjustments[self::peakLeftBack]));
} }
if (isset($this->_adjustments["center"]) && if (isset($this->_adjustments[self::center]) &&
isset($this->_adjustments["peakCenter"])) { isset($this->_adjustments[self::peakCenter])) {
if ($this->_adjustments["center"] > 0) if ($this->_adjustments[self::center] > 0)
$flags = $flags | 0x2; $flags = $flags | 0x10;
$data .= $data .=
Transform::toUInt16BE(abs($this->_adjustments["center"])) . Transform::toUInt16BE(abs($this->_adjustments[self::center])) .
Transform::toUInt16BE(abs($this->_adjustments["peakCenter"])); Transform::toUInt16BE(abs($this->_adjustments[self::peakCenter]));
} }
if (isset($this->_adjustments["bass"]) && if (isset($this->_adjustments[self::bass]) &&
isset($this->_adjustments["peakBass"])) { isset($this->_adjustments[self::peakBass])) {
if ($this->_adjustments["bass"] > 0) if ($this->_adjustments[self::bass] > 0)
$flags = $flags | 0x1; $flags = $flags | 0x20;
$data .= $data .=
Transform::toUInt16BE(abs($this->_adjustments["bass"])) . Transform::toUInt16BE(abs($this->_adjustments[self::bass])) .
Transform::toUInt16BE(abs($this->_adjustments["peakBass"])); Transform::toUInt16BE(abs($this->_adjustments[self::peakBass]));
} }
$this->setData(Transform::toInt8($flags) . $data); $this->setData(Transform::toInt8($flags) . $data);
return parent::__toString(); return parent::__toString();

View File

@@ -59,6 +59,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -108,16 +109,16 @@ final class ID3_Frame_RVRB extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_reverbLeft = Transform::fromInt16BE(substr($this->_data, 0, 2)); $this->_reverbLeft = Transform::fromUInt16BE(substr($this->_data, 0, 2));
$this->_reverbRight = Transform::fromInt16BE(substr($this->_data, 2, 2)); $this->_reverbRight = Transform::fromUInt16BE(substr($this->_data, 2, 2));
$this->_reverbBouncesLeft = Transform::fromInt8($this->_data[4]); $this->_reverbBouncesLeft = Transform::fromUInt8($this->_data[4]);
$this->_reverbBouncesRight = Transform::fromInt8($this->_data[5]); $this->_reverbBouncesRight = Transform::fromUInt8($this->_data[5]);
$this->_reverbFeedbackLtoL = Transform::fromInt8($this->_data[6]); $this->_reverbFeedbackLtoL = Transform::fromUInt8($this->_data[6]);
$this->_reverbFeedbackLtoR = Transform::fromInt8($this->_data[7]); $this->_reverbFeedbackLtoR = Transform::fromUInt8($this->_data[7]);
$this->_reverbFeedbackRtoR = Transform::fromInt8($this->_data[8]); $this->_reverbFeedbackRtoR = Transform::fromUInt8($this->_data[8]);
$this->_reverbFeedbackRtoL = Transform::fromInt8($this->_data[9]); $this->_reverbFeedbackRtoL = Transform::fromUInt8($this->_data[9]);
$this->_premixLtoR = Transform::fromInt8($this->_data[10]); $this->_premixLtoR = Transform::fromUInt8($this->_data[10]);
$this->_premixRtoL = Transform::fromInt8($this->_data[11]); $this->_premixRtoL = Transform::fromUInt8($this->_data[11]);
} }
/** /**
@@ -298,16 +299,16 @@ final class ID3_Frame_RVRB extends ID3_Frame
public function __toString() public function __toString()
{ {
$this->setData $this->setData
(Transform::toInt16BE($this->_reverbLeft) . (Transform::toUInt16BE($this->_reverbLeft) .
Transform::toInt16BE($this->_reverbRight) . Transform::toUInt16BE($this->_reverbRight) .
Transform::toInt8($this->_reverbBouncesLeft) . Transform::toUInt8($this->_reverbBouncesLeft) .
Transform::toInt8($this->_reverbBouncesRight) . Transform::toUInt8($this->_reverbBouncesRight) .
Transform::toInt8($this->_reverbFeedbackLtoL) . Transform::toUInt8($this->_reverbFeedbackLtoL) .
Transform::toInt8($this->_reverbFeedbackLtoR) . Transform::toUInt8($this->_reverbFeedbackLtoR) .
Transform::toInt8($this->_reverbFeedbackRtoR) . Transform::toUInt8($this->_reverbFeedbackRtoR) .
Transform::toInt8($this->_reverbFeedbackRtoL) . Transform::toUInt8($this->_reverbFeedbackRtoL) .
Transform::toInt8($this->_premixLtoR) . Transform::toUInt8($this->_premixLtoR) .
Transform::toInt8($this->_premixRtoL)); Transform::toUInt8($this->_premixRtoL));
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -50,6 +50,7 @@ require_once("ID3/Frame.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -76,7 +77,7 @@ final class ID3_Frame_SIGN extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_group = substr($this->_data, 0, 1); $this->_group = Transform::fromUInt8(substr($this->_data, 0, 1));
$this->_signature = substr($this->_data, 1); $this->_signature = substr($this->_data, 1);
} }
@@ -115,7 +116,7 @@ final class ID3_Frame_SIGN extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$this->setData(Transform::toInt8($this->_group) . $this->_signature); $this->setData(Transform::toUInt8($this->_group) . $this->_signature);
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -51,10 +51,10 @@ require_once("ID3/Timing.php");
* There may be more than one SYLT frame in each tag, but only one with the * There may be more than one SYLT frame in each tag, but only one with the
* same language and content descriptor. * same language and content descriptor.
* *
* @todo The data could be parsed further; data samples needed
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -68,17 +68,17 @@ final class ID3_Frame_SYLT extends ID3_Frame
* @var Array * @var Array
*/ */
public static $types = array public static $types = array
("Other", "Lyrics", "Text transcription", "Movement/Part name", "Eevents", ("Other", "Lyrics", "Text transcription", "Movement/Part name", "Events",
"Chord", "Trivia", "URLs to webpages", "URLs to images"); "Chord", "Trivia", "URLs to webpages", "URLs to images");
/** @var integer */ /** @var integer */
private $_encoding = ID3_Encoding::UTF8; private $_encoding = ID3_Encoding::UTF8;
/** @var string */ /** @var string */
private $_language = "eng"; private $_language = "und";
/** @var integer */ /** @var integer */
private $_format = 1; private $_format = ID3_Timing::MPEG_FRAMES;
/** @var integer */ /** @var integer */
private $_type = 0; private $_type = 0;
@@ -87,7 +87,7 @@ final class ID3_Frame_SYLT extends ID3_Frame
private $_description; private $_description;
/** @var Array */ /** @var Array */
private $_text; private $_events = array();
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
@@ -102,30 +102,53 @@ final class ID3_Frame_SYLT extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_language = substr($this->_data, 1, 3); $this->_language = substr($this->_data, 1, 3);
$this->_format = Transform::fromInt8($this->_data[3]); if ($this->_language == "XXX")
$this->_type = Transform::fromInt8($this->_data[4]); $this->_language = "und";
$this->_data = substr($this->_data, 5); $this->_format = Transform::fromUInt8($this->_data[4]);
$this->_type = Transform::fromUInt8($this->_data[5]);
$this->_data = substr($this->_data, 6);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list($this->_description, $this->_data) = list($this->_description, $this->_data) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
break; break;
case self::UTF16BE: case self::UTF16BE:
list($this->_description, $this->_data) = list($this->_description, $this->_data) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
break; break;
default: default:
list($this->_description, $this->_data) = list($this->_description, $this->_data) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
$this->_description = Transform::fromString8($this->_description); $this->_description = Transform::fromString8($this->_description);
} }
$this->_text = $this->_data; // FIXME: Better parsing of data while (strlen($this->_data) > 0) {
switch ($this->_encoding) {
case self::UTF16:
list($syllable, $this->_data) =
$this->explodeString16($this->_data, 2);
$syllable = Transform::fromString16($syllable);
break;
case self::UTF16BE:
list($syllable, $this->_data) =
$this->explodeString16($this->_data, 2);
$syllable = Transform::fromString16BE($syllable);
break;
default:
list($syllable, $this->_data) =
$this->explodeString8($this->_data, 2);
$syllable = Transform::fromString8($syllable);
}
$this->_events[Transform::fromUInt32BE(substr($this->_data, 0, 4))] =
$syllable;
$this->_data = substr($this->_data, 4);
}
ksort($this->_events);
} }
/** /**
@@ -147,7 +170,6 @@ final class ID3_Frame_SYLT extends ID3_Frame
* Returns the language code as specified in the * Returns the language code as specified in the
* {@link http://www.loc.gov/standards/iso639-2/ ISO-639-2} standard. * {@link http://www.loc.gov/standards/iso639-2/ ISO-639-2} standard.
* *
* @see ID3_Language#ISO_639_2
* @return string * @return string
*/ */
public function getLanguage() { return $this->_language; } public function getLanguage() { return $this->_language; }
@@ -159,7 +181,12 @@ final class ID3_Frame_SYLT extends ID3_Frame
* @see ID3_Language * @see ID3_Language
* @param string $language The language code. * @param string $language The language code.
*/ */
public function setLanguage($language) { $this->_language = $language; } public function setLanguage($language)
{
if ($language == "XXX")
$language = "und";
$this->_language = substr($language, 0, 3);
}
/** /**
* Returns the timing format. * Returns the timing format.
@@ -210,33 +237,34 @@ final class ID3_Frame_SYLT extends ID3_Frame
{ {
$this->_description = $description; $this->_description = $description;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
* Returns the texts with their timestamps. * Returns the syllable events with their timestamps.
* *
* @return Array * @return Array
*/ */
public function getText() { return $this->_text; } public function getEvents() { return $this->_events; }
/** /**
* Sets the text using given encoding. The text language and encoding must be * Sets the syllable events with their timestamps using given encoding.
* that of the description text. * The text language and encoding must be that of the description text.
* *
* @param mixed $text The test string. * @param Array $text The test string.
* @param string $language The language code. * @param string $language The language code.
* @param integer $encoding The text encoding. * @param integer $encoding The text encoding.
*/ */
public function setText($text, $language = false, $encoding = false) public function setEvents($events, $language = false, $encoding = false)
{ {
$this->_text = $text; $this->_events = $events;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
ksort($this->_events);
} }
/** /**
@@ -246,23 +274,38 @@ final class ID3_Frame_SYLT extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_language . $data = Transform::toUInt8($this->_encoding) . $this->_language .
Transform::toInt8($this->_format) . Transform::toInt8($this->_type); Transform::toUInt8($this->_format) . Transform::toUInt8($this->_type);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_text); $data .= Transform::toString16
($this->_description, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) .
"\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0" . $data .= Transform::toString16BE($this->_description) . "\0\0";
Transform::toString16BE($this->_text);
break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0" .
Transform::toString16LE($this->_text);
break; break;
default: default:
$data .= $this->_description . "\0" . $this->_text; $data .= $this->_description . "\0";
}
foreach ($this->_events as $timestamp => $syllable) {
switch ($this->_encoding) {
case self::UTF16:
case self::UTF16LE:
$data .= Transform::toString16
($syllable, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) .
"\0\0";
break;
case self::UTF16BE:
$data .= Transform::toString16BE($syllable) . "\0\0";
break;
default:
$data .= $syllable . "\0";
}
$data .= Transform::toUInt32BE($timestamp);
} }
$this->setData($data); $this->setData($data);
return parent::__toString(); return parent::__toString();

View File

@@ -62,6 +62,7 @@ require_once("ID3/Timing.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -69,11 +70,17 @@ require_once("ID3/Timing.php");
final class ID3_Frame_SYTC extends ID3_Frame final class ID3_Frame_SYTC extends ID3_Frame
implements ID3_Timing implements ID3_Timing
{ {
/** @var integer */ /** Describes a beat-free time period. */
private $_format = 1; const BEAT_FREE = 0x00;
/** @var string */ /** Indicate one single beat-stroke followed by a beat-free period. */
private $_tempoData; const SINGLE_BEAT = 0x01;
/** @var integer */
private $_format = ID3_Timing::MPEG_FRAMES;
/** @var Array */
private $_events = array();
/** /**
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
@@ -88,8 +95,17 @@ final class ID3_Frame_SYTC extends ID3_Frame
if ($reader === null) if ($reader === null)
return; return;
$this->_format = Transform::fromInt8($this->_data[0]); $offset = 0;
$this->_tempoData = substr($this->_data, 1); // FIXME: Better parsing of data $this->_format = Transform::fromUInt8($this->_data[$offset++]);
while ($offset < strlen($this->_data)) {
$tempo = Transform::fromUInt8($this->_data[$offset++]);
if ($tempo == 0xFF)
$tempo += Transform::fromUInt8($this->_data[$offset++]);
$this->_events
[Transform::fromUInt32BE(substr($this->_data, $offset, 4))] = $tempo;
$offset += 4;
}
ksort($this->_events);
} }
/** /**
@@ -108,18 +124,22 @@ final class ID3_Frame_SYTC extends ID3_Frame
public function setFormat($format) { $this->_format = $format; } public function setFormat($format) { $this->_format = $format; }
/** /**
* Returns the tempo data. * Returns the time-bpm tempo events.
* *
* @return string * @return Array
*/ */
public function getData() { return $this->_tempoData; } public function getEvents() { return $this->_events; }
/** /**
* Sets the tempo data. * Sets the time-bpm tempo events.
* *
* @param string $data The data string. * @param Array $events The time-bpm tempo events.
*/ */
public function setData($tempoData) { $this->_tempoData = $tempoData; } public function setEvents($events)
{
$this->_events = $events;
ksort($this->_events);
}
/** /**
* Returns the frame raw data. * Returns the frame raw data.
@@ -128,7 +148,15 @@ final class ID3_Frame_SYTC extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
parent::setData(Transform::toInt8($this->_format) . $this->_tempoData); $data = Transform::toUInt8($this->_format);
foreach ($this->_events as $timestamp => $tempo) {
if ($tempo >= 0xff)
$data .= Transform::toUInt8(0xff) . Transform::toUInt8($tempo - 0xff);
else
$data .= Transform::toUInt8($tempo);
$data .= Transform::toUInt32BE($timestamp);
}
parent::setData($data);
return parent::__toString(); return parent::__toString();
} }
} }

View File

@@ -52,6 +52,7 @@ require_once("ID3/Frame/AbstractText.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -69,24 +70,30 @@ final class ID3_Frame_TXXX extends ID3_Frame_AbstractText
*/ */
public function __construct($reader = null, &$options = array()) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader, $options); ID3_Frame::__construct($reader, $options);
if ($reader === null)
return;
$this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_data = substr($this->_data, 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list($this->_description, $this->_text) = list($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
$this->_text = array(Transform::fromString16($this->_text)); $this->_text = array(Transform::fromString16($this->_text));
break; break;
case self::UTF16BE: case self::UTF16BE:
list($this->_description, $this->_text) = list($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
$this->_text = array(Transform::fromString16BE($this->_text)); $this->_text = array(Transform::fromString16BE($this->_text));
break; break;
default: default:
list($this->_description, $this->_text) = list($this->_description, $this->_text) =
preg_split("/\\x00/", $this->_data); $this->explodeString8($this->_data, 2);
$this->_text = array($this->_text); $this->_text = array($this->_text);
} }
} }
@@ -118,25 +125,24 @@ final class ID3_Frame_TXXX extends ID3_Frame_AbstractText
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding); $data = Transform::toUInt8($this->_encoding);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_text[0]); $order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
$data .= Transform::toString16($this->_description, $order) . "\0\0" .
Transform::toString16($this->_text[0], $order);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0" . $data .= Transform::toString16BE($this->_description) . "\0\0" .
Transform::toString16BE($this->_text[0]); Transform::toString16BE($this->_text[0]);
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0" .
Transform::toString16LE($this->_text[0]);
break;
default: default:
$data .= $this->_description . "\0" . $this->_text[0]; $data .= $this->_description . "\0" . $this->_text[0];
} }
$this->setData($data); $this->setData($data);
return parent::__toString(); return ID3_Frame::__toString();
} }
} }

View File

@@ -51,6 +51,7 @@ require_once("ID3/Language.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -62,7 +63,7 @@ final class ID3_Frame_USER extends ID3_Frame
private $_encoding = ID3_Encoding::UTF8; private $_encoding = ID3_Encoding::UTF8;
/** @var string */ /** @var string */
private $_language = "eng"; private $_language = "und";
/** @var string */ /** @var string */
private $_text; private $_text;
@@ -71,16 +72,19 @@ final class ID3_Frame_USER extends ID3_Frame
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
* @param Reader $reader The reader object. * @param Reader $reader The reader object.
* @param Array $options The options array.
*/ */
public function __construct($reader = null) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader); parent::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_language = substr($this->_data, 1, 3); $this->_language = substr($this->_data, 1, 3);
if ($this->_language == "XXX")
$this->_language = "und";
$this->_data = substr($this->_data, 4); $this->_data = substr($this->_data, 4);
switch ($this->_encoding) { switch ($this->_encoding) {
@@ -125,7 +129,12 @@ final class ID3_Frame_USER extends ID3_Frame
* @see ID3_Language * @see ID3_Language
* @param string $language The language code. * @param string $language The language code.
*/ */
public function setLanguage($language) { $this->_language = $language; } public function setLanguage($language)
{
if ($language == "XXX")
$language = "und";
$this->_language = substr($language, 0, 3);
}
/** /**
* Returns the text. * Returns the text.
@@ -143,11 +152,11 @@ final class ID3_Frame_USER extends ID3_Frame
*/ */
public function setText($text, $language = false, $encoding = false) public function setText($text, $language = false, $encoding = false)
{ {
$this->_text = $text; $this->_text = $text;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
@@ -157,17 +166,17 @@ final class ID3_Frame_USER extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_language; $data = Transform::toUInt8($this->_encoding) . $this->_language;
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_text); case self::UTF16LE:
$data .= Transform::toString16
($this->_text, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_text); $data .= Transform::toString16BE($this->_text);
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_text);
break;
default: default:
$data .= $this->_text; $data .= $this->_text;
} }

View File

@@ -50,6 +50,7 @@ require_once("ID3/Language.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -61,7 +62,7 @@ final class ID3_Frame_USLT extends ID3_Frame
private $_encoding = ID3_Encoding::UTF8; private $_encoding = ID3_Encoding::UTF8;
/** @var string */ /** @var string */
private $_language = "eng"; private $_language = "und";
/** @var string */ /** @var string */
private $_description; private $_description;
@@ -73,34 +74,37 @@ final class ID3_Frame_USLT extends ID3_Frame
* Constructs the class with given parameters and parses object related data. * Constructs the class with given parameters and parses object related data.
* *
* @param Reader $reader The reader object. * @param Reader $reader The reader object.
* @param Array $options The options array.
*/ */
public function __construct($reader = null) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader); parent::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_language = substr($this->_data, 1, 3); $this->_language = substr($this->_data, 1, 3);
if ($this->_language == "XXX")
$this->_language = "und";
$this->_data = substr($this->_data, 4); $this->_data = substr($this->_data, 4);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
$this->_text = Transform::fromString16($this->_text); $this->_text = Transform::fromString16($this->_text);
break; break;
case self::UTF16BE: case self::UTF16BE:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
$this->_text = Transform::fromString16BE($this->_text); $this->_text = Transform::fromString16BE($this->_text);
break; break;
default: default:
list ($this->_description, $this->_text) = list ($this->_description, $this->_text) =
preg_split("/\\x00/", $this->_data, 2); $this->explodeString8($this->_data, 2);
$this->_description = Transform::fromString8($this->_description); $this->_description = Transform::fromString8($this->_description);
$this->_text = Transform::fromString8($this->_text); $this->_text = Transform::fromString8($this->_text);
} }
@@ -136,7 +140,12 @@ final class ID3_Frame_USLT extends ID3_Frame
* @see ID3_Language * @see ID3_Language
* @param string $language The language code. * @param string $language The language code.
*/ */
public function setLanguage($language) { $this->_language = $language; } public function setLanguage($language)
{
if ($language == "XXX")
$language = "und";
$this->_language = substr($language, 0, 3);
}
/** /**
* Returns the short content description. * Returns the short content description.
@@ -158,9 +167,9 @@ final class ID3_Frame_USLT extends ID3_Frame
{ {
$this->_description = $description; $this->_description = $description;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
@@ -182,9 +191,9 @@ final class ID3_Frame_USLT extends ID3_Frame
{ {
$this->_text = $text; $this->_text = $text;
if ($language !== false) if ($language !== false)
$this->_language = $language; $this->setLanguage($language);
if ($encoding !== false) if ($encoding !== false)
$this->_encoding = $encoding; $this->setEncoding($encoding);
} }
/** /**
@@ -194,20 +203,19 @@ final class ID3_Frame_USLT extends ID3_Frame
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding) . $this->_language; $data = Transform::toUInt8($this->_encoding) . $this->_language;
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0" . case self::UTF16LE:
Transform::toString16($this->_text); $order = $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER;
$data .= Transform::toString16($this->_description, $order) . "\0\0" .
Transform::toString16($this->_text, $order);
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0" . $data .= Transform::toString16BE($this->_description) . "\0\0" .
Transform::toString16BE($this->_text); Transform::toString16BE($this->_text);
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0" .
Transform::toString16LE($this->_text);
break;
default: default:
$data .= $this->_description . "\0" . $this->_text; $data .= $this->_description . "\0" . $this->_text;
} }

View File

@@ -50,6 +50,7 @@ require_once("ID3/Encoding.php");
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -71,30 +72,31 @@ final class ID3_Frame_WXXX extends ID3_Frame_AbstractLink
*/ */
public function __construct($reader = null, &$options = array()) public function __construct($reader = null, &$options = array())
{ {
parent::__construct($reader, $options); ID3_Frame::__construct($reader, $options);
if ($reader === null) if ($reader === null)
return; return;
$this->_encoding = Transform::fromInt8($this->_data[0]); $this->_encoding = Transform::fromUInt8($this->_data[0]);
$this->_data = substr($this->_data, 1); $this->_data = substr($this->_data, 1);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
list($this->_description, $this->_link) = list($this->_description, $this->_link) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16($this->_description); $this->_description = Transform::fromString16($this->_description);
break; break;
case self::UTF16BE: case self::UTF16BE:
list($this->_description, $this->_link) = list($this->_description, $this->_link) =
preg_split("/\\x00\\x00/", $this->_data, 2); $this->explodeString16($this->_data, 2);
$this->_description = Transform::fromString16BE($this->_description); $this->_description = Transform::fromString16BE($this->_description);
break; break;
default: default:
list($this->_description, $this->_link) = list($this->_description, $this->_link) =
preg_split("/\\x00/", $this->_data); $this->explodeString8($this->_data, 2);
break; break;
} }
$this->_link = implode($this->explodeString8($this->_link, 1), "");
} }
/** /**
@@ -139,21 +141,22 @@ final class ID3_Frame_WXXX extends ID3_Frame_AbstractLink
*/ */
public function __toString() public function __toString()
{ {
$data = Transform::toInt8($this->_encoding); $data = Transform::toUInt8($this->_encoding);
switch ($this->_encoding) { switch ($this->_encoding) {
case self::UTF16: case self::UTF16:
$data .= Transform::toString16($this->_description) . "\0\0"; case self::UTF16LE:
$data .= Transform::toString16
($this->_description, $this->_encoding == self::UTF16 ?
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) .
"\0\0";
break; break;
case self::UTF16BE: case self::UTF16BE:
$data .= Transform::toString16BE($this->_description) . "\0\0"; $data .= Transform::toString16BE($this->_description) . "\0\0";
break; break;
case self::UTF16LE:
$data .= Transform::toString16LE($this->_description) . "\0\0");
break;
default: default:
$data .= $this->_description . "\0"; $data .= $this->_description . "\0";
} }
$this->setData($data . $this->_link); $this->setData($data . $this->_link);
return parent::__toString(); return ID3_Frame::__toString();
} }
} }

View File

@@ -41,6 +41,7 @@
* @package php-reader * @package php-reader
* @subpackage ID3 * @subpackage ID3
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -151,12 +152,8 @@ abstract class ID3_Object
*/ */
protected function encodeSynchsafe32($val) protected function encodeSynchsafe32($val)
{ {
if (!isset($this->_options["version"]) || $this->_options["version"] >= 4) { return ($val & 0x7f) | ($val & 0x3f80) << 1 |
for ($i = 0, $mask = 0xffffff00; $i < 4; $i++, $mask <<= 8) ($val & 0x1fc000) << 2 | ($val & 0xfe00000) << 3;
$val = ($val << 1 & $mask) | ($val << 1 & ~$mask) >> 1;
return $val & 0x7fffffff;
}
return $val;
} }
/** /**
@@ -167,9 +164,46 @@ abstract class ID3_Object
*/ */
protected function decodeSynchsafe32($val) protected function decodeSynchsafe32($val)
{ {
if (!isset($this->_options["version"]) || $this->_options["version"] >= 4) return ($val & 0x7f) | ($val & 0x7f00) >> 1 |
for ($i = 0, $mask = 0xff000000; $i < 3; $i++, $mask >>= 8) ($val & 0x7f0000) >> 2 | ($val & 0x7f000000) >> 3;
$val = ($val & $mask) >> 1 | ($val & ~$mask); }
return $val;
/**
* Splits UTF-16 formatted binary data up according to null terminators
* residing in the string, up to a given limit.
*
* @param string $value The input string.
* @return Array
*/
protected function explodeString16($value, $limit = null)
{
$i = 0;
$array = array();
while (count($array) < $limit - 1 || $limit === null) {
$start = $i;
do {
$i = strpos($value, "\x00\x00", $i);
if ($i === false) {
$array[] = substr($value, $start);
return $array;
}
} while ($i & 0x1 != 0 && $i++); // make sure its aligned
$array[] = substr($value, $start, $i - $start);
$i += 2;
}
$array[] = substr($value, $i);
return $array;
}
/**
* Splits UTF-8 or ISO-8859-1 formatted binary data according to null
* terminators residing in the string, up to a given limit.
*
* @param string $value The input string.
* @return Array
*/
protected function explodeString8($value, $limit = null)
{
return preg_split("/\\x00/", $value, $limit);
} }
} }

View File

@@ -4,7 +4,7 @@
* *
* Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights
* reserved. * reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
@@ -37,9 +37,10 @@
/** /**
* An utility class to perform simple byte transformations on data. * An utility class to perform simple byte transformations on data.
* *
* @package php-reader * @package php-reader
* @author Sven Vollbehr <svollbehr@gmail.com> * @author Sven Vollbehr <svollbehr@gmail.com>
* @author Ryan Butterfield <buttza@gmail.com>
* @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup
* @license http://code.google.com/p/php-reader/wiki/License New BSD License * @license http://code.google.com/p/php-reader/wiki/License New BSD License
* @version $Rev$ * @version $Rev$
@@ -50,12 +51,32 @@ final class Transform
const MACHINE_ENDIAN_ORDER = 0; const MACHINE_ENDIAN_ORDER = 0;
const LITTLE_ENDIAN_ORDER = 1; const LITTLE_ENDIAN_ORDER = 1;
const BIG_ENDIAN_ORDER = 2; const BIG_ENDIAN_ORDER = 2;
/** /**
* Default private constructor for a static class. * Default private constructor for a static class.
*/ */
private function __construct() {} private function __construct() {}
/**
* Returns whether the current machine endian order is little endian.
*
* @return boolean
*/
public static function isLittleEndian()
{
return self::fromInt32("\x01\x00\x00\x00") == 1;
}
/**
* Returns whether the current machine endian order is big endian.
*
* @return boolean
*/
public static function isBigEndian()
{
return self::fromInt32("\x00\x00\x00\x01") == 1;
}
/** /**
* Returns 64-bit float as little-endian ordered binary data string. * Returns 64-bit float as little-endian ordered binary data string.
* *
@@ -66,7 +87,7 @@ final class Transform
{ {
return pack("V*", $value & 0xffffffff, $value / (0xffffffff+1)); return pack("V*", $value & 0xffffffff, $value / (0xffffffff+1));
} }
/** /**
* Returns little-endian ordered binary data as 64-bit float. PHP does not * Returns little-endian ordered binary data as 64-bit float. PHP does not
* support 64-bit integers as the long integer is of 32-bits but using * support 64-bit integers as the long integer is of 32-bits but using
@@ -82,7 +103,7 @@ final class Transform
return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) + return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) +
($lohi * (0xffff+1) + $lolo); ($lohi * (0xffff+1) + $lolo);
} }
/** /**
* Returns 64-bit float as big-endian ordered binary data string. * Returns 64-bit float as big-endian ordered binary data string.
* *
@@ -93,7 +114,7 @@ final class Transform
{ {
return pack("N*", $value / (0xffffffff+1), $value & 0xffffffff); return pack("N*", $value / (0xffffffff+1), $value & 0xffffffff);
} }
/** /**
* Returns big-endian ordered binary data as 64-bit float. PHP does not * Returns big-endian ordered binary data as 64-bit float. PHP does not
* support 64-bit integers as the long integer is of 32-bits but using * support 64-bit integers as the long integer is of 32-bits but using
@@ -109,7 +130,7 @@ final class Transform
return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) + return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) +
($lohi * (0xffff+1) + $lolo); ($lohi * (0xffff+1) + $lolo);
} }
/** /**
* Returns signed 32-bit integer as machine-endian ordered binary data. * Returns signed 32-bit integer as machine-endian ordered binary data.
* *
@@ -120,10 +141,10 @@ final class Transform
{ {
return pack("l*", $value); return pack("l*", $value);
} }
/** /**
* Returns machine-endian ordered binary data as signed 32-bit integer. * Returns machine-endian ordered binary data as signed 32-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
@@ -132,7 +153,7 @@ final class Transform
list(, $int) = unpack("l*", $value); list(, $int) = unpack("l*", $value);
return $int; return $int;
} }
/** /**
* Returns signed 32-bit integer as little-endian ordered binary data. * Returns signed 32-bit integer as little-endian ordered binary data.
* *
@@ -141,26 +162,26 @@ final class Transform
*/ */
public static function toInt32LE($value) public static function toInt32LE($value)
{ {
if (self::fromInt32("\x00\x00\x00\x01") == 1) if (self::isBigEndian())
return strrev(self::toInt32($value)); return strrev(self::toInt32($value));
else else
return self::toInt32($value); return self::toInt32($value);
} }
/** /**
* Returns little-endian ordered binary data as signed 32-bit integer. * Returns little-endian ordered binary data as signed 32-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
public static function fromInt32LE($value) public static function fromInt32LE($value)
{ {
if (self::fromInt32("\x00\x00\x00\x01") == 1) if (self::isBigEndian())
return self::fromInt32(strrev($value)); return self::fromInt32(strrev($value));
else else
return self::fromInt32($value); return self::fromInt32($value);
} }
/** /**
* Returns signed 32-bit integer as big-endian ordered binary data. * Returns signed 32-bit integer as big-endian ordered binary data.
* *
@@ -169,26 +190,26 @@ final class Transform
*/ */
public static function toInt32BE($value) public static function toInt32BE($value)
{ {
if (self::fromInt32("\x00\x00\x00\x01") == 1) if (self::isBigEndian())
return self::toInt32($value); return self::toInt32($value);
else else
return strrev(self::toInt32($value)); return strrev(self::toInt32($value));
} }
/** /**
* Returns big-endian ordered binary data as signed 32-bit integer. * Returns big-endian ordered binary data as signed 32-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
public static function fromInt32BE($value) public static function fromInt32BE($value)
{ {
if (self::fromInt32("\x00\x00\x00\x01") == 1) if (self::isBigEndian())
return self::fromInt32($value); return self::fromInt32($value);
else else
return self::fromInt32(strrev($value)); return self::fromInt32(strrev($value));
} }
/** /**
* Returns unsigned 32-bit integer as little-endian ordered binary data. * Returns unsigned 32-bit integer as little-endian ordered binary data.
* *
@@ -199,7 +220,7 @@ final class Transform
{ {
return pack("V*", $value); return pack("V*", $value);
} }
/** /**
* Returns little-endian ordered binary data as unsigned 32-bit integer. * Returns little-endian ordered binary data as unsigned 32-bit integer.
* *
@@ -208,10 +229,15 @@ final class Transform
*/ */
public static function fromUInt32LE($value) public static function fromUInt32LE($value)
{ {
list(, $lo, $hi) = unpack("v*", $value); if (PHP_INT_SIZE < 8) {
return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo list(, $lo, $hi) = unpack("v*", $value);
return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo
} else {
list(, $int) = unpack("V*", $value);
return $int;
}
} }
/** /**
* Returns unsigned 32-bit integer as big-endian ordered binary data. * Returns unsigned 32-bit integer as big-endian ordered binary data.
* *
@@ -222,7 +248,7 @@ final class Transform
{ {
return pack("N*", $value); return pack("N*", $value);
} }
/** /**
* Returns big-endian ordered binary data as unsigned 32-bit integer. * Returns big-endian ordered binary data as unsigned 32-bit integer.
* *
@@ -231,10 +257,15 @@ final class Transform
*/ */
public static function fromUInt32BE($value) public static function fromUInt32BE($value)
{ {
list(, $hi, $lo) = unpack("n*", $value); if (PHP_INT_SIZE < 8) {
return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo list(, $hi, $lo) = unpack("n*", $value);
return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo
} else {
list(, $int) = unpack("N*", $value);
return $int;
}
} }
/** /**
* Returns signed 16-bit integer as machine endian ordered binary data. * Returns signed 16-bit integer as machine endian ordered binary data.
* *
@@ -245,7 +276,7 @@ final class Transform
{ {
return pack("s*", $value); return pack("s*", $value);
} }
/** /**
* Returns machine endian ordered binary data as signed 16-bit integer. * Returns machine endian ordered binary data as signed 16-bit integer.
* *
@@ -257,7 +288,7 @@ final class Transform
list(, $int) = unpack("s*", $value); list(, $int) = unpack("s*", $value);
return $int; return $int;
} }
/** /**
* Returns signed 16-bit integer as little-endian ordered binary data. * Returns signed 16-bit integer as little-endian ordered binary data.
* *
@@ -266,12 +297,12 @@ final class Transform
*/ */
public static function toInt16LE($value) public static function toInt16LE($value)
{ {
if (self::fromInt16("\x00\x01") == 1) if (self::isBigEndian())
return strrev(self::toInt16($value)); return strrev(self::toInt16($value));
else else
return self::toInt16($value); return self::toInt16($value);
} }
/** /**
* Returns little-endian ordered binary data as signed 16-bit integer. * Returns little-endian ordered binary data as signed 16-bit integer.
* *
@@ -280,12 +311,12 @@ final class Transform
*/ */
public static function fromInt16LE($value) public static function fromInt16LE($value)
{ {
if (self::fromInt16("\x00\x01") == 1) if (self::isBigEndian())
return self::fromInt16(strrev($value)); return self::fromInt16(strrev($value));
else else
return self::fromInt16($value); return self::fromInt16($value);
} }
/** /**
* Returns signed 16-bit integer as big-endian ordered binary data. * Returns signed 16-bit integer as big-endian ordered binary data.
* *
@@ -294,12 +325,12 @@ final class Transform
*/ */
public static function toInt16BE($value) public static function toInt16BE($value)
{ {
if (self::fromInt16("\x00\x01") == 1) if (self::isBigEndian())
return self::toInt16($value); return self::toInt16($value);
else else
return strrev(self::toInt16($value)); return strrev(self::toInt16($value));
} }
/** /**
* Returns big-endian ordered binary data as signed 16-bit integer. * Returns big-endian ordered binary data as signed 16-bit integer.
* *
@@ -308,26 +339,27 @@ final class Transform
*/ */
public static function fromInt16BE($value) public static function fromInt16BE($value)
{ {
if (self::fromInt16("\x00\x01") == 1) if (self::isBigEndian())
return self::fromInt16($value); return self::fromInt16($value);
else else
return self::fromInt16(strrev($value)); return self::fromInt16(strrev($value));
} }
/** /**
* Returns machine endian ordered binary data as unsigned 16-bit integer. * Returns machine endian ordered binary data as unsigned 16-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @param integer $order The byte order of the binary data string. * @param integer $order The byte order of the binary data string.
* @return integer * @return integer
*/ */
private static function fromUInt16($value, $order = self::MACHINE_ENDIAN_ORDER) private static function fromUInt16($value, $order = self::MACHINE_ENDIAN_ORDER)
{ {
list(, $int) = unpack(($order == 2 ? "n" : list(, $int) = unpack
($order == 1 ? "v" : "S")) . "*", $value); (($order == self::BIG_ENDIAN_ORDER ? "n" :
($order == self::LITTLE_ENDIAN_ORDER ? "v" : "S")) . "*", $value);
return $int; return $int;
} }
/** /**
* Returns unsigned 16-bit integer as little-endian ordered binary data. * Returns unsigned 16-bit integer as little-endian ordered binary data.
* *
@@ -338,10 +370,10 @@ final class Transform
{ {
return pack("v*", $value); return pack("v*", $value);
} }
/** /**
* Returns little-endian ordered binary data as unsigned 16-bit integer. * Returns little-endian ordered binary data as unsigned 16-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
@@ -349,7 +381,7 @@ final class Transform
{ {
return self::fromUInt16($value, self::LITTLE_ENDIAN_ORDER); return self::fromUInt16($value, self::LITTLE_ENDIAN_ORDER);
} }
/** /**
* Returns unsigned 16-bit integer as big-endian ordered binary data. * Returns unsigned 16-bit integer as big-endian ordered binary data.
* *
@@ -360,10 +392,10 @@ final class Transform
{ {
return pack("n*", $value); return pack("n*", $value);
} }
/** /**
* Returns big-endian ordered binary data as unsigned 16-bit integer. * Returns big-endian ordered binary data as unsigned 16-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
@@ -371,32 +403,135 @@ final class Transform
{ {
return self::fromUInt16($value, self::BIG_ENDIAN_ORDER); return self::fromUInt16($value, self::BIG_ENDIAN_ORDER);
} }
/** /**
* Returns binary data as 8-bit integer. * Returns an 8-bit integer as binary data.
* *
* @param integer $value The input value. * @param integer $value The input value.
* @return integer * @return integer
*/ */
public static function toInt8($value) public static function toInt8($value)
{ {
return chr($value); return pack("c*", $value);
} }
/** /**
* Returns binary data as 8-bit integer. * Returns binary data as 8-bit integer.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return integer * @return integer
*/ */
public static function fromInt8($value) public static function fromInt8($value)
{ {
return ord($value); list(, $int) = unpack("c*", $value);
return $int;
}
/**
* Returns an unsigned 8-bit integer as binary data.
*
* @param integer $value The input value.
* @return integer
*/
public static function toUInt8($value)
{
return pack("C*", $value);
}
/**
* Returns binary data as an unsigned 8-bit integer.
*
* @param string $value The binary data string.
* @return integer
*/
public static function fromUInt8($value)
{
list(, $int) = unpack("C*", $value);
return $int;
}
/**
* Returns a floating point number as machine endian ordered binary data.
*
* @param float $value The input value.
* @return string
*/
public static function toFloat($value)
{
return pack("f*", $value);
}
/**
* Returns machine endian ordered binary data as a floating point number.
*
* @param string $value The binary data string.
* @return float
*/
public static function fromFloat($value)
{
list(, $float) = unpack("f*", $value);
return $float;
}
/**
* Returns a floating point number as little-endian ordered binary data.
*
* @param float $value The input value.
* @return string
*/
public static function toFloatLE($value)
{
if (self::isBigEndian())
return strrev(self::toFloat($value));
else
return self::toFloat($value);
}
/**
* Returns little-endian ordered binary data as a floating point number.
*
* @param string $value The binary data string.
* @return float
*/
public static function fromFloatLE($value)
{
if (self::isBigEndian())
return self::fromFloat(strrev($value));
else
return self::fromFloat($value);
}
/**
* Returns a floating point number as big-endian ordered binary data.
*
* @param float $value The input value.
* @return string
*/
public static function toFloatBE($value)
{
if (self::isBigEndian())
return self::toFloat($value);
else
return strrev(self::toFloat($value));
}
/**
* Returns big-endian ordered binary data as a float point number.
*
* @param string $value The binary data string.
* @return float
*/
public static function fromFloatBE($value)
{
if (self::isBigEndian())
return self::fromFloat($value);
else
return self::fromFloat(strrev($value));
} }
/** /**
* Returns string as binary data padded to given length with zeros. * Returns string as binary data padded to given length with zeros.
* *
* @param string $value The input value. * @param string $value The input value.
* @return string * @return string
*/ */
@@ -415,10 +550,11 @@ final class Transform
{ {
return rtrim($value, "\0"); return rtrim($value, "\0");
} }
/** /**
* Returns machine-ordered multibyte string as machine-endian ordered binary * Returns machine-ordered multibyte string as UTF-16 defined-order binary
* data * data. The byte order is stored using a byte order mask (BOM) in the binary
* data string.
* *
* @param string $value The input value. * @param string $value The input value.
* @param integer $order The byte order of the binary data string. * @param integer $order The byte order of the binary data string.
@@ -426,29 +562,44 @@ final class Transform
*/ */
public static function toString16($value, $order = self::MACHINE_ENDIAN_ORDER) public static function toString16($value, $order = self::MACHINE_ENDIAN_ORDER)
{ {
$string = ""; $format = $order == self::BIG_ENDIAN_ORDER ? "n" :
($order == self::LITTLE_ENDIAN_ORDER ? "v" : "S");
$string = pack($format, 0xfeff);
foreach (unpack("S*", $value) as $char) foreach (unpack("S*", $value) as $char)
$string .= $string .= pack($format, $char);
pack(($order == 2 ? "n" : ($order == 1 ? "v" : "S")), $char);
return $string; return $string;
} }
/** /**
* Returns UTF-16 formatted binary data as machine-ordered multibyte string. * Returns UTF-16 formatted binary data as machine-ordered multibyte string.
* The byte order is determined from the byte order mark included in the * The byte order is determined from the byte order mark included in the
* binary data string. * binary data string. The order parameter is updated if a BOM is found.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @param integer $order The endian to decode using if no BOM was found.
* @return string * @return string
*/ */
public static function fromString16($value) public static function fromString16
($value, &$order = self::MACHINE_ENDIAN_ORDER)
{ {
if ($value[0] == 0xfe && $value[1] = 0xff) if (strlen($value) < 2)
return self::fromString16BE(substr($value, 2)); return "";
else
return self::fromString16LE(substr($value, 2)); if (ord($value[0]) == 0xfe && ord($value[1]) == 0xff) {
$order = self::BIG_ENDIAN_ORDER;
return self::fromString16BE(substr($value, 2));
}
else if (ord($value[0]) == 0xff && ord($value[1]) == 0xfe) {
$order = self::LITTLE_ENDIAN_ORDER;
return self::fromString16LE(substr($value, 2));
}
else if ($order == self::BIG_ENDIAN_ORDER ||
($order == self::MACHINE_ENDIAN_ORDER && self::isBigEndian()))
return self::fromString16BE($value);
else
return self::fromString16LE($value);
} }
/** /**
* Returns machine-ordered multibyte string as little-endian ordered binary * Returns machine-ordered multibyte string as little-endian ordered binary
* data. * data.
@@ -458,12 +609,15 @@ final class Transform
*/ */
public static function toString16LE($value) public static function toString16LE($value)
{ {
return self::toString16($value, self::LITTLE_ENDIAN_ORDER); $string = "";
foreach (unpack("S*", $value) as $char)
$string .= pack("v", $char);
return $string;
} }
/** /**
* Returns little-endian ordered binary data as machine ordered multibyte * Returns little-endian ordered binary data as machine ordered multibyte
* string. * string. Removes terminating zero.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return string * @return string
@@ -476,7 +630,7 @@ final class Transform
$string .= pack("S", $char); $string .= pack("S", $char);
return $string; return $string;
} }
/** /**
* Returns machine ordered multibyte string as big-endian ordered binary data. * Returns machine ordered multibyte string as big-endian ordered binary data.
* *
@@ -485,12 +639,16 @@ final class Transform
*/ */
public static function toString16BE($value) public static function toString16BE($value)
{ {
return self::toString16($value, self::BIG_ENDIAN_ORDER); $string = "";
foreach (unpack("S*", $value) as $char)
$string .= pack("n", $char);
return $string;
} }
/** /**
* Returns big-endian ordered binary data as machine ordered multibyte string. * Returns big-endian ordered binary data as machine ordered multibyte string.
* * Removes terminating zero.
*
* @param string $value The binary data string. * @param string $value The binary data string.
* @return string * @return string
*/ */
@@ -502,10 +660,10 @@ final class Transform
$string .= pack("S", $char); $string .= pack("S", $char);
return $string; return $string;
} }
/** /**
* Returns hexadecimal string having high nibble first as binary data. * Returns hexadecimal string having high nibble first as binary data.
* *
* @param string $value The input value. * @param string $value The input value.
* @return string * @return string
*/ */
@@ -513,22 +671,22 @@ final class Transform
{ {
return pack("H*", $value); return pack("H*", $value);
} }
/** /**
* Returns binary data as hexadecimal string having high nibble first. * Returns binary data as hexadecimal string having high nibble first.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return string * @return string
*/ */
public static function fromHHex($value) public static function fromHHex($value)
{ {
list($hex) = unpack("H*0", $value); list($hex) = unpack("H*0", $value);
return $hex; return $hex;
} }
/** /**
* Returns hexadecimal string having low nibble first as binary data. * Returns hexadecimal string having low nibble first as binary data.
* *
* @param string $value The input value. * @param string $value The input value.
* @return string * @return string
*/ */
@@ -536,23 +694,23 @@ final class Transform
{ {
return pack("h*", $value); return pack("h*", $value);
} }
/** /**
* Returns binary data as hexadecimal string having low nibble first. * Returns binary data as hexadecimal string having low nibble first.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return string * @return string
*/ */
public static function fromLHex($value) public static function fromLHex($value)
{ {
list($hex) = unpack("h*0", $value); list($hex) = unpack("h*0", $value);
return $hex; return $hex;
} }
/** /**
* Returns big-endian ordered hexadecimal GUID string as little-endian ordered * Returns big-endian ordered hexadecimal GUID string as little-endian ordered
* binary data string. * binary data string.
* *
* @param string $value The input value. * @param string $value The input value.
* @return string * @return string
*/ */
@@ -563,11 +721,11 @@ final class Transform
("V1v2N2", hexdec($C[0]), hexdec($C[1]), hexdec($C[2]), ("V1v2N2", hexdec($C[0]), hexdec($C[1]), hexdec($C[2]),
hexdec($C[3] . substr($C[4], 0, 4)), hexdec(substr($C[4], 4))); hexdec($C[3] . substr($C[4], 0, 4)), hexdec(substr($C[4], 4)));
} }
/** /**
* Returns the little-endian ordered binary data as big-endian ordered * Returns the little-endian ordered binary data as big-endian ordered
* hexadecimal GUID string. * hexadecimal GUID string.
* *
* @param string $value The binary data string. * @param string $value The binary data string.
* @return string * @return string
*/ */
@@ -576,11 +734,11 @@ final class Transform
$C = @unpack("V1V/v2v/N2N", $value); $C = @unpack("V1V/v2v/N2N", $value);
list($hex) = @unpack("H*0", pack list($hex) = @unpack("H*0", pack
("NnnNN", $C["V"], $C["v1"], $C["v2"], $C["N1"], $C["N2"])); ("NnnNN", $C["V"], $C["v1"], $C["v2"], $C["N1"], $C["N2"]));
/* Fixes a bug in PHP versions earlier than Jan 25 2006 */ /* Fixes a bug in PHP versions earlier than Jan 25 2006 */
if (implode("", unpack("H*", pack("H*", "a"))) == "a00") if (implode("", unpack("H*", pack("H*", "a"))) == "a00")
$hex = substr($hex, 0, -1); $hex = substr($hex, 0, -1);
return preg_replace return preg_replace
("/^(.{8})(.{4})(.{4})(.{4})/", "\\1-\\2-\\3-\\4-", $hex); ("/^(.{8})(.{4})(.{4})(.{4})/", "\\1-\\2-\\3-\\4-", $hex);
} }