git-svn-id: http://php-reader.googlecode.com/svn/branches/zend@153 51a70ab9-7547-0410-9469-37e369ee0574
349 lines
10 KiB
PHP
349 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* Zend Framework
|
|
*
|
|
* LICENSE
|
|
*
|
|
* This source file is subject to the new BSD license that is bundled
|
|
* with this package in the file LICENSE.txt.
|
|
* It is also available through the world-wide-web at this URL:
|
|
* http://framework.zend.com/license/new-bsd
|
|
* If you did not receive a copy of the license and are unable to
|
|
* obtain it through the world-wide-web, please send an email
|
|
* to license@zend.com so we can send you a copy immediately.
|
|
*
|
|
* @category Zend
|
|
* @package Zend_Media
|
|
* @subpackage ID3
|
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
|
* @version $Id$
|
|
*/
|
|
|
|
/**#@+ @ignore */
|
|
require_once 'Zend/Media/Id3/Object.php';
|
|
/**#@-*/
|
|
|
|
/**
|
|
* The extended header contains information that can provide further insight in
|
|
* the structure of the tag, but is not vital to the correct parsing of the tag
|
|
* information; hence the extended header is optional.
|
|
*
|
|
* @category Zend
|
|
* @package Zend_Media
|
|
* @subpackage ID3
|
|
* @author Sven Vollbehr <sven@vollbehr.eu>
|
|
* @author Ryan Butterfield <buttza@gmail.com>
|
|
* @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
|
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
|
* @version $Id$
|
|
*/
|
|
final class Zend_Media_Id3_ExtendedHeader extends Zend_Media_Id3_Object
|
|
{
|
|
/**
|
|
* A flag to denote that the present tag is an update of a tag found earlier
|
|
* in the present file or stream. If frames defined as unique are found in
|
|
* the present tag, they are to override any corresponding ones found in the
|
|
* earlier tag. This flag has no corresponding data.
|
|
*
|
|
* @since ID3v2.4.0
|
|
*/
|
|
const UPDATE = 64;
|
|
|
|
/**
|
|
* @since ID3v2.4.0 A flag to denote that a CRC-32 data is included in the
|
|
* extended header. The CRC is calculated on all the data between the header
|
|
* and footer as indicated by the header's tag length field, minus the
|
|
* extended header. Note that this includes the padding (if there is any),
|
|
* but excludes the footer. The CRC-32 is stored as an 35 bit synchsafe
|
|
* integer, leaving the upper four bits always zeroed.
|
|
*
|
|
* @since ID3v2.3.0 The CRC is calculated before unsynchronisation on the
|
|
* data between the extended header and the padding, i.e. the frames and
|
|
* only the frames.
|
|
*/
|
|
const CRC32 = 32;
|
|
|
|
/**
|
|
* A flag to denote whether or not the tag has restrictions applied on it.
|
|
*
|
|
* @since ID3v2.4.0
|
|
*/
|
|
const RESTRICTED = 16;
|
|
|
|
/** @var integer */
|
|
private $_size;
|
|
|
|
/** @var integer */
|
|
private $_flags = 0;
|
|
|
|
/** @var integer */
|
|
private $_padding;
|
|
|
|
/** @var integer */
|
|
private $_crc;
|
|
|
|
/** @var integer */
|
|
private $_restrictions = 0;
|
|
|
|
/**
|
|
* Constructs the class with given parameters and reads object related data
|
|
* from the ID3v2 tag.
|
|
*
|
|
* @param Zend_Io_Reader $reader The reader object.
|
|
* @param Array $options The options array.
|
|
*/
|
|
public function __construct($reader = null, &$options = array())
|
|
{
|
|
parent::__construct($reader, $options);
|
|
|
|
if ($reader === null)
|
|
return;
|
|
|
|
$offset = $this->_reader->getOffset();
|
|
$this->_size = $this->_reader->readUInt32BE();
|
|
|
|
/* ID3v2.3.0 ExtendedHeader */
|
|
if ($this->getOption('version', 4) < 4) {
|
|
if ($this->_reader->readUInt16BE() == 0x8000) {
|
|
$this->_flags = self::CRC32;
|
|
}
|
|
$this->_padding = $this->_reader->readUInt32BE();
|
|
if ($this->hasFlag(self::CRC32)) {
|
|
$this->_crc = $this->_reader->readUInt32BE();
|
|
}
|
|
}
|
|
|
|
/* ID3v2.4.0 ExtendedHeader */
|
|
else {
|
|
$this->_size = $this->_decodeSynchsafe32($this->_size);
|
|
$this->_reader->skip(1);
|
|
$this->_flags = $this->_reader->readInt8();
|
|
if ($this->hasFlag(self::UPDATE)) {
|
|
$this->_reader->skip(1);
|
|
}
|
|
if ($this->hasFlag(self::CRC32)) {
|
|
$this->_reader->skip(1);
|
|
$this->_crc =
|
|
$this->_reader->readInt8() * (0xfffffff + 1) +
|
|
_decodeSynchsafe32($this->_reader->readUInt32BE());
|
|
}
|
|
if ($this->hasFlag(self::RESTRICTED)) {
|
|
$this->_reader->skip(1);
|
|
$this->_restrictions = $this->_reader->readInt8();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the extended header size in bytes.
|
|
*
|
|
* @return integer
|
|
*/
|
|
public function getSize()
|
|
{
|
|
return $this->_size;
|
|
}
|
|
|
|
/**
|
|
* Checks whether or not the flag is set. Returns <var>true</var> if the
|
|
* flag is set, <var>false</var> otherwise.
|
|
*
|
|
* @param integer $flag The flag to query.
|
|
* @return boolean
|
|
*/
|
|
public function hasFlag($flag)
|
|
{
|
|
return ($this->_flags & $flag) == $flag;
|
|
}
|
|
|
|
/**
|
|
* Returns the flags byte.
|
|
*
|
|
* @return integer
|
|
*/
|
|
public function getFlags($flags)
|
|
{
|
|
return $this->_flags;
|
|
}
|
|
|
|
/**
|
|
* Sets the flags byte.
|
|
*
|
|
* @param integer $flags The flags byte.
|
|
*/
|
|
public function setFlags($flags)
|
|
{
|
|
$this->_flags = $flags;
|
|
}
|
|
|
|
/**
|
|
* Returns the CRC-32 data.
|
|
*
|
|
* @return integer
|
|
*/
|
|
public function getCrc()
|
|
{
|
|
if ($this->hasFlag(self::CRC32)) {
|
|
return $this->_crc;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets whether the CRC-32 should be generated upon tag write.
|
|
*
|
|
* @param boolean $useCrc Whether CRC-32 should be generated.
|
|
*/
|
|
public function useCrc($useCrc)
|
|
{
|
|
if ($useCrc) {
|
|
$this->setFlags($this->getFlags() | self::CRC32);
|
|
} else {
|
|
$this->setFlags($this->getFlags() & ~self::CRC32);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the CRC-32. The CRC-32 value is calculated of all the frames in the
|
|
* tag and includes padding.
|
|
*
|
|
* @param integer $crc The 32-bit CRC value.
|
|
*/
|
|
public function setCrc($crc)
|
|
{
|
|
if (is_bool($crc)) {
|
|
$this->useCrc($crc);
|
|
} else {
|
|
$this->_crc = $crc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the restrictions. For some applications it might be desired to
|
|
* restrict a tag in more ways than imposed by the ID3v2 specification. Note
|
|
* that the presence of these restrictions does not affect how the tag is
|
|
* decoded, merely how it was restricted before encoding. If this flag is
|
|
* set the tag is restricted as follows:
|
|
*
|
|
* <pre>
|
|
* Restrictions %ppqrrstt
|
|
*
|
|
* p - Tag size restrictions
|
|
*
|
|
* 00 No more than 128 frames and 1 MB total tag size.
|
|
* 01 No more than 64 frames and 128 KB total tag size.
|
|
* 10 No more than 32 frames and 40 KB total tag size.
|
|
* 11 No more than 32 frames and 4 KB total tag size.
|
|
*
|
|
* q - Text encoding restrictions
|
|
*
|
|
* 0 No restrictions
|
|
* 1 Strings are only encoded with ISO-8859-1 or UTF-8.
|
|
*
|
|
* r - Text fields size restrictions
|
|
*
|
|
* 00 No restrictions
|
|
* 01 No string is longer than 1024 characters.
|
|
* 10 No string is longer than 128 characters.
|
|
* 11 No string is longer than 30 characters.
|
|
*
|
|
* Note that nothing is said about how many bytes is used to represent
|
|
* those characters, since it is encoding dependent. If a text frame
|
|
* consists of more than one string, the sum of the strungs is restricted
|
|
* as stated.
|
|
*
|
|
* s - Image encoding restrictions
|
|
*
|
|
* 0 No restrictions
|
|
* 1 Images are encoded only with PNG [PNG] or JPEG [JFIF].
|
|
*
|
|
* t - Image size restrictions
|
|
*
|
|
* 00 No restrictions
|
|
* 01 All images are 256x256 pixels or smaller.
|
|
* 10 All images are 64x64 pixels or smaller.
|
|
* 11 All images are exactly 64x64 pixels, unless required otherwise.
|
|
* </pre>
|
|
*
|
|
* @return integer
|
|
*/
|
|
public function getRestrictions()
|
|
{
|
|
return $this->_restrictions;
|
|
}
|
|
|
|
/**
|
|
* Sets the restrictions byte. See {@link #getRestrictions} for more.
|
|
*
|
|
* @param integer $restrictions The restrictions byte.
|
|
*/
|
|
public function setRestrictions($restrictions)
|
|
{
|
|
$this->_restrictions = $restrictions;
|
|
}
|
|
|
|
/**
|
|
* Returns the total padding size, or simply the total tag size excluding
|
|
* the frames and the headers.
|
|
*
|
|
* @return integer
|
|
* @deprecated ID3v2.3.0
|
|
*/
|
|
public function getPadding()
|
|
{
|
|
return $this->_padding;
|
|
}
|
|
|
|
/**
|
|
* Sets the total padding size, or simply the total tag size excluding the
|
|
* frames and the headers.
|
|
*
|
|
* @param integer $padding The padding size.
|
|
* @deprecated ID3v2.3.0
|
|
*/
|
|
public function setPadding($padding)
|
|
{
|
|
return $this->_padding = $padding;
|
|
}
|
|
|
|
/**
|
|
* Writes the header data.
|
|
*
|
|
* @param Zend_Io_Writer $writer The writer object.
|
|
* @return void
|
|
*/
|
|
public function write($writer)
|
|
{
|
|
/* ID3v2.3.0 ExtendedHeader */
|
|
if ($this->getOption('version', 4) < 4) {
|
|
$writer->writeUInt32BE($this->_size)
|
|
->writeUInt16BE($this->hasFlag(self::CRC32) ? 0x8000 : 0)
|
|
->writeUInt32BE($this->_padding);
|
|
if ($this->hasFlag(self::CRC32)) {
|
|
$writer->writeUInt32BE($this->_crc);
|
|
}
|
|
}
|
|
|
|
/* ID3v2.4.0 ExtendedHeader */
|
|
else {
|
|
$writer->writeUInt32BE($this->_encodeSynchsafe32($this->_size))
|
|
->writeInt8(1)
|
|
->writeInt8($this->_flags);
|
|
if ($this->hasFlag(self::UPDATE)) {
|
|
$writer->write("\0");
|
|
}
|
|
if ($this->hasFlag(self::CRC32)) {
|
|
$writer->writeInt8(5)
|
|
->writeInt8
|
|
($this->_crc & 0xf0000000 >> 28 & 0xf /*eq >>> 28*/)
|
|
->writeUInt32BE($this->_encodeSynchsafe32($this->_crc));
|
|
}
|
|
if ($this->hasFlag(self::RESTRICTED)) {
|
|
$writer->writeInt8(1)
|
|
->writeInt8($this->_restrictions);
|
|
}
|
|
}
|
|
}
|
|
}
|