Add support for ID3v2.3 unsynchronisation
git-svn-id: http://php-reader.googlecode.com/svn/branches/zend@155 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
@@ -290,6 +290,10 @@ abstract class Zend_Media_Id3_Frame extends Zend_Media_Id3_Object
|
|||||||
$data = $buffer->toString();
|
$data = $buffer->toString();
|
||||||
$size = $this->_size = strlen($data);
|
$size = $this->_size = strlen($data);
|
||||||
|
|
||||||
|
// ID3v2.4.0 supports frame level unsynchronisation. The corresponding
|
||||||
|
// option is set to true when any of the frames use the
|
||||||
|
// unsynchronisation scheme. The usage is denoted by
|
||||||
|
// Zend_Media_Id3_Header flag that is set accordingly upon file write.
|
||||||
if ($this->getOption('version', 4) >= 4) {
|
if ($this->getOption('version', 4) >= 4) {
|
||||||
$data = $this->_encodeUnsynchronisation($data);
|
$data = $this->_encodeUnsynchronisation($data);
|
||||||
if (($dataLength = strlen($data)) != $size) {
|
if (($dataLength = strlen($data)) != $size) {
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ require_once 'Zend/Media/Id3/Header.php';
|
|||||||
* unique and predefined identifier which allows software to skip unknown
|
* unique and predefined identifier which allows software to skip unknown
|
||||||
* frames.
|
* frames.
|
||||||
*
|
*
|
||||||
* @todo Unsynchronisation not supported for ID3v2.3 tag
|
|
||||||
* @category Zend
|
* @category Zend
|
||||||
* @package Zend_Media
|
* @package Zend_Media
|
||||||
* @subpackage ID3
|
* @subpackage ID3
|
||||||
@@ -134,6 +133,9 @@ final class Zend_Media_Id3v2 extends Zend_Media_Id3_Object
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->_header = new Zend_Media_Id3_Header($this->_reader, $options);
|
$this->_header = new Zend_Media_Id3_Header($this->_reader, $options);
|
||||||
|
|
||||||
|
$tagSize = $this->_header->getSize();
|
||||||
|
|
||||||
if ($this->_header->getVersion() < 3 ||
|
if ($this->_header->getVersion() < 3 ||
|
||||||
$this->_header->getVersion() > 4) {
|
$this->_header->getVersion() > 4) {
|
||||||
require_once 'Zend/Media/Id3/Exception.php';
|
require_once 'Zend/Media/Id3/Exception.php';
|
||||||
@@ -142,9 +144,10 @@ final class Zend_Media_Id3v2 extends Zend_Media_Id3_Object
|
|||||||
}
|
}
|
||||||
if ($this->_header->getVersion() < 4 &&
|
if ($this->_header->getVersion() < 4 &&
|
||||||
$this->_header->hasFlag(Zend_Media_Id3_Header::UNSYNCHRONISATION)) {
|
$this->_header->hasFlag(Zend_Media_Id3_Header::UNSYNCHRONISATION)) {
|
||||||
require_once 'Zend/Media/Id3/Exception.php';
|
$data = $this->_reader->read($this->_header->getSize());
|
||||||
throw new Zend_Media_Id3_Exception
|
$this->_reader = new Zend_Io_StringReader
|
||||||
('Unsynchronisation not yet supported for this version of ID3v2 tag');
|
($this->_decodeUnsynchronisation($data));
|
||||||
|
$tagSize = $this->_reader->getSize();
|
||||||
}
|
}
|
||||||
$this->clearOption('unsyncronisation');
|
$this->clearOption('unsyncronisation');
|
||||||
if ($this->_header->hasFlag(Zend_Media_Id3_Header::UNSYNCHRONISATION)) {
|
if ($this->_header->hasFlag(Zend_Media_Id3_Header::UNSYNCHRONISATION)) {
|
||||||
@@ -164,7 +167,7 @@ final class Zend_Media_Id3v2 extends Zend_Media_Id3_Object
|
|||||||
$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 >= $tagSize -
|
||||||
($this->hasFooter() ? 10 : 0) - 10 /* header */) {
|
($this->hasFooter() ? 10 : 0) - 10 /* header */) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -517,16 +520,34 @@ final class Zend_Media_Id3v2 extends Zend_Media_Id3_Object
|
|||||||
$frame->write($buffer);
|
$frame->write($buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$data = $buffer->toString();
|
$frameData = $buffer->toString();
|
||||||
$datalen = strlen($data);
|
$frameDataLength = strlen($frameData);
|
||||||
$padlen = 0;
|
$paddingLength = 0;
|
||||||
|
|
||||||
|
// ID3v2.4.0 supports frame level unsynchronisation. The corresponding
|
||||||
|
// option is set to true when any of the frames use the
|
||||||
|
// unsynchronisation scheme.
|
||||||
if ($this->getOption('unsyncronisation', false) === true) {
|
if ($this->getOption('unsyncronisation', false) === true) {
|
||||||
$this->_header->setFlags
|
$this->_header->setFlags
|
||||||
($this->_header->getFlags() |
|
($this->_header->getFlags() |
|
||||||
Zend_Media_Id3_Header::UNSYNCHRONISATION);
|
Zend_Media_Id3_Header::UNSYNCHRONISATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ID3v2.3.0 supports only tag level unsynchronisation
|
||||||
|
if ($this->getOption('version', 4) < 4) {
|
||||||
|
$frameData = $this->_encodeUnsynchronisation($frameData);
|
||||||
|
if (($len = strlen($frameData)) != $frameDataLength) {
|
||||||
|
$frameDataLength = $len;
|
||||||
|
$this->_header->setFlags
|
||||||
|
($this->_header->getFlags() |
|
||||||
|
Zend_Media_Id3_Header::UNSYNCHRONISATION);
|
||||||
|
} else {
|
||||||
|
$this->_header->setFlags
|
||||||
|
($this->_header->getFlags() &
|
||||||
|
~Zend_Media_Id3_Header::UNSYNCHRONISATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The tag padding is calculated as follows. If the tag can be written
|
// 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
|
// in 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
|
// padding. If there is no previous tag or the new tag is bigger than
|
||||||
@@ -534,45 +555,49 @@ final class Zend_Media_Id3v2 extends Zend_Media_Id3_Object
|
|||||||
// 4096 bytes.
|
// 4096 bytes.
|
||||||
if ($this->hasFooter() === false) {
|
if ($this->hasFooter() === false) {
|
||||||
if ($this->_reader !== null &&
|
if ($this->_reader !== null &&
|
||||||
$datalen < $this->_header->getSize()) {
|
$frameDataLength < $this->_header->getSize()) {
|
||||||
$padlen = $this->_header->getSize() - $datalen;
|
$paddingLength = $this->_header->getSize() - $frameDataLength;
|
||||||
} else {
|
} else {
|
||||||
$padlen = 4096;
|
$paddingLength = 4096;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID3v2.4.0 CRC calculated w/ padding */
|
/* ID3v2.4.0 CRC calculated w/ padding */
|
||||||
if ($this->getOption('version', 4) >= 4) {
|
if ($this->getOption('version', 4) >= 4) {
|
||||||
$data = str_pad($data, $datalen + $padlen, "\0");
|
$frameData =
|
||||||
|
str_pad($frameData, $frameDataLength += $paddingLength, "\0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$extendedHeaderData = '';
|
||||||
|
$extendedHeaderDataLength = 0;
|
||||||
if ($this->hasExtendedHeader()) {
|
if ($this->hasExtendedHeader()) {
|
||||||
$this->_extendedHeader->setPadding($padlen);
|
$this->_extendedHeader->setPadding($paddingLength);
|
||||||
if ($this->_extendedHeader->hasFlag
|
if ($this->_extendedHeader->hasFlag
|
||||||
(Zend_Media_Id3_ExtendedHeader::CRC32)) {
|
(Zend_Media_Id3_ExtendedHeader::CRC32)) {
|
||||||
$crc = crc32($data);
|
$crc = crc32($frameData);
|
||||||
if ($crc & 0x80000000) {
|
if ($crc & 0x80000000) {
|
||||||
$crc = -(($crc ^ 0xffffffff) + 1);
|
$crc = -(($crc ^ 0xffffffff) + 1);
|
||||||
}
|
}
|
||||||
$this->_extendedHeader->setCrc($crc);
|
$this->_extendedHeader->setCrc($crc);
|
||||||
}
|
}
|
||||||
|
$buffer = new Zend_Io_StringWriter();
|
||||||
|
$this->_extendedHeader->write($buffer);
|
||||||
|
$extendedHeaderData = $buffer->toString();
|
||||||
|
$extendedHeaderDataLength = strlen($extendedHeaderData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ID3v2.3.0 CRC calculated w/o padding */
|
/* ID3v2.3.0 CRC calculated w/o padding */
|
||||||
if ($this->getOption('version', 4) < 4) {
|
if ($this->getOption('version', 4) < 4) {
|
||||||
$data = str_pad($data, $datalen + $padlen, "\0");
|
$frameData =
|
||||||
|
str_pad($frameData, $frameDataLength += $paddingLength, "\0");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->_header->setSize(strlen($data));
|
$this->_header->setSize($extendedHeaderDataLength + $frameDataLength);
|
||||||
|
|
||||||
$writer->write('ID3');
|
$writer->write('ID3');
|
||||||
$this->_header->write($writer);
|
$this->_header->write($writer);
|
||||||
if ($this->hasExtendedHeader()) {
|
$writer->write($extendedHeaderData);
|
||||||
$this->_extendedHeader->write($writer);
|
$writer->write($frameData);
|
||||||
}
|
|
||||||
|
|
||||||
$writer->write($data);
|
|
||||||
|
|
||||||
if ($this->hasFooter()) {
|
if ($this->hasFooter()) {
|
||||||
$writer->write('3DI');
|
$writer->write('3DI');
|
||||||
$this->_footer->write($writer);
|
$this->_footer->write($writer);
|
||||||
|
|||||||
Reference in New Issue
Block a user