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:
@@ -149,10 +149,10 @@ class ID3_Frame extends ID3_Object
|
|||||||
$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,11 +168,23 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +239,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -63,6 +63,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$
|
||||||
@@ -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())
|
||||||
{
|
{
|
||||||
@@ -119,25 +120,32 @@ final class ID3v2
|
|||||||
$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);
|
||||||
@@ -341,6 +349,11 @@ 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)
|
||||||
@@ -401,7 +414,10 @@ 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
|
||||||
@@ -409,7 +425,7 @@ final class ID3v2
|
|||||||
*
|
*
|
||||||
* @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
|
||||||
|
|||||||
@@ -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$
|
||||||
@@ -70,6 +71,8 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$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()
|
||||||
@@ -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()
|
||||||
@@ -196,5 +218,4 @@ final class TestTransform extends PHPUnit_Framework_TestCase
|
|||||||
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