Support for decoding and encoding frames with unsynchronisation schema (ID3v2.4 only)
git-svn-id: http://php-reader.googlecode.com/svn/trunk@107 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
@@ -43,7 +43,7 @@ require_once("ID3/Object.php");
|
|||||||
* A base class for all ID3v2 frames as described in the
|
* A base class for all ID3v2 frames as described in the
|
||||||
* {@link http://www.id3.org/id3v2.4.0-frames ID3v2 frames document}.
|
* {@link http://www.id3.org/id3v2.4.0-frames ID3v2 frames document}.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @package php-reader
|
* @package php-reader
|
||||||
* @subpackage ID3
|
* @subpackage ID3
|
||||||
* @author Sven Vollbehr <svollbehr@gmail.com>
|
* @author Sven Vollbehr <svollbehr@gmail.com>
|
||||||
@@ -128,11 +128,11 @@ class ID3_Frame extends ID3_Object
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw content of the frame.
|
* Raw content of the frame.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $_data = "";
|
protected $_data = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the class with given parameters and reads object related data
|
* Constructs the class with given parameters and reads object related data
|
||||||
* from the ID3v2 tag.
|
* from the ID3v2 tag.
|
||||||
@@ -144,15 +144,15 @@ class ID3_Frame extends ID3_Object
|
|||||||
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) {
|
||||||
$this->_identifier = substr(get_class($this), -4);
|
$this->_identifier = substr(get_class($this), -4);
|
||||||
} else {
|
} else {
|
||||||
$this->_identifier = $this->_reader->readString8(4);
|
$this->_identifier = $this->_reader->readString8(4);
|
||||||
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
|
||||||
|
|
||||||
/* ID3v2.3.0 Flags; convert to 2.4.0 format */
|
/* ID3v2.3.0 size and flags; convert flags to 2.4.0 format */
|
||||||
if ($this->getOption("version", 4) < 4) {
|
if ($this->getOption("version", 4) < 4) {
|
||||||
|
$this->_size = $this->_reader->readUInt32BE();
|
||||||
$flags = $this->_reader->readUInt16BE();
|
$flags = $this->_reader->readUInt16BE();
|
||||||
if (($flags & 0x8000) == 0x8000)
|
if (($flags & 0x8000) == 0x8000)
|
||||||
$this->_flags |= self::DISCARD_ON_TAGCHANGE;
|
$this->_flags |= self::DISCARD_ON_TAGCHANGE;
|
||||||
@@ -168,14 +168,26 @@ class ID3_Frame extends ID3_Object
|
|||||||
$this->_flags |= self::GROUPING_IDENTITY;
|
$this->_flags |= self::GROUPING_IDENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID3v2.4.0 Flags */
|
/* ID3v2.4.0 size and flags */
|
||||||
else
|
else {
|
||||||
|
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||||
$this->_flags = $this->_reader->readUInt16BE();
|
$this->_flags = $this->_reader->readUInt16BE();
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataLength = $this->_size;
|
||||||
|
if ($this->hasFlag(self::DATA_LENGTH_INDICATOR)) {
|
||||||
|
$dataLength = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||||
|
$this->_size -= 4;
|
||||||
|
}
|
||||||
$this->_data = $this->_reader->read($this->_size);
|
$this->_data = $this->_reader->read($this->_size);
|
||||||
|
$this->_size = $dataLength;
|
||||||
|
|
||||||
|
if ($this->hasFlag(self::UNSYNCHRONISATION) ||
|
||||||
|
$this->getOption("unsyncronisation", false) === true)
|
||||||
|
$this->_data = $this->decodeUnsynchronisation($this->_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the frame identifier string.
|
* Returns the frame identifier string.
|
||||||
*
|
*
|
||||||
@@ -227,14 +239,14 @@ class ID3_Frame extends ID3_Object
|
|||||||
/**
|
/**
|
||||||
* Sets the frame raw data.
|
* Sets the frame raw data.
|
||||||
*
|
*
|
||||||
* @return string
|
* @param string $data
|
||||||
*/
|
*/
|
||||||
protected function setData($data)
|
protected function setData($data)
|
||||||
{
|
{
|
||||||
$this->_data = $data;
|
$this->_data = $data;
|
||||||
$this->_size = strlen($data);
|
$this->_size = strlen($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the frame raw data.
|
* Returns the frame raw data.
|
||||||
*
|
*
|
||||||
@@ -263,8 +275,21 @@ class ID3_Frame extends ID3_Object
|
|||||||
else
|
else
|
||||||
$flags = $this->_flags;
|
$flags = $this->_flags;
|
||||||
|
|
||||||
|
$size = $this->_size;
|
||||||
|
if ($this->getOption("version", 4) < 4)
|
||||||
|
$data = $this->_data;
|
||||||
|
else {
|
||||||
|
$data = $this->encodeUnsynchronisation($this->_data);
|
||||||
|
if (($dataLength = strlen($data)) != $size) {
|
||||||
|
$size = 4 + $dataLength;
|
||||||
|
$data = Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
|
||||||
|
$data;
|
||||||
|
$flags |= self::DATA_LENGTH_INDICATOR | self::UNSYNCHRONISATION;
|
||||||
|
$this->setOption("unsyncronisation", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
return Transform::toString8(substr($this->_identifier, 0, 4), 4) .
|
return Transform::toString8(substr($this->_identifier, 0, 4), 4) .
|
||||||
Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
|
Transform::toUInt32BE($this->encodeSynchsafe32($size)) .
|
||||||
Transform::toUInt16BE($flags) . $this->_data;
|
Transform::toUInt16BE($flags) . $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
|
|||||||
case self::UTF16LE:
|
case self::UTF16LE:
|
||||||
$array = $this->_text;
|
$array = $this->_text;
|
||||||
foreach ($array as &$text)
|
foreach ($array as &$text)
|
||||||
$text = Transform::toString16($str);
|
$text = Transform::toString16($text);
|
||||||
$data .= Transform::toString16
|
$data .= Transform::toString16
|
||||||
(implode("\0\0", $array), $this->_encoding == self::UTF16 ?
|
(implode("\0\0", $array), $this->_encoding == self::UTF16 ?
|
||||||
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER);
|
Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER);
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ require_once("ID3/Timing.php");
|
|||||||
* a time-period is at the same time as the beat description occurs. There may
|
* a time-period is at the same time as the beat description occurs. There may
|
||||||
* only be one SYTC frame in each tag.
|
* only be one SYTC frame in each tag.
|
||||||
*
|
*
|
||||||
* @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>
|
||||||
@@ -99,7 +98,7 @@ final class ID3_Frame_SYTC extends ID3_Frame
|
|||||||
$this->_format = Transform::fromUInt8($this->_data[$offset++]);
|
$this->_format = Transform::fromUInt8($this->_data[$offset++]);
|
||||||
while ($offset < strlen($this->_data)) {
|
while ($offset < strlen($this->_data)) {
|
||||||
$tempo = Transform::fromUInt8($this->_data[$offset++]);
|
$tempo = Transform::fromUInt8($this->_data[$offset++]);
|
||||||
if ($tempo == 0xFF)
|
if ($tempo == 0xff)
|
||||||
$tempo += Transform::fromUInt8($this->_data[$offset++]);
|
$tempo += Transform::fromUInt8($this->_data[$offset++]);
|
||||||
$this->_events
|
$this->_events
|
||||||
[Transform::fromUInt32BE(substr($this->_data, $offset, 4))] = $tempo;
|
[Transform::fromUInt32BE(substr($this->_data, $offset, 4))] = $tempo;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ final class ID3_Header extends ID3_Object
|
|||||||
*/
|
*/
|
||||||
public function __construct($reader = null, &$options = array())
|
public function __construct($reader = null, &$options = array())
|
||||||
{
|
{
|
||||||
parent::__construct($reader);
|
parent::__construct($reader, $options);
|
||||||
|
|
||||||
if ($reader === null)
|
if ($reader === null)
|
||||||
return;
|
return;
|
||||||
@@ -98,8 +98,6 @@ final class ID3_Header extends ID3_Object
|
|||||||
$this->_reader->readInt8() + $this->_reader->readInt8() / 10;
|
$this->_reader->readInt8() + $this->_reader->readInt8() / 10;
|
||||||
$this->_flags = $this->_reader->readInt8();
|
$this->_flags = $this->_reader->readInt8();
|
||||||
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||||
|
|
||||||
$this->setOptions($options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ abstract class ID3_Object
|
|||||||
public function __construct($reader = null, &$options = array())
|
public function __construct($reader = null, &$options = array())
|
||||||
{
|
{
|
||||||
$this->_reader = $reader;
|
$this->_reader = $reader;
|
||||||
$this->_options = $options;
|
$this->_options = &$options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,7 +101,7 @@ abstract class ID3_Object
|
|||||||
*
|
*
|
||||||
* @param Array $options The options array.
|
* @param Array $options The options array.
|
||||||
*/
|
*/
|
||||||
public function setOptions(&$options) { $this->_options = $options; }
|
public function setOptions(&$options) { $this->_options = &$options; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the given option the given value.
|
* Sets the given option the given value.
|
||||||
@@ -168,6 +168,49 @@ abstract class ID3_Object
|
|||||||
($val & 0x7f0000) >> 2 | ($val & 0x7f000000) >> 3;
|
($val & 0x7f0000) >> 2 | ($val & 0x7f000000) >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the unsynchronisation scheme to the given data string.
|
||||||
|
*
|
||||||
|
* Whenever a false synchronisation is found within the data, one zeroed byte
|
||||||
|
* is inserted after the first false synchronisation byte. This has the side
|
||||||
|
* effect that all 0xff00 combinations have to be altered, so they will not
|
||||||
|
* be affected by the decoding process. Therefore all the 0xff00 combinations
|
||||||
|
* have to be replaced with the 0xff0000 combination during the
|
||||||
|
* unsynchronisation.
|
||||||
|
*
|
||||||
|
* @param string $data The input data.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function encodeUnsynchronisation(&$data)
|
||||||
|
{
|
||||||
|
$result = "";
|
||||||
|
for ($i = 0, $j = 0; $i < strlen($data) - 1; $i++)
|
||||||
|
if (ord($data[$i]) == 0xff &&
|
||||||
|
((($tmp = ord($data[$i + 1])) & 0xe0) == 0xe0 || $tmp == 0x0)) {
|
||||||
|
$result .= substr($data, $j, $i + 1 - $j) . "\0";
|
||||||
|
$j = $i + 1;
|
||||||
|
}
|
||||||
|
return $result . substr($data, $j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses the unsynchronisation scheme from the given data string.
|
||||||
|
*
|
||||||
|
* @see encodeUnsyncronisation
|
||||||
|
* @param string $data The input data.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function decodeUnsynchronisation(&$data)
|
||||||
|
{
|
||||||
|
$result = "";
|
||||||
|
for ($i = 0, $j = 0; $i < strlen($data) - 1; $i++)
|
||||||
|
if (ord($data[$i]) == 0xff && ord($data[$i + 1]) == 0x0) {
|
||||||
|
$result .= substr($data, $j, $i + 1 - $j);
|
||||||
|
$j = $i + 2;
|
||||||
|
}
|
||||||
|
return $result . substr($data, $j);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits UTF-16 formatted binary data up according to null terminators
|
* Splits UTF-16 formatted binary data up according to null terminators
|
||||||
* residing in the string, up to a given limit.
|
* residing in the string, up to a given limit.
|
||||||
|
|||||||
@@ -108,22 +108,25 @@ final class ID3v1
|
|||||||
private $_reader;
|
private $_reader;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $_filename;
|
private $_filename = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the ID3v1 class with given file. The file is not mandatory
|
* Constructs the ID3v1 class with given file. The file is not mandatory
|
||||||
* argument and may be omitted. A new tag can be written to a file also by
|
* argument and may be omitted. A new tag can be written to a file also by
|
||||||
* giving the filename to the {@link #write} method of this class.
|
* giving the filename to the {@link #write} method of this class.
|
||||||
*
|
*
|
||||||
* @param string $filename The path to the file.
|
* @param string|Reader $filename The path to the file, file descriptor of an
|
||||||
|
* opened file, or {@link Reader} instance.
|
||||||
*/
|
*/
|
||||||
public function __construct($filename = false)
|
public function __construct($filename = false)
|
||||||
{
|
{
|
||||||
if (($this->_filename = $filename) !== false &&
|
if ($filename instanceof Reader)
|
||||||
file_exists($filename) !== false)
|
|
||||||
$this->_reader = new Reader($filename);
|
|
||||||
else if ($filename instanceof Reader)
|
|
||||||
$this->_reader = &$filename;
|
$this->_reader = &$filename;
|
||||||
|
else if ((is_string($filename) && ($this->_filename = $filename) !== false &&
|
||||||
|
file_exists($filename) !== false) ||
|
||||||
|
(is_resource($filename) &&
|
||||||
|
in_array(get_resource_type($filename), array("file", "stream"))))
|
||||||
|
$this->_reader = new Reader($filename);
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -288,9 +291,9 @@ final class ID3v1
|
|||||||
if ($filename === false && ($filename = $this->_filename) === false)
|
if ($filename === false && ($filename = $this->_filename) === false)
|
||||||
throw new ID3_Exception("No file given to write the tag to");
|
throw new ID3_Exception("No file given to write the tag to");
|
||||||
|
|
||||||
if (($fd = fopen
|
if (($fd = fopen
|
||||||
($filename, file_exists($filename) ? "r+b" : "wb")) === false)
|
($filename, file_exists($filename) ? "r+b" : "wb")) === false)
|
||||||
throw new ID3_Exception("Unable to open file for writing: " . $filename);
|
throw new ID3_Exception("Unable to open file for writing: " . $filename);
|
||||||
|
|
||||||
fseek($fd, $this->_reader !== false ? -128 : 0, SEEK_END);
|
fseek($fd, $this->_reader !== false ? -128 : 0, SEEK_END);
|
||||||
fwrite($fd, $this, 128);
|
fwrite($fd, $this, 128);
|
||||||
|
|||||||
127
src/ID3v2.php
127
src/ID3v2.php
@@ -3,7 +3,7 @@
|
|||||||
* PHP Reader Library
|
* PHP Reader Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008 The PHP Reader Project Workgroup. All rights reserved.
|
* Copyright (c) 2008 The PHP Reader Project Workgroup. All rights 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:
|
||||||
*
|
*
|
||||||
@@ -59,10 +59,11 @@ require_once("ID3/Frame.php");
|
|||||||
* need not be known to the software that encounters them. Each frame has an
|
* need not be known to the software that encounters them. Each frame has an
|
||||||
* unique and predefined identifier which allows software to skip unknown
|
* unique and predefined identifier which allows software to skip unknown
|
||||||
* frames.
|
* frames.
|
||||||
*
|
*
|
||||||
* @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$
|
||||||
@@ -77,26 +78,26 @@ final class ID3v2
|
|||||||
|
|
||||||
/** @var ID3_ExtendedHeader */
|
/** @var ID3_ExtendedHeader */
|
||||||
private $_extendedHeader;
|
private $_extendedHeader;
|
||||||
|
|
||||||
/** @var ID3_Header */
|
/** @var ID3_Header */
|
||||||
private $_footer;
|
private $_footer;
|
||||||
|
|
||||||
/** @var Array */
|
/** @var Array */
|
||||||
private $_frames = array();
|
private $_frames = array();
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $_filename = false;
|
private $_filename = false;
|
||||||
|
|
||||||
/** @var Array */
|
/** @var Array */
|
||||||
private $_options;
|
private $_options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the ID3v2 class with given file and options. The options array
|
* Constructs the ID3v2 class with given file and options. The options array
|
||||||
* may also be given as the only parameter.
|
* may also be given as the only parameter.
|
||||||
*
|
*
|
||||||
* The following options are currently recognized:
|
* The following options are currently recognized:
|
||||||
* o version -- The ID3v2 tag version to use in write operation. This option
|
* o version -- The ID3v2 tag version to use in write operation. This option
|
||||||
* is automatically set when a tag is read from a file and defaults to
|
* is automatically set when a tag is read from a file and defaults to
|
||||||
* version 4.0 for tag write.
|
* version 4.0 for tag write.
|
||||||
* o readonly -- Indicates that the tag is read from a temporary file or
|
* o readonly -- Indicates that the tag is read from a temporary file or
|
||||||
* another source it cannot be written back to. The tag can, however,
|
* another source it cannot be written back to. The tag can, however,
|
||||||
@@ -105,9 +106,9 @@ final class ID3v2
|
|||||||
* @todo Only limited subset of flags are processed.
|
* @todo Only limited subset of flags are processed.
|
||||||
* @todo Utilize the SEEK frame and search for a footer to find the tag
|
* @todo Utilize the SEEK frame and search for a footer to find the tag
|
||||||
* @todo Utilize the LINK frame to fetch frames from other sources
|
* @todo Utilize the LINK frame to fetch frames from other sources
|
||||||
* @param string $filename The path to the file, file descriptor of an opened
|
* @param string|Reader $filename The path to the file, file descriptor of an
|
||||||
* file, or {@link Reader} instance.
|
* opened file, or {@link Reader} instance.
|
||||||
* @param Array $options The options array.
|
* @param Array $options The options array.
|
||||||
*/
|
*/
|
||||||
public function __construct($filename = false, $options = array())
|
public function __construct($filename = false, $options = array())
|
||||||
{
|
{
|
||||||
@@ -115,43 +116,50 @@ final class ID3v2
|
|||||||
$options = $filename;
|
$options = $filename;
|
||||||
$filename = false;
|
$filename = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_options = &$options;
|
$this->_options = &$options;
|
||||||
if ($filename === false ||
|
if ($filename === false ||
|
||||||
(is_string($filename) && file_exists($filename) === false) ||
|
(is_string($filename) && file_exists($filename) === false) ||
|
||||||
(is_resource($filename) && get_resource_type($filename) != "file")) {
|
(is_resource($filename) &&
|
||||||
|
in_array(get_resource_type($filename), array("file", "stream")))) {
|
||||||
$this->_header = new ID3_Header(null, $options);
|
$this->_header = new ID3_Header(null, $options);
|
||||||
} else {
|
} else {
|
||||||
if (is_string($filename) && !isset($options["readonly"]))
|
if (is_string($filename) && !isset($options["readonly"]))
|
||||||
$this->_filename = $filename;
|
$this->_filename = $filename;
|
||||||
if ($filename instanceof Reader)
|
if ($filename instanceof Reader)
|
||||||
$this->_reader = $filename;
|
$this->_reader = &$filename;
|
||||||
else
|
else
|
||||||
$this->_reader = new Reader($filename);
|
$this->_reader = new Reader($filename);
|
||||||
if ($this->_reader->readString8(3) != "ID3")
|
if ($this->_reader->readString8(3) != "ID3")
|
||||||
throw new ID3_Exception
|
throw new ID3_Exception("File does not contain ID3v2 tag");
|
||||||
("File does not contain ID3v2 tag: " . $filename);
|
|
||||||
|
|
||||||
$startOffset = $this->_reader->getOffset();
|
$startOffset = $this->_reader->getOffset();
|
||||||
|
|
||||||
$this->_header = new ID3_Header($this->_reader, $options);
|
$this->_header = new ID3_Header($this->_reader, $options);
|
||||||
if ($this->_header->getVersion() < 3 || $this->_header->getVersion() > 4)
|
if ($this->_header->getVersion() < 3 || $this->_header->getVersion() > 4)
|
||||||
throw new ID3_Exception
|
throw new ID3_Exception
|
||||||
("File does not contain ID3v2 tag of supported version: " . $filename);
|
("File does not contain ID3v2 tag of supported version");
|
||||||
|
if ($this->_header->getVersion() < 4 &&
|
||||||
|
$this->_header->hasFlag(ID3_Header::UNSYNCHRONISATION))
|
||||||
|
throw new ID3_Exception
|
||||||
|
("Unsynchronisation not supported for this version of ID3v2 tag");
|
||||||
|
unset($this->_options["unsyncronisation"]);
|
||||||
|
if ($this->_header->hasFlag(ID3_Header::UNSYNCHRONISATION))
|
||||||
|
$this->_options["unsyncronisation"] = true;
|
||||||
if ($this->_header->hasFlag(ID3_Header::EXTENDEDHEADER))
|
if ($this->_header->hasFlag(ID3_Header::EXTENDEDHEADER))
|
||||||
$this->_extendedHeader =
|
$this->_extendedHeader =
|
||||||
new ID3_ExtendedHeader($this->_reader, $options);
|
new ID3_ExtendedHeader($this->_reader, $options);
|
||||||
if ($this->_header->hasFlag(ID3_Header::FOOTER))
|
if ($this->_header->hasFlag(ID3_Header::FOOTER))
|
||||||
$this->_footer = &$this->_header; // skip footer, and rather copy header
|
$this->_footer = &$this->_header; // skip footer, and rather copy header
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
$offset = $this->_reader->getOffset();
|
$offset = $this->_reader->getOffset();
|
||||||
|
|
||||||
// Jump off the loop if we reached the end of the tag
|
// Jump off the loop if we reached the end of the tag
|
||||||
if ($offset - $startOffset - 10 >= $this->_header->getSize() -
|
if ($offset - $startOffset - 10 >= $this->_header->getSize() -
|
||||||
($this->hasFooter() ? 10 : 0))
|
($this->hasFooter() ? 10 : 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Jump off the loop if we reached the last frame
|
// Jump off the loop if we reached the last frame
|
||||||
if ($this->_reader->available() < 4 || Transform::fromUInt32BE
|
if ($this->_reader->available() < 4 || Transform::fromUInt32BE
|
||||||
($identifier = $this->_reader->read(4)) == 0)
|
($identifier = $this->_reader->read(4)) == 0)
|
||||||
@@ -165,7 +173,7 @@ final class ID3v2
|
|||||||
$frame = new $classname($this->_reader, $options);
|
$frame = new $classname($this->_reader, $options);
|
||||||
else
|
else
|
||||||
$frame = new ID3_Frame($this->_reader, $options);
|
$frame = new ID3_Frame($this->_reader, $options);
|
||||||
|
|
||||||
if (!isset($this->_frames[$frame->getIdentifier()]))
|
if (!isset($this->_frames[$frame->getIdentifier()]))
|
||||||
$this->_frames[$frame->getIdentifier()] = array();
|
$this->_frames[$frame->getIdentifier()] = array();
|
||||||
$this->_frames[$frame->getIdentifier()][] = $frame;
|
$this->_frames[$frame->getIdentifier()][] = $frame;
|
||||||
@@ -175,15 +183,15 @@ final class ID3v2
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the header object.
|
* Returns the header object.
|
||||||
*
|
*
|
||||||
* @return ID3_Header
|
* @return ID3_Header
|
||||||
*/
|
*/
|
||||||
public function getHeader() { return $this->_header; }
|
public function getHeader() { return $this->_header; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether there is an extended header present in the tag. Returns
|
* Checks whether there is an extended header present in the tag. Returns
|
||||||
* <var>true</var> if the header is present, <var>false</var> otherwise.
|
* <var>true</var> if the header is present, <var>false</var> otherwise.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function hasExtendedHeader()
|
public function hasExtendedHeader()
|
||||||
@@ -191,11 +199,11 @@ final class ID3v2
|
|||||||
if ($this->_header)
|
if ($this->_header)
|
||||||
return $this->_header->hasFlag(ID3_Header::EXTENDEDHEADER);
|
return $this->_header->hasFlag(ID3_Header::EXTENDEDHEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the extended header object if present, or <var>false</var>
|
* Returns the extended header object if present, or <var>false</var>
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @return ID3_ExtendedHeader|false
|
* @return ID3_ExtendedHeader|false
|
||||||
*/
|
*/
|
||||||
public function getExtendedHeader()
|
public function getExtendedHeader()
|
||||||
@@ -219,27 +227,27 @@ final class ID3v2
|
|||||||
$this->_extendedHeader = $extendedHeader;
|
$this->_extendedHeader = $extendedHeader;
|
||||||
} else throw new ID3_Exception("Invalid argument");
|
} else throw new ID3_Exception("Invalid argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether there is a frame given as an argument defined in the tag.
|
* Checks whether there is a frame given as an argument defined in the tag.
|
||||||
* Returns <var>true</var> if one ore more frames are present,
|
* Returns <var>true</var> if one ore more frames are present,
|
||||||
* <var>false</var> otherwise.
|
* <var>false</var> otherwise.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function hasFrame($identifier)
|
public function hasFrame($identifier)
|
||||||
{
|
{
|
||||||
return isset($this->_frames[$identifier]);
|
return isset($this->_frames[$identifier]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the frames the tag contains as an associate array. The frame
|
* Returns all the frames the tag contains as an associate array. The frame
|
||||||
* identifiers work as keys having an array of frames as associated value.
|
* identifiers work as keys having an array of frames as associated value.
|
||||||
*
|
*
|
||||||
* @return Array
|
* @return Array
|
||||||
*/
|
*/
|
||||||
public function getFrames() { return $this->_frames; }
|
public function getFrames() { return $this->_frames; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of frames matching the given identifier or an empty array
|
* Returns an array of frames matching the given identifier or an empty array
|
||||||
* if no frames matched the identifier.
|
* if no frames matched the identifier.
|
||||||
@@ -251,7 +259,7 @@ final class ID3v2
|
|||||||
* Please note that one may also use the shorthand $obj->identifier to access
|
* Please note that one may also use the shorthand $obj->identifier to access
|
||||||
* the first frame with the identifier given. Wildcards cannot be used with
|
* the first frame with the identifier given. Wildcards cannot be used with
|
||||||
* the shorthand.
|
* the shorthand.
|
||||||
*
|
*
|
||||||
* @return Array
|
* @return Array
|
||||||
*/
|
*/
|
||||||
public function getFramesByIdentifier($identifier)
|
public function getFramesByIdentifier($identifier)
|
||||||
@@ -265,7 +273,7 @@ final class ID3v2
|
|||||||
$matches[] = $frame;
|
$matches[] = $frame;
|
||||||
return $matches;
|
return $matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new frame to the tag and returns it.
|
* Adds a new frame to the tag and returns it.
|
||||||
*
|
*
|
||||||
@@ -279,18 +287,18 @@ final class ID3v2
|
|||||||
$this->_frames[$frame->getIdentifier()] = array();
|
$this->_frames[$frame->getIdentifier()] = array();
|
||||||
return $this->_frames[$frame->getIdentifier()][] = $frame;
|
return $this->_frames[$frame->getIdentifier()][] = $frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether there is a footer present in the tag. Returns
|
* Checks whether there is a footer present in the tag. Returns
|
||||||
* <var>true</var> if the footer is present, <var>false</var> otherwise.
|
* <var>true</var> if the footer is present, <var>false</var> otherwise.
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function hasFooter()
|
public function hasFooter()
|
||||||
{
|
{
|
||||||
return $this->_header->hasFlag(ID3_Header::FOOTER);
|
return $this->_header->hasFlag(ID3_Header::FOOTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the footer object if present, or <var>false</var> otherwise.
|
* Returns the footer object if present, or <var>false</var> otherwise.
|
||||||
*
|
*
|
||||||
@@ -302,7 +310,7 @@ final class ID3v2
|
|||||||
return $this->_footer;
|
return $this->_footer;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the tag should have a footer defined.
|
* Sets whether the tag should have a footer defined.
|
||||||
*
|
*
|
||||||
@@ -319,13 +327,13 @@ final class ID3v2
|
|||||||
overridden upon re-write */
|
overridden upon re-write */
|
||||||
if ($this->hasFooter())
|
if ($this->hasFooter())
|
||||||
$this->_header->setSize($this->_header->getSize() + 10);
|
$this->_header->setSize($this->_header->getSize() + 10);
|
||||||
|
|
||||||
$this->_header->setFlags
|
$this->_header->setFlags
|
||||||
($this->_header->getFlags() & ~ID3_Header::FOOTER);
|
($this->_header->getFlags() & ~ID3_Header::FOOTER);
|
||||||
$this->_footer = null;
|
$this->_footer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the possibly altered ID3v2 tag back to the file where it was read.
|
* Writes the possibly altered ID3v2 tag back to the file where it was read.
|
||||||
* If the class was constructed without a file name, one can be provided here
|
* If the class was constructed without a file name, one can be provided here
|
||||||
@@ -341,11 +349,16 @@ final class ID3v2
|
|||||||
{
|
{
|
||||||
if ($filename === false && ($filename = $this->_filename) === false)
|
if ($filename === false && ($filename = $this->_filename) === false)
|
||||||
throw new ID3_Exception("No file given to write the tag to");
|
throw new ID3_Exception("No file given to write the tag to");
|
||||||
|
else if ($filename !== false && $this->_filename !== false &&
|
||||||
|
realpath($filename) != realpath($this->_filename) &&
|
||||||
|
!copy($this->_filename, $filename))
|
||||||
|
throw new ID3_Exception("Unable to copy source to destination: " .
|
||||||
|
realpath($this->_filename) . "->" . realpath($filename));
|
||||||
|
|
||||||
if (($fd = fopen
|
if (($fd = fopen
|
||||||
($filename, file_exists($filename) ? "r+b" : "wb")) === false)
|
($filename, file_exists($filename) ? "r+b" : "wb")) === false)
|
||||||
throw new ID3_Exception("Unable to open file for writing: " . $filename);
|
throw new ID3_Exception("Unable to open file for writing: " . $filename);
|
||||||
|
|
||||||
$oldTagSize = $this->_header->getSize();
|
$oldTagSize = $this->_header->getSize();
|
||||||
$tag = "" . $this;
|
$tag = "" . $this;
|
||||||
$tagSize = empty($this->_frames) ? 0 : strlen($tag);
|
$tagSize = empty($this->_frames) ? 0 : strlen($tag);
|
||||||
@@ -368,7 +381,7 @@ final class ID3v2
|
|||||||
|
|
||||||
$this->_filename = $filename;
|
$this->_filename = $filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic function so that $obj->value will work. The method will attempt to
|
* Magic function so that $obj->value will work. The method will attempt to
|
||||||
* return the first frame that matches the identifier.
|
* return the first frame that matches the identifier.
|
||||||
@@ -393,7 +406,7 @@ final class ID3v2
|
|||||||
return $this->addFrame(new $classname());
|
return $this->addFrame(new $classname());
|
||||||
throw new ID3_Exception("Unknown frame/field: " . $name);
|
throw new ID3_Exception("Unknown frame/field: " . $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic function so that isset($obj->value) will work. This method checks
|
* Magic function so that isset($obj->value) will work. This method checks
|
||||||
* whether the frame matching the identifier exists.
|
* whether the frame matching the identifier exists.
|
||||||
@@ -401,16 +414,19 @@ final class ID3v2
|
|||||||
* @param string $name The frame identifier.
|
* @param string $name The frame identifier.
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function __isset($name) { return isset($this->_boxes[$name]); }
|
public function __isset($name)
|
||||||
|
{
|
||||||
|
return isset($this->_frames[strtoupper($name)]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Magic function so that unset($obj->value) will work. This method removes
|
* Magic function so that unset($obj->value) will work. This method removes
|
||||||
* all the frames matching the identifier.
|
* all the frames matching the identifier.
|
||||||
*
|
*
|
||||||
* @param string $name The frame identifier.
|
* @param string $name The frame identifier.
|
||||||
*/
|
*/
|
||||||
public function __unset($name) { unset($this->_boxes[$name]); }
|
public function __unset($name) { unset($this->_frames[strtoupper($name)]); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the tag raw data.
|
* Returns the tag raw data.
|
||||||
*
|
*
|
||||||
@@ -418,6 +434,8 @@ final class ID3v2
|
|||||||
*/
|
*/
|
||||||
public function __toString()
|
public function __toString()
|
||||||
{
|
{
|
||||||
|
unset($this->_options["unsyncronisation"]);
|
||||||
|
|
||||||
$data = "";
|
$data = "";
|
||||||
foreach ($this->_frames as $frames)
|
foreach ($this->_frames as $frames)
|
||||||
foreach ($frames as $frame)
|
foreach ($frames as $frame)
|
||||||
@@ -426,6 +444,11 @@ final class ID3v2
|
|||||||
$datalen = strlen($data);
|
$datalen = strlen($data);
|
||||||
$padlen = 0;
|
$padlen = 0;
|
||||||
|
|
||||||
|
if (isset($this->_options["unsyncronisation"]) &&
|
||||||
|
$this->_options["unsyncronisation"] === true)
|
||||||
|
$this->_header->setFlags
|
||||||
|
($this->_header->getFlags() | ID3_Header::UNSYNCHRONISATION);
|
||||||
|
|
||||||
/* The tag padding is calculated as follows. If the tag can be written in
|
/* The tag padding is calculated as follows. If the tag can be written in
|
||||||
the space of the previous tag, the remaining space is used for padding.
|
the space of the previous tag, the remaining space is used for padding.
|
||||||
If there is no previous tag or the new tag is bigger than the space taken
|
If there is no previous tag or the new tag is bigger than the space taken
|
||||||
@@ -438,11 +461,11 @@ final class ID3v2
|
|||||||
else
|
else
|
||||||
$padlen = ceil(log(0.2 * ($datalen / 1024 + 10), 10) * 1024);
|
$padlen = ceil(log(0.2 * ($datalen / 1024 + 10), 10) * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID3v2.4.0 CRC calculated w/ padding */
|
/* ID3v2.4.0 CRC calculated w/ padding */
|
||||||
if (!isset($this->_options["version"]) || $this->_options["version"] >= 4)
|
if (!isset($this->_options["version"]) || $this->_options["version"] >= 4)
|
||||||
$data = str_pad($data, $datalen + $padlen, "\0");
|
$data = str_pad($data, $datalen + $padlen, "\0");
|
||||||
|
|
||||||
if ($this->hasExtendedHeader()) {
|
if ($this->hasExtendedHeader()) {
|
||||||
$this->_extendedHeader->setPadding($padlen);
|
$this->_extendedHeader->setPadding($padlen);
|
||||||
if ($this->_extendedHeader->hasFlag(ID3_ExtendedHeader::CRC32)) {
|
if ($this->_extendedHeader->hasFlag(ID3_ExtendedHeader::CRC32)) {
|
||||||
@@ -453,13 +476,13 @@ final class ID3v2
|
|||||||
}
|
}
|
||||||
$data = $this->getExtendedHeader() . $data;
|
$data = $this->getExtendedHeader() . $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID3v2.3.0 CRC calculated w/o padding */
|
/* ID3v2.3.0 CRC calculated w/o padding */
|
||||||
if (isset($this->_options["version"]) && $this->_options["version"] < 4)
|
if (isset($this->_options["version"]) && $this->_options["version"] < 4)
|
||||||
$data = str_pad($data, $datalen + $padlen, "\0");
|
$data = str_pad($data, $datalen + $padlen, "\0");
|
||||||
|
|
||||||
$this->_header->setSize(strlen($data));
|
$this->_header->setSize(strlen($data));
|
||||||
|
|
||||||
return "ID3" . $this->_header . $data .
|
return "ID3" . $this->_header . $data .
|
||||||
($this->hasFooter() ? "3DI" . $this->getFooter() : "");
|
($this->hasFooter() ? "3DI" . $this->getFooter() : "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ require_once("PHPUnit/Framework.php");
|
|||||||
require_once("PHPUnit/TextUI/TestRunner.php");
|
require_once("PHPUnit/TextUI/TestRunner.php");
|
||||||
|
|
||||||
ini_set("include_path", ini_get("include_path") . PATH_SEPARATOR . "../src/");
|
ini_set("include_path", ini_get("include_path") . PATH_SEPARATOR . "../src/");
|
||||||
|
ini_set("memory_limit", "16M");
|
||||||
|
|
||||||
$suite = new PHPUnit_Framework_TestSuite("PHP Reader");
|
$suite = new PHPUnit_Framework_TestSuite("PHP Reader");
|
||||||
|
|
||||||
|
|||||||
@@ -121,4 +121,19 @@ final class TestID3v2 extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals("13/13", $id3->trck->text);
|
$this->assertEquals("13/13", $id3->trck->text);
|
||||||
$this->assertEquals("Trance", $id3->tcon->text);
|
$this->assertEquals("Trance", $id3->tcon->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testUnsynchronisation()
|
||||||
|
{
|
||||||
|
$id3 = new ID3v2("id3v2.tag");
|
||||||
|
$id3->tit2->text = "\xff\xf0";
|
||||||
|
$id3->tcon->text = "\xff\xe0\xf0";
|
||||||
|
$id3->write();
|
||||||
|
|
||||||
|
$this->assertEquals
|
||||||
|
("TIT2\0\0\0\x08\0\x03\0\0\0\x03\x03\xff\x00\xf0", "" . $id3->tit2);
|
||||||
|
|
||||||
|
$id3 = new ID3v2("id3v2.tag");
|
||||||
|
$this->assertEquals("\xff\xf0", $id3->tit2->text);
|
||||||
|
$this->assertEquals("\xff\xe0\xf0", $id3->tcon->text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ require_once("Transform.php");
|
|||||||
* @package php-reader
|
* @package php-reader
|
||||||
* @subpackage Tests
|
* @subpackage Tests
|
||||||
* @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,11 +66,13 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
(0x7fffffffffffffff, Transform::fromInt64BE
|
(0x7fffffffffffffff, Transform::fromInt64BE
|
||||||
(Transform::toInt64BE(0x7fffffffffffffff)));
|
(Transform::toInt64BE(0x7fffffffffffffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInt32()
|
function testInt32()
|
||||||
{
|
{
|
||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
(0x7fffffff, Transform::fromInt32(Transform::toInt32(0x7fffffff)));
|
(0x7fffffff, Transform::fromInt32(Transform::toInt32(0x7fffffff)));
|
||||||
|
$this->assertEquals
|
||||||
|
(-0x7fffffff, Transform::fromInt32(Transform::toInt32(-0x7fffffff)));
|
||||||
$this->assertEquals(-1, Transform::fromInt32(Transform::toInt32(-1)));
|
$this->assertEquals(-1, Transform::fromInt32(Transform::toInt32(-1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +81,8 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(1, Transform::fromInt32LE("\x01\x00\x00\x00"));
|
$this->assertEquals(1, Transform::fromInt32LE("\x01\x00\x00\x00"));
|
||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
(0x7fffffff, Transform::fromInt32LE(Transform::toInt32LE(0x7fffffff)));
|
(0x7fffffff, Transform::fromInt32LE(Transform::toInt32LE(0x7fffffff)));
|
||||||
|
$this->assertEquals
|
||||||
|
(-0x7fffffff, Transform::fromInt32LE(Transform::toInt32LE(-0x7fffffff)));
|
||||||
$this->assertEquals(-1, Transform::fromInt32LE(Transform::toInt32LE(-1)));
|
$this->assertEquals(-1, Transform::fromInt32LE(Transform::toInt32LE(-1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +91,8 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(1, Transform::fromInt32BE("\x00\x00\x00\x01"));
|
$this->assertEquals(1, Transform::fromInt32BE("\x00\x00\x00\x01"));
|
||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
(0x7fffffff, Transform::fromInt32BE(Transform::toInt32BE(0x7fffffff)));
|
(0x7fffffff, Transform::fromInt32BE(Transform::toInt32BE(0x7fffffff)));
|
||||||
$this->assertEquals(-1, Transform::fromInt32BE(Transform::toInt32BE(-1)));
|
$this->assertEquals
|
||||||
|
(-0x7fffffff, Transform::fromInt32BE(Transform::toInt32BE(-0x7fffffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUInt32LE()
|
function testUInt32LE()
|
||||||
@@ -104,7 +110,7 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
(0xffffffff, Transform::fromUInt32BE(Transform::toUInt32BE(0xffffffff)));
|
(0xffffffff, Transform::fromUInt32BE(Transform::toUInt32BE(0xffffffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInt16()
|
function testInt16()
|
||||||
{
|
{
|
||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
@@ -143,7 +149,7 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
(0xffff, Transform::fromUInt16BE(Transform::toUInt16BE(0xffff)));
|
(0xffff, Transform::fromUInt16BE(Transform::toUInt16BE(0xffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testInt8()
|
function testInt8()
|
||||||
{
|
{
|
||||||
$this->assertEquals(0x7f, Transform::fromInt8(Transform::toInt8(0x7f)));
|
$this->assertEquals(0x7f, Transform::fromInt8(Transform::toInt8(0x7f)));
|
||||||
@@ -152,9 +158,25 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
function testString16()
|
function testString16()
|
||||||
{
|
{
|
||||||
$this->assertEquals("00e4", Transform::fromHHex
|
$this->assertEquals("00e4", Transform::fromHHex
|
||||||
(Transform::fromString16(Transform::toString16("\xff\xfe\x00\xe4"))));
|
(Transform::fromString16(Transform::toString16("\x00\xe4"))));
|
||||||
$this->assertEquals("00e4", Transform::fromHHex
|
$this->assertEquals
|
||||||
(Transform::fromString16(Transform::toString16("\xfe\xff\x00\xe4"))));
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::fromString16(Transform::toString16LE
|
||||||
|
("\xff\xfe\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
|
||||||
|
$this->assertEquals
|
||||||
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::fromString16(Transform::toString16BE
|
||||||
|
("\xff\xfe\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
|
||||||
|
$this->assertEquals
|
||||||
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::fromString16(Transform::toString16
|
||||||
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::LITTLE_ENDIAN_ORDER)));
|
||||||
|
$this->assertEquals
|
||||||
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::fromString16(Transform::toString16
|
||||||
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.",
|
||||||
|
Transform::BIG_ENDIAN_ORDER)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testString16LE()
|
function testString16LE()
|
||||||
@@ -176,7 +198,7 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
Transform::fromString16BE(Transform::toString16BE
|
Transform::fromString16BE(Transform::toString16BE
|
||||||
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
|
("\0T\0h\0i\0s\0 \0i\0s\0 \0a\0 \0t\0e\0s\0t\0.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHHex()
|
function testHHex()
|
||||||
{
|
{
|
||||||
$this->assertEquals("6c34", bin2hex(Transform::toHHex("6c34")));
|
$this->assertEquals("6c34", bin2hex(Transform::toHHex("6c34")));
|
||||||
@@ -188,13 +210,12 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals("c643", bin2hex(Transform::toLHex("6c34")));
|
$this->assertEquals("c643", bin2hex(Transform::toLHex("6c34")));
|
||||||
$this->assertEquals("6c34", Transform::fromLHex(Transform::toLHex("6c34")));
|
$this->assertEquals("6c34", Transform::fromLHex(Transform::toLHex("6c34")));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testGUID()
|
function testGUID()
|
||||||
{
|
{
|
||||||
$this->assertEquals
|
$this->assertEquals
|
||||||
("75b22630-668e-11cf-a6d9-00aa0062ce6c",
|
("75b22630-668e-11cf-a6d9-00aa0062ce6c",
|
||||||
Transform::fromGUID(Transform::toGUID
|
Transform::fromGUID(Transform::toGUID
|
||||||
("75b22630-668e-11cf-a6d9-00aa0062ce6c")));
|
("75b22630-668e-11cf-a6d9-00aa0062ce6c")));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user