diff --git a/wp-includes/ID3/getid3.lib.php b/wp-includes/ID3/getid3.lib.php index a7282c77c0..0c92e060c3 100644 --- a/wp-includes/ID3/getid3.lib.php +++ b/wp-includes/ID3/getid3.lib.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // // // getid3.lib.php - part of getID3() // @@ -282,7 +283,6 @@ class getid3_lib } } else { throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()'); - break; } } return self::CastAsInt($intvalue); @@ -635,7 +635,7 @@ class getid3_lib } if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) { if (($fp_dest = fopen($filename_dest, 'wb'))) { - if (fseek($fp_src, $offset, SEEK_SET) == 0) { + if (fseek($fp_src, $offset) == 0) { $byteslefttowrite = $length; while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) { $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite); @@ -986,6 +986,19 @@ class getid3_lib throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset); } + public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') { + if (is_string($data)) { + return self::MultiByteCharString2HTML($data, $charset); + } elseif (is_array($data)) { + $return_data = array(); + foreach ($data as $key => $value) { + $return_data[$key] = self::recursiveMultiByteCharString2HTML($value, $charset); + } + return $return_data; + } + // integer, float, objects, resources, etc + return $data; + } public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') { $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string @@ -1210,16 +1223,21 @@ class getid3_lib $newvaluelength = strlen(trim($value)); foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { $oldvaluelength = strlen(trim($existingvalue)); - if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { + if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); - break 2; + //break 2; + break; } } } if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) { $value = (is_string($value) ? trim($value) : $value); - $ThisFileInfo['comments'][$tagname][] = $value; + if (!is_numeric($key)) { + $ThisFileInfo['comments'][$tagname][$key] = $value; + } else { + $ThisFileInfo['comments'][$tagname][] = $value; + } } } } @@ -1227,20 +1245,23 @@ class getid3_lib } // Copy to ['comments_html'] - foreach ($ThisFileInfo['comments'] as $field => $values) { - if ($field == 'picture') { - // pictures can take up a lot of space, and we don't need multiple copies of them - // let there be a single copy in [comments][picture], and not elsewhere - continue; - } - foreach ($values as $index => $value) { - if (is_array($value)) { - $ThisFileInfo['comments_html'][$field][$index] = $value; - } else { - $ThisFileInfo['comments_html'][$field][$index] = str_replace('�', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding'])); + if (!empty($ThisFileInfo['comments'])) { + foreach ($ThisFileInfo['comments'] as $field => $values) { + if ($field == 'picture') { + // pictures can take up a lot of space, and we don't need multiple copies of them + // let there be a single copy in [comments][picture], and not elsewhere + continue; + } + foreach ($values as $index => $value) { + if (is_array($value)) { + $ThisFileInfo['comments_html'][$field][$index] = $value; + } else { + $ThisFileInfo['comments_html'][$field][$index] = str_replace('�', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding'])); + } } } } + } return true; } @@ -1339,4 +1360,17 @@ class getid3_lib } return $filesize; } + + + /** + * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) + * @param string $path A path. + * @param string $suffix If the name component ends in suffix this will also be cut off. + * @return string + */ + public static function mb_basename($path, $suffix = null) { + $splited = preg_split('#/#', rtrim($path, '/ ')); + return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); + } + } \ No newline at end of file diff --git a/wp-includes/ID3/getid3.php b/wp-includes/ID3/getid3.php index 84b9cce6ef..394e25e4e3 100644 --- a/wp-includes/ID3/getid3.php +++ b/wp-includes/ID3/getid3.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // // // Please see readme.txt for more information // @@ -17,18 +18,21 @@ if (!defined('GETID3_OS_ISWINDOWS')) { if (!defined('GETID3_INCLUDEPATH')) { define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); } +// Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923) +if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { + define('IMG_JPG', IMAGETYPE_JPEG); +} // attempt to define temp dir as something flexible but reliable $temp_dir = ini_get('upload_tmp_dir'); if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { $temp_dir = ''; } -if (!$temp_dir && function_exists('sys_get_temp_dir')) { - // PHP v5.2.1+ +if (!$temp_dir) { // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts $temp_dir = sys_get_temp_dir(); } -$temp_dir = realpath($temp_dir); +$temp_dir = @realpath($temp_dir); // see https://github.com/JamesHeinrich/getID3/pull/10 $open_basedir = ini_get('open_basedir'); if ($open_basedir) { // e.g. "/var/www/vhosts/getid3.org/httpdocs/:/tmp/" @@ -57,7 +61,9 @@ if (!$temp_dir) { $temp_dir = '*'; // invalid directory name should force tempnam() to use system default temp dir } // $temp_dir = '/something/else/'; // feel free to override temp dir here if it works better for your system -define('GETID3_TEMP_DIR', $temp_dir); +if (!defined('GETID3_TEMP_DIR')) { + define('GETID3_TEMP_DIR', $temp_dir); +} unset($open_basedir, $temp_dir); // End: Defines @@ -97,13 +103,13 @@ class getID3 public $fp; // Filepointer to file being analysed. public $info; // Result array. public $tempdir = GETID3_TEMP_DIR; + public $memory_limit = 0; // Protected variables protected $startup_error = ''; protected $startup_warning = ''; - protected $memory_limit = 0; - const VERSION = '1.9.7-20130705'; + const VERSION = '1.9.8-20140511'; const FREAD_BUFFER_SIZE = 32768; const ATTACHMENTS_NONE = false; @@ -112,13 +118,6 @@ class getID3 // public: constructor public function __construct() { - // Check for PHP version - $required_php_version = '5.0.5'; - if (version_compare(PHP_VERSION, $required_php_version, '<')) { - $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION; - return false; - } - // Check memory $this->memory_limit = ini_get('memory_limit'); if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) { @@ -261,16 +260,32 @@ class getID3 $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); // open local file - if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { + //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 + if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // great } else { - throw new getid3_exception('Could not open "'.$filename.'" (does not exist, or is not a file)'); + $errormessagelist = array(); + if (!is_readable($filename)) { + $errormessagelist[] = '!is_readable'; + } + if (!is_file($filename)) { + $errormessagelist[] = '!is_file'; + } + if (!file_exists($filename)) { + $errormessagelist[] = '!file_exists'; + } + if (empty($errormessagelist)) { + $errormessagelist[] = 'fopen failed'; + } + throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')'); } $this->info['filesize'] = filesize($filename); // set redundant parameters - might be needed in some include file - $this->info['filename'] = basename($filename); + // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion + $filename = str_replace('\\', '/', $filename); $this->info['filepath'] = str_replace('\\', '/', realpath(dirname($filename))); + $this->info['filename'] = getid3_lib::mb_basename($filename); $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename']; @@ -352,7 +367,7 @@ class getID3 // ID3v2 detection (NOT parsing), even if ($this->option_tag_id3v2 == false) done to make fileformat easier if (!$this->option_tag_id3v2) { - fseek($this->fp, 0, SEEK_SET); + fseek($this->fp, 0); $header = fread($this->fp, 10); if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) { $this->info['id3v2']['header'] = true; @@ -363,7 +378,7 @@ class getID3 } // read 32 kb file data - fseek($this->fp, $this->info['avdataoffset'], SEEK_SET); + fseek($this->fp, $this->info['avdataoffset']); $formattest = fread($this->fp, 32774); // determine format @@ -588,6 +603,14 @@ class getID3 'mime_type' => 'audio/basic', ), + // AMR - audio - Adaptive Multi Rate + 'amr' => array( + 'pattern' => '^\x23\x21AMR\x0A', // #!AMR[0A] + 'group' => 'audio', + 'module' => 'amr', + 'mime_type' => 'audio/amr', + ), + // AVR - audio - Audio Visual Research 'avr' => array( 'pattern' => '^2BIT', @@ -1161,6 +1184,7 @@ class getID3 'matroska' => array('matroska' , 'UTF-8'), 'flac' => array('vorbiscomment' , 'UTF-8'), 'divxtag' => array('divx' , 'ISO-8859-1'), + 'iptc' => array('iptc' , 'ISO-8859-1'), ); } @@ -1181,7 +1205,11 @@ class getID3 $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed! } if ($value) { - $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value; + if (!is_numeric($key)) { + $this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value; + } else { + $this->info['tags'][trim($tag_name)][trim($tag_key)][] = $value; + } } } if ($tag_key == 'picture') { @@ -1196,14 +1224,7 @@ class getID3 if ($this->option_tags_html) { foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) { - foreach ($valuearray as $key => $value) { - if (is_string($value)) { - //$this->info['tags_html'][$tag_name][$tag_key][$key] = getid3_lib::MultiByteCharString2HTML($value, $encoding); - $this->info['tags_html'][$tag_name][$tag_key][$key] = str_replace('�', '', trim(getid3_lib::MultiByteCharString2HTML($value, $encoding))); - } else { - $this->info['tags_html'][$tag_name][$tag_key][$key] = $value; - } - } + $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding); } } @@ -1259,7 +1280,6 @@ class getID3 return true; } - public function getHashdata($algorithm) { switch ($algorithm) { case 'md5': @@ -1565,8 +1585,11 @@ class getID3 } -abstract class getid3_handler -{ +abstract class getid3_handler { + + /** + * @var getID3 + */ protected $getid3; // pointer protected $data_string_flag = false; // analyzing filepointer or string @@ -1593,7 +1616,7 @@ abstract class getid3_handler // Analyze from string instead public function AnalyzeString($string) { // Enter string mode - $this->setStringMode($string); + $this->setStringMode($string); // Save info $saved_avdataoffset = $this->getid3->info['avdataoffset']; @@ -1634,10 +1657,10 @@ abstract class getid3_handler $this->data_string_position += $bytes; return substr($this->data_string, $this->data_string_position - $bytes, $bytes); } - $pos = $this->ftell() + $bytes; - if (!getid3_lib::intValueSupported($pos)) { + $pos = $this->ftell() + $bytes; + if (!getid3_lib::intValueSupported($pos)) { throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); - } + } return fread($this->getid3->fp, $bytes); } @@ -1657,14 +1680,14 @@ abstract class getid3_handler break; } return 0; - } else { - $pos = $bytes; - if ($whence == SEEK_CUR) { + } else { + $pos = $bytes; + if ($whence == SEEK_CUR) { $pos = $this->ftell() + $bytes; - } elseif ($whence == SEEK_END) { - $pos = $this->info['filesize'] + $bytes; - } - if (!getid3_lib::intValueSupported($pos)) { + } elseif ($whence == SEEK_END) { + $pos = $this->getid3->info['filesize'] + $bytes; + } + if (!getid3_lib::intValueSupported($pos)) { throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); } } @@ -1682,20 +1705,17 @@ abstract class getid3_handler return $this->dependency_to == $module; } - protected function error($text) - { + protected function error($text) { $this->getid3->info['error'][] = $text; return false; } - protected function warning($text) - { + protected function warning($text) { return $this->getid3->warning($text); } - protected function notice($text) - { + protected function notice($text) { // does nothing for now } diff --git a/wp-includes/ID3/license.commercial.txt b/wp-includes/ID3/license.commercial.txt index 416e5a1469..bc7861bf87 100644 --- a/wp-includes/ID3/license.commercial.txt +++ b/wp-includes/ID3/license.commercial.txt @@ -24,4 +24,4 @@ made publicly available to all getID3() users. The licensee may not sub-license getID3() itself, meaning that any commercially released product containing all or parts of getID3() must have added functionality beyond what is available in getID3(); -getID3() itself may not be re-licensed by the licensee. +getID3() itself may not be re-licensed by the licensee. \ No newline at end of file diff --git a/wp-includes/ID3/license.txt b/wp-includes/ID3/license.txt index 85f4356e81..32d8ec76ee 100644 --- a/wp-includes/ID3/license.txt +++ b/wp-includes/ID3/license.txt @@ -2,6 +2,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// ***************************************************************** @@ -25,4 +26,4 @@ getID3 Commercial License: http://getid3.org/#gCL (payment required) ***************************************************************** Copies of each of the above licenses are included in the 'licenses' -directory of the getID3 distribution. +directory of the getID3 distribution. \ No newline at end of file diff --git a/wp-includes/ID3/module.audio-video.asf.php b/wp-includes/ID3/module.audio-video.asf.php index cfc60a7803..884e2fff66 100644 --- a/wp-includes/ID3/module.audio-video.asf.php +++ b/wp-includes/ID3/module.audio-video.asf.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -15,8 +16,7 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); -class getid3_asf extends getid3_handler -{ +class getid3_asf extends getid3_handler { public function __construct(getID3 $getid3) { parent::__construct($getid3); // extends getid3_handler::__construct() @@ -66,25 +66,22 @@ class getid3_asf extends getid3_handler $info['fileformat'] = 'asf'; - fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); - $HeaderObjectData = fread($this->getid3->fp, 30); + $this->fseek($info['avdataoffset']); + $HeaderObjectData = $this->fread(30); $thisfile_asf_headerobject['objectid'] = substr($HeaderObjectData, 0, 16); $thisfile_asf_headerobject['objectid_guid'] = $this->BytestringToGUID($thisfile_asf_headerobject['objectid']); if ($thisfile_asf_headerobject['objectid'] != GETID3_ASF_Header_Object) { - $info['warning'][] = 'ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}'; - unset($info['fileformat']); - unset($info['asf']); - return false; - break; + unset($info['fileformat'], $info['asf']); + return $this->error('ASF header GUID {'.$this->BytestringToGUID($thisfile_asf_headerobject['objectid']).'} does not match expected "GETID3_ASF_Header_Object" GUID {'.$this->BytestringToGUID(GETID3_ASF_Header_Object).'}'); } $thisfile_asf_headerobject['objectsize'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 16, 8)); $thisfile_asf_headerobject['headerobjects'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 24, 4)); $thisfile_asf_headerobject['reserved1'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 28, 1)); $thisfile_asf_headerobject['reserved2'] = getid3_lib::LittleEndian2Int(substr($HeaderObjectData, 29, 1)); - $NextObjectOffset = ftell($this->getid3->fp); - $ASFHeaderData = fread($this->getid3->fp, $thisfile_asf_headerobject['objectsize'] - 30); + $NextObjectOffset = $this->ftell(); + $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30); $offset = 0; for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { @@ -284,7 +281,7 @@ class getid3_asf extends getid3_handler $offset += 4; $thisfile_asf_headerextensionobject['extension_data'] = substr($ASFHeaderData, $offset, $thisfile_asf_headerextensionobject['extension_data_size']); $unhandled_sections = 0; - $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->ASF_HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections); + $thisfile_asf_headerextensionobject['extension_data_parsed'] = $this->HeaderExtensionObjectDataParse($thisfile_asf_headerextensionobject['extension_data'], $unhandled_sections); if ($unhandled_sections === 0) { unset($thisfile_asf_headerextensionobject['extension_data']); } @@ -332,7 +329,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_codeclistobject_codecentries_current['type_raw'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); $offset += 2; - $thisfile_asf_codeclistobject_codecentries_current['type'] = $this->ASFCodecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']); + $thisfile_asf_codeclistobject_codecentries_current['type'] = self::codecListObjectTypeLookup($thisfile_asf_codeclistobject_codecentries_current['type_raw']); $CodecNameLength = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)) * 2; // 2 bytes per character $offset += 2; @@ -826,22 +823,14 @@ class getid3_asf extends getid3_handler break; case 'id3': - // id3v2 module might not be loaded - if (class_exists('getid3_id3v2')) { - $tempfile = tempnam(GETID3_TEMP_DIR, 'getID3'); - $tempfilehandle = fopen($tempfile, 'wb'); - $tempThisfileInfo = array('encoding'=>$info['encoding']); - fwrite($tempfilehandle, $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); - fclose($tempfilehandle); + $this->getid3->include_module('tag.id3v2'); - $getid3_temp = new getID3(); - $getid3_temp->openfile($tempfile); - $getid3_id3v2 = new getid3_id3v2($getid3_temp); - $getid3_id3v2->Analyze(); - $info['id3v2'] = $getid3_temp->info['id3v2']; - unset($getid3_temp, $getid3_id3v2); + $getid3_id3v2 = new getid3_id3v2($this->getid3); + $getid3_id3v2->AnalyzeString($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']); + unset($getid3_id3v2); - unlink($tempfile); + if ($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_length'] > 1024) { + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'] = ''; } break; @@ -860,7 +849,7 @@ class getid3_asf extends getid3_handler $wm_picture_offset = 0; $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 1)); $wm_picture_offset += 1; - $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type'] = $this->WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']); + $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type'] = self::WMpictureTypeLookup($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_type_id']); $thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['image_size'] = getid3_lib::LittleEndian2Int(substr($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'], $wm_picture_offset, 4)); $wm_picture_offset += 4; @@ -1156,8 +1145,8 @@ class getid3_asf extends getid3_handler } } - while (ftell($this->getid3->fp) < $info['avdataend']) { - $NextObjectDataHeader = fread($this->getid3->fp, 24); + while ($this->ftell() < $info['avdataend']) { + $NextObjectDataHeader = $this->fread(24); $offset = 0; $NextObjectGUID = substr($NextObjectDataHeader, 0, 16); $offset += 16; @@ -1179,7 +1168,7 @@ class getid3_asf extends getid3_handler $thisfile_asf['data_object'] = array(); $thisfile_asf_dataobject = &$thisfile_asf['data_object']; - $DataObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 50 - 24); + $DataObjectData = $NextObjectDataHeader.$this->fread(50 - 24); $offset = 24; $thisfile_asf_dataobject['objectid'] = $NextObjectGUID; @@ -1207,9 +1196,9 @@ class getid3_asf extends getid3_handler // * * Error Correction Present bits 1 // If set, use Opaque Data Packet structure, else use Payload structure // * Error Correction Data - $info['avdataoffset'] = ftell($this->getid3->fp); - fseek($this->getid3->fp, ($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data - $info['avdataend'] = ftell($this->getid3->fp); + $info['avdataoffset'] = $this->ftell(); + $this->fseek(($thisfile_asf_dataobject['objectsize'] - 50), SEEK_CUR); // skip actual audio/video data + $info['avdataend'] = $this->ftell(); break; case GETID3_ASF_Simple_Index_Object: @@ -1229,7 +1218,7 @@ class getid3_asf extends getid3_handler $thisfile_asf['simple_index_object'] = array(); $thisfile_asf_simpleindexobject = &$thisfile_asf['simple_index_object']; - $SimpleIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 56 - 24); + $SimpleIndexObjectData = $NextObjectDataHeader.$this->fread(56 - 24); $offset = 24; $thisfile_asf_simpleindexobject['objectid'] = $NextObjectGUID; @@ -1246,7 +1235,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_simpleindexobject['index_entries_count'] = getid3_lib::LittleEndian2Int(substr($SimpleIndexObjectData, $offset, 4)); $offset += 4; - $IndexEntriesData = $SimpleIndexObjectData.fread($this->getid3->fp, 6 * $thisfile_asf_simpleindexobject['index_entries_count']); + $IndexEntriesData = $SimpleIndexObjectData.$this->fread(6 * $thisfile_asf_simpleindexobject['index_entries_count']); for ($IndexEntriesCounter = 0; $IndexEntriesCounter < $thisfile_asf_simpleindexobject['index_entries_count']; $IndexEntriesCounter++) { $thisfile_asf_simpleindexobject['index_entries'][$IndexEntriesCounter]['packet_number'] = getid3_lib::LittleEndian2Int(substr($IndexEntriesData, $offset, 4)); $offset += 4; @@ -1283,7 +1272,7 @@ class getid3_asf extends getid3_handler $thisfile_asf['asf_index_object'] = array(); $thisfile_asf_asfindexobject = &$thisfile_asf['asf_index_object']; - $ASFIndexObjectData = $NextObjectDataHeader.fread($this->getid3->fp, 34 - 24); + $ASFIndexObjectData = $NextObjectDataHeader.$this->fread(34 - 24); $offset = 24; $thisfile_asf_asfindexobject['objectid'] = $NextObjectGUID; @@ -1297,7 +1286,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_asfindexobject['index_blocks_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); $offset += 4; - $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count']); + $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count']); for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { $IndexSpecifierStreamNumber = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 2)); $offset += 2; @@ -1307,17 +1296,17 @@ class getid3_asf extends getid3_handler $thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type_text'] = $this->ASFIndexObjectIndexTypeLookup($thisfile_asf_asfindexobject['index_specifiers'][$IndexSpecifiersCounter]['index_type']); } - $ASFIndexObjectData .= fread($this->getid3->fp, 4); + $ASFIndexObjectData .= $this->fread(4); $thisfile_asf_asfindexobject['index_entry_count'] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); $offset += 4; - $ASFIndexObjectData .= fread($this->getid3->fp, 8 * $thisfile_asf_asfindexobject['index_specifiers_count']); + $ASFIndexObjectData .= $this->fread(8 * $thisfile_asf_asfindexobject['index_specifiers_count']); for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { $thisfile_asf_asfindexobject['block_positions'][$IndexSpecifiersCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 8)); $offset += 8; } - $ASFIndexObjectData .= fread($this->getid3->fp, 4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']); + $ASFIndexObjectData .= $this->fread(4 * $thisfile_asf_asfindexobject['index_specifiers_count'] * $thisfile_asf_asfindexobject['index_entry_count']); for ($IndexEntryCounter = 0; $IndexEntryCounter < $thisfile_asf_asfindexobject['index_entry_count']; $IndexEntryCounter++) { for ($IndexSpecifiersCounter = 0; $IndexSpecifiersCounter < $thisfile_asf_asfindexobject['index_specifiers_count']; $IndexSpecifiersCounter++) { $thisfile_asf_asfindexobject['offsets'][$IndexSpecifiersCounter][$IndexEntryCounter] = getid3_lib::LittleEndian2Int(substr($ASFIndexObjectData, $offset, 4)); @@ -1332,9 +1321,9 @@ class getid3_asf extends getid3_handler if ($this->GUIDname($NextObjectGUIDtext)) { $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8); } else { - $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.(ftell($this->getid3->fp) - 16 - 8); + $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8); } - fseek($this->getid3->fp, ($NextObjectSize - 16 - 8), SEEK_CUR); + $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR); break; } } @@ -1433,10 +1422,10 @@ class getid3_asf extends getid3_handler $thisfile_video['dataformat'] = (!empty($thisfile_video['dataformat']) ? $thisfile_video['dataformat'] : 'asf'); } if (!empty($thisfile_video['streams'])) { - $thisfile_video['streams']['resolution_x'] = 0; - $thisfile_video['streams']['resolution_y'] = 0; + $thisfile_video['resolution_x'] = 0; + $thisfile_video['resolution_y'] = 0; foreach ($thisfile_video['streams'] as $key => $valuearray) { - if (($valuearray['resolution_x'] > $thisfile_video['streams']['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['streams']['resolution_y'])) { + if (($valuearray['resolution_x'] > $thisfile_video['resolution_x']) || ($valuearray['resolution_y'] > $thisfile_video['resolution_y'])) { $thisfile_video['resolution_x'] = $valuearray['resolution_x']; $thisfile_video['resolution_y'] = $valuearray['resolution_y']; } @@ -1451,15 +1440,14 @@ class getid3_asf extends getid3_handler return true; } - public static function ASFCodecListObjectTypeLookup($CodecListType) { - static $ASFCodecListObjectTypeLookup = array(); - if (empty($ASFCodecListObjectTypeLookup)) { - $ASFCodecListObjectTypeLookup[0x0001] = 'Video Codec'; - $ASFCodecListObjectTypeLookup[0x0002] = 'Audio Codec'; - $ASFCodecListObjectTypeLookup[0xFFFF] = 'Unknown Codec'; - } + public static function codecListObjectTypeLookup($CodecListType) { + static $lookup = array( + 0x0001 => 'Video Codec', + 0x0002 => 'Audio Codec', + 0xFFFF => 'Unknown Codec' + ); - return (isset($ASFCodecListObjectTypeLookup[$CodecListType]) ? $ASFCodecListObjectTypeLookup[$CodecListType] : 'Invalid Codec Type'); + return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type'); } public static function KnownGUIDs() { @@ -1666,31 +1654,37 @@ class getid3_asf extends getid3_handler } public static function WMpictureTypeLookup($WMpictureType) { - static $WMpictureTypeLookup = array(); - if (empty($WMpictureTypeLookup)) { - $WMpictureTypeLookup[0x03] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Front Cover'); - $WMpictureTypeLookup[0x04] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Back Cover'); - $WMpictureTypeLookup[0x00] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'User Defined'); - $WMpictureTypeLookup[0x05] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Leaflet Page'); - $WMpictureTypeLookup[0x06] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Media Label'); - $WMpictureTypeLookup[0x07] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lead Artist'); - $WMpictureTypeLookup[0x08] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Artist'); - $WMpictureTypeLookup[0x09] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Conductor'); - $WMpictureTypeLookup[0x0A] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band'); - $WMpictureTypeLookup[0x0B] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Composer'); - $WMpictureTypeLookup[0x0C] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Lyricist'); - $WMpictureTypeLookup[0x0D] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Recording Location'); - $WMpictureTypeLookup[0x0E] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Recording'); - $WMpictureTypeLookup[0x0F] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'During Performance'); - $WMpictureTypeLookup[0x10] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Video Screen Capture'); - $WMpictureTypeLookup[0x12] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Illustration'); - $WMpictureTypeLookup[0x13] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Band Logotype'); - $WMpictureTypeLookup[0x14] = getid3_lib::iconv_fallback('ISO-8859-1', 'UTF-16LE', 'Publisher Logotype'); + static $lookup = null; + if ($lookup === null) { + $lookup = array( + 0x03 => 'Front Cover', + 0x04 => 'Back Cover', + 0x00 => 'User Defined', + 0x05 => 'Leaflet Page', + 0x06 => 'Media Label', + 0x07 => 'Lead Artist', + 0x08 => 'Artist', + 0x09 => 'Conductor', + 0x0A => 'Band', + 0x0B => 'Composer', + 0x0C => 'Lyricist', + 0x0D => 'Recording Location', + 0x0E => 'During Recording', + 0x0F => 'During Performance', + 0x10 => 'Video Screen Capture', + 0x12 => 'Illustration', + 0x13 => 'Band Logotype', + 0x14 => 'Publisher Logotype' + ); + $lookup = array_map(function($str) { + return getid3_lib::iconv_fallback('UTF-8', 'UTF-16LE', $str); + }, $lookup); } - return (isset($WMpictureTypeLookup[$WMpictureType]) ? $WMpictureTypeLookup[$WMpictureType] : ''); + + return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : ''); } - public function ASF_HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { + public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { // http://msdn.microsoft.com/en-us/library/bb643323.aspx $offset = 0; @@ -1825,7 +1819,7 @@ class getid3_asf extends getid3_handler $descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); $offset += 2; - $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); + $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); $descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); $offset += 4; @@ -1897,7 +1891,7 @@ class getid3_asf extends getid3_handler $descriptionRecord['data_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); $offset += 2; - $descriptionRecord['data_type_text'] = $this->ASFmetadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); + $descriptionRecord['data_type_text'] = self::metadataLibraryObjectDataTypeLookup($descriptionRecord['data_type']); $descriptionRecord['data_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); $offset += 4; @@ -1937,8 +1931,8 @@ class getid3_asf extends getid3_handler } - public static function ASFmetadataLibraryObjectDataTypeLookup($id) { - static $ASFmetadataLibraryObjectDataTypeLookup = array( + public static function metadataLibraryObjectDataTypeLookup($id) { + static $lookup = array( 0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters 0x0001 => 'BYTE array', // The type of the data is implementation-specific 0x0002 => 'BOOL', // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer. Only 0x0000 or 0x0001 are permitted values @@ -1947,7 +1941,7 @@ class getid3_asf extends getid3_handler 0x0005 => 'WORD', // The data is 2 bytes long and should be interpreted as a 16-bit unsigned integer 0x0006 => 'GUID', // The data is 16 bytes long and should be interpreted as a 128-bit GUID ); - return (isset($ASFmetadataLibraryObjectDataTypeLookup[$id]) ? $ASFmetadataLibraryObjectDataTypeLookup[$id] : 'invalid'); + return (isset($lookup[$id]) ? $lookup[$id] : 'invalid'); } public function ASF_WMpicture(&$data) { @@ -1964,7 +1958,7 @@ class getid3_asf extends getid3_handler $offset = 0; $WMpicture['image_type_id'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 1)); $offset += 1; - $WMpicture['image_type'] = $this->WMpictureTypeLookup($WMpicture['image_type_id']); + $WMpicture['image_type'] = self::WMpictureTypeLookup($WMpicture['image_type_id']); $WMpicture['image_size'] = getid3_lib::LittleEndian2Int(substr($data, $offset, 4)); $offset += 4; @@ -2016,4 +2010,4 @@ class getid3_asf extends getid3_handler return $string; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio-video.flv.php b/wp-includes/ID3/module.audio-video.flv.php index f9c4cf3ea0..2ee077eb26 100644 --- a/wp-includes/ID3/module.audio-video.flv.php +++ b/wp-includes/ID3/module.audio-video.flv.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // // // // FLV module by Seth Kaufman // // // @@ -38,6 +39,11 @@ // * version 0.6.1 (30 May 2011) // // prevent infinite loops in expGolombUe() // // // +// * version 0.7.0 (16 Jul 2013) // +// handle GETID3_FLV_VIDEO_VP6FLV_ALPHA // +// improved AVCSequenceParameterSetReader::readData() // +// by Xander Schouwerwou // +// // ///////////////////////////////////////////////////////////////// // // // module.audio-video.flv.php // @@ -67,38 +73,38 @@ define('H264_PROFILE_HIGH422', 122); define('H264_PROFILE_HIGH444', 144); define('H264_PROFILE_HIGH444_PREDICTIVE', 244); -class getid3_flv extends getid3_handler -{ +class getid3_flv extends getid3_handler { + + const magic = 'FLV'; + public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration public function Analyze() { $info = &$this->getid3->info; - fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + $this->fseek($info['avdataoffset']); $FLVdataLength = $info['avdataend'] - $info['avdataoffset']; - $FLVheader = fread($this->getid3->fp, 5); + $FLVheader = $this->fread(5); $info['fileformat'] = 'flv'; $info['flv']['header']['signature'] = substr($FLVheader, 0, 3); $info['flv']['header']['version'] = getid3_lib::BigEndian2Int(substr($FLVheader, 3, 1)); $TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1)); - $magic = 'FLV'; - if ($info['flv']['header']['signature'] != $magic) { - $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"'; - unset($info['flv']); - unset($info['fileformat']); + if ($info['flv']['header']['signature'] != self::magic) { + $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"'; + unset($info['flv'], $info['fileformat']); return false; } $info['flv']['header']['hasAudio'] = (bool) ($TypeFlags & 0x04); $info['flv']['header']['hasVideo'] = (bool) ($TypeFlags & 0x01); - $FrameSizeDataLength = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 4)); + $FrameSizeDataLength = getid3_lib::BigEndian2Int($this->fread(4)); $FLVheaderFrameLength = 9; if ($FrameSizeDataLength > $FLVheaderFrameLength) { - fseek($this->getid3->fp, $FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR); + $this->fseek($FrameSizeDataLength - $FLVheaderFrameLength, SEEK_CUR); } $Duration = 0; $found_video = false; @@ -108,15 +114,15 @@ class getid3_flv extends getid3_handler $tagParseCount = 0; $info['flv']['framecount'] = array('total'=>0, 'audio'=>0, 'video'=>0); $flv_framecount = &$info['flv']['framecount']; - while (((ftell($this->getid3->fp) + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime)) { - $ThisTagHeader = fread($this->getid3->fp, 16); + while ((($this->ftell() + 16) < $info['avdataend']) && (($tagParseCount++ <= $this->max_frames) || !$found_valid_meta_playtime)) { + $ThisTagHeader = $this->fread(16); $PreviousTagLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 0, 4)); $TagType = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 4, 1)); $DataLength = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 5, 3)); $Timestamp = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 8, 3)); $LastHeaderByte = getid3_lib::BigEndian2Int(substr($ThisTagHeader, 15, 1)); - $NextOffset = ftell($this->getid3->fp) - 1 + $DataLength; + $NextOffset = $this->ftell() - 1 + $DataLength; if ($Timestamp > $Duration) { $Duration = $Timestamp; } @@ -140,7 +146,7 @@ class getid3_flv extends getid3_handler $found_video = true; $info['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07; - $FLVvideoHeader = fread($this->getid3->fp, 11); + $FLVvideoHeader = $this->fread(11); if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) { // this code block contributed by: moysevichØgmail*com @@ -160,7 +166,7 @@ class getid3_flv extends getid3_handler //$spsSize = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 9, 2)); $spsSize = getid3_lib::LittleEndian2Int(substr($FLVvideoHeader, 9, 2)); // read the first SequenceParameterSet - $sps = fread($this->getid3->fp, $spsSize); + $sps = $this->fread($spsSize); if (strlen($sps) == $spsSize) { // make sure that whole SequenceParameterSet was red $spsReader = new AVCSequenceParameterSetReader($sps); $spsReader->readData(); @@ -185,19 +191,15 @@ class getid3_flv extends getid3_handler //$PictureSizeEnc <<= 1; //$info['video']['resolution_y'] = ($PictureSizeEnc & 0xFF00) >> 8; - $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2)); - $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)); - $PictureSizeEnc['x'] >>= 7; - $PictureSizeEnc['y'] >>= 7; + $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 2)) >> 7; + $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 5, 2)) >> 7; $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFF; $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFF; break; case 1: - $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3)); - $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3)); - $PictureSizeEnc['x'] >>= 7; - $PictureSizeEnc['y'] >>= 7; + $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 4, 3)) >> 7; + $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 3)) >> 7; $info['video']['resolution_x'] = $PictureSizeEnc['x'] & 0xFFFF; $info['video']['resolution_y'] = $PictureSizeEnc['y'] & 0xFFFF; break; @@ -233,8 +235,22 @@ class getid3_flv extends getid3_handler break; } + + } elseif ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_VP6FLV_ALPHA) { + + /* contributed by schouwerwouØgmail*com */ + if (!isset($info['video']['resolution_x'])) { // only when meta data isn't set + $PictureSizeEnc['x'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 6, 2)); + $PictureSizeEnc['y'] = getid3_lib::BigEndian2Int(substr($FLVvideoHeader, 7, 2)); + $info['video']['resolution_x'] = ($PictureSizeEnc['x'] & 0xFF) << 3; + $info['video']['resolution_y'] = ($PictureSizeEnc['y'] & 0xFF) << 3; + } + /* end schouwerwouØgmail*com */ + + } + if (!empty($info['video']['resolution_x']) && !empty($info['video']['resolution_y'])) { + $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y']; } - $info['video']['pixel_aspect_ratio'] = $info['video']['resolution_x'] / $info['video']['resolution_y']; } break; @@ -242,8 +258,8 @@ class getid3_flv extends getid3_handler case GETID3_FLV_TAG_META: if (!$found_meta) { $found_meta = true; - fseek($this->getid3->fp, -1, SEEK_CUR); - $datachunk = fread($this->getid3->fp, $DataLength); + $this->fseek(-1, SEEK_CUR); + $datachunk = $this->fread($DataLength); $AMFstream = new AMFStream($datachunk); $reader = new AMFReader($AMFstream); $eventName = $reader->readData(); @@ -279,7 +295,7 @@ class getid3_flv extends getid3_handler // noop break; } - fseek($this->getid3->fp, $NextOffset, SEEK_SET); + $this->fseek($NextOffset); } $info['playtime_seconds'] = $Duration / 1000; @@ -288,16 +304,16 @@ class getid3_flv extends getid3_handler } if ($info['flv']['header']['hasAudio']) { - $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['audio']['audioFormat']); - $info['audio']['sample_rate'] = $this->FLVaudioRate($info['flv']['audio']['audioRate']); - $info['audio']['bits_per_sample'] = $this->FLVaudioBitDepth($info['flv']['audio']['audioSampleSize']); + $info['audio']['codec'] = self::audioFormatLookup($info['flv']['audio']['audioFormat']); + $info['audio']['sample_rate'] = self::audioRateLookup($info['flv']['audio']['audioRate']); + $info['audio']['bits_per_sample'] = self::audioBitDepthLookup($info['flv']['audio']['audioSampleSize']); $info['audio']['channels'] = $info['flv']['audio']['audioType'] + 1; // 0=mono,1=stereo $info['audio']['lossless'] = ($info['flv']['audio']['audioFormat'] ? false : true); // 0=uncompressed $info['audio']['dataformat'] = 'flv'; } if (!empty($info['flv']['header']['hasVideo'])) { - $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['video']['videoCodec']); + $info['video']['codec'] = self::videoCodecLookup($info['flv']['video']['videoCodec']); $info['video']['dataformat'] = 'flv'; $info['video']['lossless'] = false; } @@ -308,17 +324,17 @@ class getid3_flv extends getid3_handler $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; } if (isset($info['flv']['meta']['onMetaData']['audiocodecid'])) { - $info['audio']['codec'] = $this->FLVaudioFormat($info['flv']['meta']['onMetaData']['audiocodecid']); + $info['audio']['codec'] = self::audioFormatLookup($info['flv']['meta']['onMetaData']['audiocodecid']); } if (isset($info['flv']['meta']['onMetaData']['videocodecid'])) { - $info['video']['codec'] = $this->FLVvideoCodec($info['flv']['meta']['onMetaData']['videocodecid']); + $info['video']['codec'] = self::videoCodecLookup($info['flv']['meta']['onMetaData']['videocodecid']); } return true; } - public function FLVaudioFormat($id) { - $FLVaudioFormat = array( + public static function audioFormatLookup($id) { + static $lookup = array( 0 => 'Linear PCM, platform endian', 1 => 'ADPCM', 2 => 'mp3', @@ -330,35 +346,35 @@ class getid3_flv extends getid3_handler 8 => 'G.711 mu-law logarithmic PCM', 9 => 'reserved', 10 => 'AAC', - 11 => false, // unknown? + 11 => 'Speex', 12 => false, // unknown? 13 => false, // unknown? 14 => 'mp3 8kHz', 15 => 'Device-specific sound', ); - return (isset($FLVaudioFormat[$id]) ? $FLVaudioFormat[$id] : false); + return (isset($lookup[$id]) ? $lookup[$id] : false); } - public function FLVaudioRate($id) { - $FLVaudioRate = array( + public static function audioRateLookup($id) { + static $lookup = array( 0 => 5500, 1 => 11025, 2 => 22050, 3 => 44100, ); - return (isset($FLVaudioRate[$id]) ? $FLVaudioRate[$id] : false); + return (isset($lookup[$id]) ? $lookup[$id] : false); } - public function FLVaudioBitDepth($id) { - $FLVaudioBitDepth = array( + public static function audioBitDepthLookup($id) { + static $lookup = array( 0 => 8, 1 => 16, ); - return (isset($FLVaudioBitDepth[$id]) ? $FLVaudioBitDepth[$id] : false); + return (isset($lookup[$id]) ? $lookup[$id] : false); } - public function FLVvideoCodec($id) { - $FLVvideoCodec = array( + public static function videoCodecLookup($id) { + static $lookup = array( GETID3_FLV_VIDEO_H263 => 'Sorenson H.263', GETID3_FLV_VIDEO_SCREEN => 'Screen video', GETID3_FLV_VIDEO_VP6FLV => 'On2 VP6', @@ -366,7 +382,7 @@ class getid3_flv extends getid3_handler GETID3_FLV_VIDEO_SCREENV2 => 'Screen video v2', GETID3_FLV_VIDEO_H264 => 'Sorenson H.264', ); - return (isset($FLVvideoCodec[$id]) ? $FLVvideoCodec[$id] : false); + return (isset($lookup[$id]) ? $lookup[$id] : false); } } @@ -374,7 +390,7 @@ class AMFStream { public $bytes; public $pos; - public function AMFStream(&$bytes) { + public function __construct(&$bytes) { $this->bytes =& $bytes; $this->pos = 0; } @@ -457,7 +473,7 @@ class AMFStream { class AMFReader { public $stream; - public function AMFReader(&$stream) { + public function __construct(&$stream) { $this->stream =& $stream; } @@ -619,60 +635,60 @@ class AVCSequenceParameterSetReader { public $width; public $height; - public function AVCSequenceParameterSetReader($sps) { + public function __construct($sps) { $this->sps = $sps; } public function readData() { $this->skipBits(8); $this->skipBits(8); - $profile = $this->getBits(8); // read profile - $this->skipBits(16); - $this->expGolombUe(); // read sps id - if (in_array($profile, array(H264_PROFILE_HIGH, H264_PROFILE_HIGH10, H264_PROFILE_HIGH422, H264_PROFILE_HIGH444, H264_PROFILE_HIGH444_PREDICTIVE))) { - if ($this->expGolombUe() == 3) { - $this->skipBits(1); - } - $this->expGolombUe(); - $this->expGolombUe(); - $this->skipBits(1); - if ($this->getBit()) { - for ($i = 0; $i < 8; $i++) { - if ($this->getBit()) { - $size = $i < 6 ? 16 : 64; - $lastScale = 8; - $nextScale = 8; - for ($j = 0; $j < $size; $j++) { - if ($nextScale != 0) { - $deltaScale = $this->expGolombUe(); - $nextScale = ($lastScale + $deltaScale + 256) % 256; - } - if ($nextScale != 0) { - $lastScale = $nextScale; - } - } - } + $profile = $this->getBits(8); // read profile + if ($profile > 0) { + $this->skipBits(8); + $level_idc = $this->getBits(8); // level_idc + $this->expGolombUe(); // seq_parameter_set_id // sps + $this->expGolombUe(); // log2_max_frame_num_minus4 + $picOrderType = $this->expGolombUe(); // pic_order_cnt_type + if ($picOrderType == 0) { + $this->expGolombUe(); // log2_max_pic_order_cnt_lsb_minus4 + } elseif ($picOrderType == 1) { + $this->skipBits(1); // delta_pic_order_always_zero_flag + $this->expGolombSe(); // offset_for_non_ref_pic + $this->expGolombSe(); // offset_for_top_to_bottom_field + $num_ref_frames_in_pic_order_cnt_cycle = $this->expGolombUe(); // num_ref_frames_in_pic_order_cnt_cycle + for ($i = 0; $i < $num_ref_frames_in_pic_order_cnt_cycle; $i++) { + $this->expGolombSe(); // offset_for_ref_frame[ i ] } } - } - $this->expGolombUe(); - $pocType = $this->expGolombUe(); - if ($pocType == 0) { - $this->expGolombUe(); - } elseif ($pocType == 1) { - $this->skipBits(1); - $this->expGolombSe(); - $this->expGolombSe(); - $pocCycleLength = $this->expGolombUe(); - for ($i = 0; $i < $pocCycleLength; $i++) { - $this->expGolombSe(); + $this->expGolombUe(); // num_ref_frames + $this->skipBits(1); // gaps_in_frame_num_value_allowed_flag + $pic_width_in_mbs_minus1 = $this->expGolombUe(); // pic_width_in_mbs_minus1 + $pic_height_in_map_units_minus1 = $this->expGolombUe(); // pic_height_in_map_units_minus1 + + $frame_mbs_only_flag = $this->getBits(1); // frame_mbs_only_flag + if ($frame_mbs_only_flag == 0) { + $this->skipBits(1); // mb_adaptive_frame_field_flag } + $this->skipBits(1); // direct_8x8_inference_flag + $frame_cropping_flag = $this->getBits(1); // frame_cropping_flag + + $frame_crop_left_offset = 0; + $frame_crop_right_offset = 0; + $frame_crop_top_offset = 0; + $frame_crop_bottom_offset = 0; + + if ($frame_cropping_flag) { + $frame_crop_left_offset = $this->expGolombUe(); // frame_crop_left_offset + $frame_crop_right_offset = $this->expGolombUe(); // frame_crop_right_offset + $frame_crop_top_offset = $this->expGolombUe(); // frame_crop_top_offset + $frame_crop_bottom_offset = $this->expGolombUe(); // frame_crop_bottom_offset + } + $this->skipBits(1); // vui_parameters_present_flag + // etc + + $this->width = (($pic_width_in_mbs_minus1 + 1) * 16) - ($frame_crop_left_offset * 2) - ($frame_crop_right_offset * 2); + $this->height = ((2 - $frame_mbs_only_flag) * ($pic_height_in_map_units_minus1 + 1) * 16) - ($frame_crop_top_offset * 2) - ($frame_crop_bottom_offset * 2); } - $this->expGolombUe(); - $this->skipBits(1); - $this->width = ($this->expGolombUe() + 1) * 16; - $heightMap = $this->expGolombUe() + 1; - $this->height = (2 - $this->getBit()) * $heightMap * 16; } public function skipBits($bits) { @@ -726,4 +742,4 @@ class AVCSequenceParameterSetReader { public function getHeight() { return $this->height; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio-video.matroska.php b/wp-includes/ID3/module.audio-video.matroska.php index fb0af7221e..79d0b7debf 100644 --- a/wp-includes/ID3/module.audio-video.matroska.php +++ b/wp-includes/ID3/module.audio-video.matroska.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -281,10 +282,8 @@ class getid3_matroska extends getid3_handler switch ($trackarray['CodecID']) { case 'V_MS/VFW/FOURCC': - if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) { - $this->warning('Unable to parse codec private data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"'); - break; - } + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); + $parsed = getid3_riff::ParseBITMAPINFOHEADER($trackarray['CodecPrivate']); $track_info['codec'] = getid3_riff::fourccLookup($parsed['fourcc']); $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed; @@ -335,10 +334,7 @@ class getid3_matroska extends getid3_handler case 'A_MPEG/L3': case 'A_MPEG/L2': case 'A_FLAC': - if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, false)) { - $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.'.$track_info['dataformat'].'.php"'); - break; - } + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true); if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) { $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set'); @@ -385,10 +381,6 @@ class getid3_matroska extends getid3_handler } if (!empty($getid3_temp->info['warning'])) { foreach ($getid3_temp->info['warning'] as $newerror) { - if ($track_info['dataformat'] == 'mp3' && preg_match('/^Probable truncated file: expecting \d+ bytes of audio data, only found \d+ \(short by \d+ bytes\)$/', $newerror)) { - // LAME/Xing header is probably set, but audio data is chunked into Matroska file and near-impossible to verify if audio stream is complete, so ignore useless warning - continue; - } $this->warning($class.'() says: ['.$newerror.']'); } } @@ -400,7 +392,7 @@ class getid3_matroska extends getid3_handler case 'A_AAC/MPEG2/LC/SBR': case 'A_AAC/MPEG4/LC': case 'A_AAC/MPEG4/LC/SBR': - $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated'); + $this->warning($trackarray['CodecID'].' audio data contains no header, audio/video bitrates can\'t be calculated'); break; case 'A_VORBIS': @@ -415,10 +407,7 @@ class getid3_matroska extends getid3_handler } $vorbis_offset -= 1; - if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, false)) { - $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio.ogg.php"'); - break; - } + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true); // create temp instance $getid3_temp = new getID3(); @@ -455,10 +444,7 @@ class getid3_matroska extends getid3_handler break; case 'A_MS/ACM': - if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, false)) { - $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because cannot include "module.audio-video.riff.php"'); - break; - } + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']); foreach ($parsed as $key => $value) { @@ -515,7 +501,6 @@ class getid3_matroska extends getid3_handler switch ($top_element['id']) { case EBML_ID_EBML: - $info['fileformat'] = 'matroska'; $info['matroska']['header']['offset'] = $top_element['offset']; $info['matroska']['header']['length'] = $top_element['length']; @@ -534,6 +519,7 @@ class getid3_matroska extends getid3_handler case EBML_ID_DOCTYPE: $element_data['data'] = getid3_lib::trimNullByte($element_data['data']); $info['matroska']['doctype'] = $element_data['data']; + $info['fileformat'] = $element_data['data']; break; default: @@ -1526,8 +1512,8 @@ class getid3_matroska extends getid3_handler $CodecIDlist['V_MPEG4/ISO/AVC'] = 'h264'; $CodecIDlist['V_MPEG4/ISO/SP'] = 'mpeg4'; $CodecIDlist['V_VP8'] = 'vp8'; - $CodecIDlist['V_MS/VFW/FOURCC'] = 'riff'; - $CodecIDlist['A_MS/ACM'] = 'riff'; + $CodecIDlist['V_MS/VFW/FOURCC'] = 'vcm'; // Microsoft (TM) Video Codec Manager (VCM) + $CodecIDlist['A_MS/ACM'] = 'acm'; // Microsoft (TM) Audio Codec Manager (ACM) } return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid); } @@ -1762,4 +1748,4 @@ class getid3_matroska extends getid3_handler return $info; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio-video.quicktime.php b/wp-includes/ID3/module.audio-video.quicktime.php index 1b5ad5f042..03f7a922f3 100644 --- a/wp-includes/ID3/module.audio-video.quicktime.php +++ b/wp-includes/ID3/module.audio-video.quicktime.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -30,7 +31,7 @@ class getid3_quicktime extends getid3_handler $info['quicktime']['hinting'] = false; $info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present - fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + $this->fseek($info['avdataoffset']); $offset = 0; $atomcounter = 0; @@ -40,15 +41,15 @@ class getid3_quicktime extends getid3_handler $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions'; break; } - fseek($this->getid3->fp, $offset, SEEK_SET); - $AtomHeader = fread($this->getid3->fp, 8); + $this->fseek($offset); + $AtomHeader = $this->fread(8); $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); $atomname = substr($AtomHeader, 4, 4); // 64-bit MOV patch by jlegateØktnc*com if ($atomsize == 1) { - $atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8)); + $atomsize = getid3_lib::BigEndian2Int($this->fread(8)); } $info['quicktime'][$atomname]['name'] = $atomname; @@ -66,58 +67,8 @@ class getid3_quicktime extends getid3_handler // to read user data atoms, you should allow for the terminating 0. break; } - switch ($atomname) { - case 'mdat': // Media DATa atom - // 'mdat' contains the actual data for the audio/video - if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { - - $info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8; - $OldAVDataEnd = $info['avdataend']; - $info['avdataend'] = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; - - $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename); - $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; - $getid3_temp->info['avdataend'] = $info['avdataend']; - $getid3_mp3 = new getid3_mp3($getid3_temp); - if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) { - $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); - if (!empty($getid3_temp->info['warning'])) { - foreach ($getid3_temp->info['warning'] as $value) { - $info['warning'][] = $value; - } - } - if (!empty($getid3_temp->info['mpeg'])) { - $info['mpeg'] = $getid3_temp->info['mpeg']; - if (isset($info['mpeg']['audio'])) { - $info['audio']['dataformat'] = 'mp3'; - $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); - $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; - $info['audio']['channels'] = $info['mpeg']['audio']['channels']; - $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; - $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); - $info['bitrate'] = $info['audio']['bitrate']; - } - } - } - unset($getid3_mp3, $getid3_temp); - $info['avdataend'] = $OldAVDataEnd; - unset($OldAVDataEnd); - - } - break; - - case 'free': // FREE space atom - case 'skip': // SKIP atom - case 'wide': // 64-bit expansion placeholder atom - // 'free', 'skip' and 'wide' are just padding, contains no useful data at all - break; - - default: - $atomHierarchy = array(); - $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); - break; - } + $atomHierarchy = array(); + $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, round($this->getid3->memory_limit / 2))), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); $offset += $atomsize; $atomcounter++; @@ -172,15 +123,12 @@ class getid3_quicktime extends getid3_handler $info = &$this->getid3->info; - //$atom_parent = array_pop($atomHierarchy); - $atom_parent = end($atomHierarchy); // http://www.getid3.org/phpBB3/viewtopic.php?t=1717 + $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717 array_push($atomHierarchy, $atomname); $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); $atom_structure['name'] = $atomname; $atom_structure['size'] = $atomsize; $atom_structure['offset'] = $baseoffset; -//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'
'; -//echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'

'; switch ($atomname) { case 'moov': // MOVie container atom case 'trak': // TRAcK container atom @@ -200,27 +148,27 @@ class getid3_quicktime extends getid3_handler break; case 'ilst': // Item LiST container atom - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - - // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted - $allnumericnames = true; - foreach ($atom_structure['subatoms'] as $subatomarray) { - if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { - $allnumericnames = false; - break; - } - } - if ($allnumericnames) { - $newData = array(); + if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { + // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted + $allnumericnames = true; foreach ($atom_structure['subatoms'] as $subatomarray) { - foreach ($subatomarray['subatoms'] as $newData_subatomarray) { - unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); - $newData[$subatomarray['name']] = $newData_subatomarray; + if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { + $allnumericnames = false; break; } } - $atom_structure['data'] = $newData; - unset($atom_structure['subatoms']); + if ($allnumericnames) { + $newData = array(); + foreach ($atom_structure['subatoms'] as $subatomarray) { + foreach ($subatomarray['subatoms'] as $newData_subatomarray) { + unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); + $newData[$subatomarray['name']] = $newData_subatomarray; + break; + } + } + $atom_structure['data'] = $newData; + unset($atom_structure['subatoms']); + } } break; @@ -308,46 +256,46 @@ class getid3_quicktime extends getid3_handler case 'geID': case 'plID': case 'sfID': // iTunes store country - case '©alb': // ALBum - case '©art': // ARTist - case '©ART': - case '©aut': - case '©cmt': // CoMmenT - case '©com': // COMposer - case '©cpy': - case '©day': // content created year - case '©dir': - case '©ed1': - case '©ed2': - case '©ed3': - case '©ed4': - case '©ed5': - case '©ed6': - case '©ed7': - case '©ed8': - case '©ed9': - case '©enc': - case '©fmt': - case '©gen': // GENre - case '©grp': // GRouPing - case '©hst': - case '©inf': - case '©lyr': // LYRics - case '©mak': - case '©mod': - case '©nam': // full NAMe - case '©ope': - case '©PRD': - case '©prd': - case '©prf': - case '©req': - case '©src': - case '©swr': - case '©too': // encoder - case '©trk': // TRacK - case '©url': - case '©wrn': - case '©wrt': // WRiTer + case "\xA9".'alb': // ALBum + case "\xA9".'art': // ARTist + case "\xA9".'ART': + case "\xA9".'aut': + case "\xA9".'cmt': // CoMmenT + case "\xA9".'com': // COMposer + case "\xA9".'cpy': + case "\xA9".'day': // content created year + case "\xA9".'dir': + case "\xA9".'ed1': + case "\xA9".'ed2': + case "\xA9".'ed3': + case "\xA9".'ed4': + case "\xA9".'ed5': + case "\xA9".'ed6': + case "\xA9".'ed7': + case "\xA9".'ed8': + case "\xA9".'ed9': + case "\xA9".'enc': + case "\xA9".'fmt': + case "\xA9".'gen': // GENre + case "\xA9".'grp': // GRouPing + case "\xA9".'hst': + case "\xA9".'inf': + case "\xA9".'lyr': // LYRics + case "\xA9".'mak': + case "\xA9".'mod': + case "\xA9".'nam': // full NAMe + case "\xA9".'ope': + case "\xA9".'PRD': + case "\xA9".'prd': + case "\xA9".'prf': + case "\xA9".'req': + case "\xA9".'src': + case "\xA9".'swr': + case "\xA9".'too': // encoder + case "\xA9".'trk': // TRacK + case "\xA9".'url': + case "\xA9".'wrn': + case "\xA9".'wrt': // WRiTer case '----': // itunes specific if ($atom_parent == 'udta') { // User data atom handler @@ -370,7 +318,7 @@ class getid3_quicktime extends getid3_handler $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); if ($boxsmallsize <= 1) { - $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset); + $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset); $atom_structure['data'] = null; $atomoffset = strlen($atom_data); break; @@ -380,7 +328,7 @@ class getid3_quicktime extends getid3_handler $atom_structure['data'] = $boxsmalldata; break; default: - $info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset; + $info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset; $atom_structure['data'] = $atom_data; break; } @@ -392,7 +340,7 @@ class getid3_quicktime extends getid3_handler $boxtype = substr($atom_data, $atomoffset + 4, 4); $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); if ($boxsize <= 1) { - $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset); + $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset); $atom_structure['data'] = null; $atomoffset = strlen($atom_data); break; @@ -409,7 +357,7 @@ class getid3_quicktime extends getid3_handler $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); switch ($atom_structure['flags_raw']) { - case 0: // data flag + case 0: // data flag case 21: // tmpo/cpil flag switch ($atomname) { case 'cpil': @@ -460,17 +408,27 @@ class getid3_quicktime extends getid3_handler } break; - case 1: // text flag + case 1: // text flag case 13: // image flag default: $atom_structure['data'] = substr($boxdata, 8); + if ($atomname == 'covr') { + // not a foolproof check, but better than nothing + if (preg_match('#^\xFF\xD8\xFF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/jpeg'; + } elseif (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/png'; + } elseif (preg_match('#^GIF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/gif'; + } + } break; } break; default: - $info['warning'][] = 'Unknown QuickTime box type: "'.getid3_lib::PrintHexBytes($boxtype).'" at offset '.$baseoffset; + $info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset; $atom_structure['data'] = $atom_data; } @@ -840,7 +798,12 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ $sttsEntriesDataOffset = 8; //$FrameRateCalculatorArray = array(); $frames_count = 0; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + + $max_stts_entries_to_scan = min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']); + if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { + $info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($this->getid3->memory_limit / 1048576).'MB).'; + } + for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); $sttsEntriesDataOffset += 4; $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); @@ -1086,8 +1049,8 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ case 'sync': // SYNChronization atom case 'scpt': // tranSCriPT atom case 'ssrc': // non-primary SouRCe atom - for ($i = 0; $i < (strlen($atom_data) % 4); $i++) { - $atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4)); + for ($i = 0; $i < strlen($atom_data); $i += 4) { + @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); } break; @@ -1260,10 +1223,76 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ break; case 'mdat': // Media DATa atom + // 'mdat' contains the actual data for the audio/video, possibly also subtitles + +/* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */ + + // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?) + $mdat_offset = 0; + while (true) { + if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') { + $mdat_offset += 8; + } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') { + $mdat_offset += 8; + } else { + break; + } + } + + // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field + while (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) + && ($chapter_string_length < 1000) + && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2)) + && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) { + $mdat_offset += (2 + $chapter_string_length); + @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0]; + } + + + + if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { + + $info['avdataoffset'] = $atom_structure['offset'] + 8; // $info['quicktime'][$atomname]['offset'] + 8; + $OldAVDataEnd = $info['avdataend']; + $info['avdataend'] = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; + + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; + $getid3_temp->info['avdataend'] = $info['avdataend']; + $getid3_mp3 = new getid3_mp3($getid3_temp); + if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) { + $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $value) { + $info['warning'][] = $value; + } + } + if (!empty($getid3_temp->info['mpeg'])) { + $info['mpeg'] = $getid3_temp->info['mpeg']; + if (isset($info['mpeg']['audio'])) { + $info['audio']['dataformat'] = 'mp3'; + $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + $info['bitrate'] = $info['audio']['bitrate']; + } + } + } + unset($getid3_mp3, $getid3_temp); + $info['avdataend'] = $OldAVDataEnd; + unset($OldAVDataEnd); + + } + + unset($mdat_offset, $chapter_string_length, $chapter_matches); + break; + case 'free': // FREE space atom case 'skip': // SKIP atom case 'wide': // 64-bit expansion placeholder atom - // 'mdat' data is too big to deal with, contains no useful metadata // 'free', 'skip' and 'wide' are just padding, contains no useful data at all // When writing QuickTime files, it is sometimes necessary to update an atom's size. @@ -1329,7 +1358,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ //$atom_structure['data'] = $atom_data; break; - case '©xyz': // GPS latitude+longitude+altitude + case "\xA9".'xyz': // GPS latitude+longitude+altitude $atom_structure['data'] = $atom_data; if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) { @list($all, $latitude, $longitude, $altitude) = $matches; @@ -1358,16 +1387,12 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); } break; - case 'NCHD': // MakerNoteVersion - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html - $atom_structure['data'] = $atom_data; - break; - case 'NCTG': // NikonTags - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); break; - case 'NCDB': // NikonTags - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html $atom_structure['data'] = $atom_data; break; @@ -1391,7 +1416,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ break; default: - $info['warning'][] = 'Unknown QuickTime atom type: "'.$atomname.'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset; + $info['warning'][] = 'Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset; $atom_structure['data'] = $atom_data; break; } @@ -2086,58 +2111,58 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
// // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -26,8 +27,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE_ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true); getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); -class getid3_riff extends getid3_handler -{ +class getid3_riff extends getid3_handler { + + protected $container = 'riff'; // default public function Analyze() { $info = &$this->getid3->info; @@ -58,7 +60,8 @@ class getid3_riff extends getid3_handler switch ($RIFFtype) { case 'FORM': // AIFF, AIFC - $info['fileformat'] = 'aiff'; + //$info['fileformat'] = 'aiff'; + $this->container = 'aiff'; $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); break; @@ -66,13 +69,18 @@ class getid3_riff extends getid3_handler case 'RIFF': // AVI, WAV, etc case 'SDSS': // SDSS is identical to RIFF, just renamed. Used by SmartSound QuickTracks (www.smartsound.com) case 'RMP3': // RMP3 is identical to RIFF, just renamed. Used by [unknown program] when creating RIFF-MP3s - $info['fileformat'] = 'riff'; + //$info['fileformat'] = 'riff'; + $this->container = 'riff'; $thisfile_riff['header_size'] = $this->EitherEndian2Int($RIFFsize); if ($RIFFsubtype == 'RMP3') { // RMP3 is identical to WAVE, just renamed. Used by [unknown program] when creating RIFF-MP3s $RIFFsubtype = 'WAVE'; } - $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); + if ($RIFFsubtype != 'AMV ') { + // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size + // Handled separately in ParseRIFFAMV() + $thisfile_riff[$RIFFsubtype] = $this->ParseRIFF($offset, ($offset + $thisfile_riff['header_size'] - 4)); + } if (($info['avdataend'] - $info['filesize']) == 1) { // LiteWave appears to incorrectly *not* pad actual output file // to nearest WORD boundary so may appear to be short by one @@ -110,16 +118,19 @@ class getid3_riff extends getid3_handler $nextRIFFoffset = $chunkdata['offset'] + $chunkdata['size']; switch ($nextRIFFheaderID) { - case 'RIFF': $chunkdata['chunks'] = $this->ParseRIFF($chunkdata['offset'] + 4, $nextRIFFoffset); - if (!isset($thisfile_riff[$nextRIFFtype])) { $thisfile_riff[$nextRIFFtype] = array(); } $thisfile_riff[$nextRIFFtype][] = $chunkdata; break; + case 'AMV ': + unset($info['riff']); + $info['amv'] = $this->ParseRIFFAMV($chunkdata['offset'] + 4, $nextRIFFoffset); + break; + case 'JUNK': // ignore $thisfile_riff[$nextRIFFheaderID][] = $chunkdata; @@ -152,13 +163,17 @@ class getid3_riff extends getid3_handler default: $this->error('Cannot parse RIFF (this is maybe not a RIFF / WAV / AVI file?) - expecting "FORM|RIFF|SDSS|RMP3" found "'.$RIFFsubtype.'" instead'); - unset($info['fileformat']); + //unset($info['fileformat']); return false; } $streamindex = 0; switch ($RIFFsubtype) { + + // http://en.wikipedia.org/wiki/Wav case 'WAVE': + $info['fileformat'] = 'wav'; + if (empty($thisfile_audio['bitrate_mode'])) { $thisfile_audio['bitrate_mode'] = 'cbr'; } @@ -588,10 +603,13 @@ class getid3_riff extends getid3_handler } break; + // http://en.wikipedia.org/wiki/Audio_Video_Interleave case 'AVI ': + $info['fileformat'] = 'avi'; + $info['mime_type'] = 'video/avi'; + $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably $thisfile_video['dataformat'] = 'avi'; - $info['mime_type'] = 'video/avi'; if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8; @@ -825,7 +843,7 @@ class getid3_riff extends getid3_handler switch ($strhfccType) { case 'vids': - $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($info['fileformat'] == 'riff')); + $thisfile_riff_raw_strf_strhfccType_streamindex = self::ParseBITMAPINFOHEADER(substr($strfData, 0, 40), ($this->container == 'riff')); $thisfile_video['bits_per_sample'] = $thisfile_riff_raw_strf_strhfccType_streamindex['biBitCount']; if ($thisfile_riff_video_current['codec'] == 'DV') { @@ -875,11 +893,28 @@ class getid3_riff extends getid3_handler } break; + + case 'AMV ': + $info['fileformat'] = 'amv'; + $info['mime_type'] = 'video/amv'; + + $thisfile_video['bitrate_mode'] = 'vbr'; // it's MJPEG, presumably contant-quality encoding, thereby VBR + $thisfile_video['dataformat'] = 'mjpeg'; + $thisfile_video['codec'] = 'mjpeg'; + $thisfile_video['lossless'] = false; + $thisfile_video['bits_per_sample'] = 24; + + $thisfile_audio['dataformat'] = 'adpcm'; + $thisfile_audio['lossless'] = false; + break; + + + // http://en.wikipedia.org/wiki/CD-DA case 'CDDA': - $thisfile_audio['bitrate_mode'] = 'cbr'; + $info['fileformat'] = 'cda'; + unset($info['mime_type']); + $thisfile_audio_dataformat = 'cda'; - $thisfile_audio['lossless'] = true; - unset($info['mime_type']); $info['avdataoffset'] = 44; @@ -901,6 +936,7 @@ class getid3_riff extends getid3_handler $info['playtime_seconds'] = $thisfile_riff_CDDA_fmt_0['playtime_seconds']; // hardcoded data for CD-audio + $thisfile_audio['lossless'] = true; $thisfile_audio['sample_rate'] = 44100; $thisfile_audio['channels'] = 2; $thisfile_audio['bits_per_sample'] = 16; @@ -909,13 +945,15 @@ class getid3_riff extends getid3_handler } break; - + // http://en.wikipedia.org/wiki/AIFF case 'AIFF': case 'AIFC': + $info['fileformat'] = 'aiff'; + $info['mime_type'] = 'audio/x-aiff'; + $thisfile_audio['bitrate_mode'] = 'cbr'; $thisfile_audio_dataformat = 'aiff'; $thisfile_audio['lossless'] = true; - $info['mime_type'] = 'audio/x-aiff'; if (isset($thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'])) { $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['SSND'][0]['offset'] + 8; @@ -1028,12 +1066,15 @@ class getid3_riff extends getid3_handler */ break; + // http://en.wikipedia.org/wiki/8SVX case '8SVX': + $info['fileformat'] = '8svx'; + $info['mime_type'] = 'audio/8svx'; + $thisfile_audio['bitrate_mode'] = 'cbr'; $thisfile_audio_dataformat = '8svx'; $thisfile_audio['bits_per_sample'] = 8; $thisfile_audio['channels'] = 1; // overridden below, if need be - $info['mime_type'] = 'audio/x-aiff'; if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; @@ -1108,31 +1149,31 @@ class getid3_riff extends getid3_handler } break; - case 'CDXA': - $info['mime_type'] = 'video/mpeg'; + $info['fileformat'] = 'vcd'; // Asume Video CD + $info['mime_type'] = 'video/mpeg'; + if (!empty($thisfile_riff['CDXA']['data'][0]['size'])) { - if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, false)) { - $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename); - $getid3_mpeg = new getid3_mpeg($getid3_temp); - $getid3_mpeg->Analyze(); - if (empty($getid3_temp->info['error'])) { - $info['audio'] = $getid3_temp->info['audio']; - $info['video'] = $getid3_temp->info['video']; - $info['mpeg'] = $getid3_temp->info['mpeg']; - $info['warning'] = $getid3_temp->info['warning']; - } - unset($getid3_temp, $getid3_mpeg); + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true); + + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_mpeg = new getid3_mpeg($getid3_temp); + $getid3_mpeg->Analyze(); + if (empty($getid3_temp->info['error'])) { + $info['audio'] = $getid3_temp->info['audio']; + $info['video'] = $getid3_temp->info['video']; + $info['mpeg'] = $getid3_temp->info['mpeg']; + $info['warning'] = $getid3_temp->info['warning']; } + unset($getid3_temp, $getid3_mpeg); } break; default: $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead'; - unset($info['fileformat']); - break; + //unset($info['fileformat']); } switch ($RIFFsubtype) { @@ -1150,6 +1191,7 @@ class getid3_riff extends getid3_handler if (isset($thisfile_riff[$RIFFsubtype]['id3 '])) { getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); + $getid3_temp = new getID3(); $getid3_temp->openfile($this->getid3->filename); $getid3_id3v2 = new getid3_id3v2($getid3_temp); @@ -1278,6 +1320,115 @@ class getid3_riff extends getid3_handler return true; } + public function ParseRIFFAMV($startoffset, $maxoffset) { + // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size + + // https://code.google.com/p/amv-codec-tools/wiki/AmvDocumentation + //typedef struct _amvmainheader { + //FOURCC fcc; // 'amvh' + //DWORD cb; + //DWORD dwMicroSecPerFrame; + //BYTE reserve[28]; + //DWORD dwWidth; + //DWORD dwHeight; + //DWORD dwSpeed; + //DWORD reserve0; + //DWORD reserve1; + //BYTE bTimeSec; + //BYTE bTimeMin; + //WORD wTimeHour; + //} AMVMAINHEADER; + + $info = &$this->getid3->info; + $RIFFchunk = false; + + try { + + $this->fseek($startoffset); + $maxoffset = min($maxoffset, $info['avdataend']); + $AMVheader = $this->fread(284); + if (substr($AMVheader, 0, 8) != 'hdrlamvh') { + throw new Exception('expecting "hdrlamv" at offset '.($startoffset + 0).', found "'.substr($AMVheader, 0, 8).'"'); + } + if (substr($AMVheader, 8, 4) != "\x38\x00\x00\x00") { // "amvh" chunk size, hardcoded to 0x38 = 56 bytes + throw new Exception('expecting "0x38000000" at offset '.($startoffset + 8).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 8, 4)).'"'); + } + $RIFFchunk = array(); + $RIFFchunk['amvh']['us_per_frame'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 12, 4)); + $RIFFchunk['amvh']['reserved28'] = substr($AMVheader, 16, 28); // null? reserved? + $RIFFchunk['amvh']['resolution_x'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 44, 4)); + $RIFFchunk['amvh']['resolution_y'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 48, 4)); + $RIFFchunk['amvh']['frame_rate_int'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 52, 4)); + $RIFFchunk['amvh']['reserved0'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 56, 4)); // 1? reserved? + $RIFFchunk['amvh']['reserved1'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 60, 4)); // 0? reserved? + $RIFFchunk['amvh']['runtime_sec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 64, 1)); + $RIFFchunk['amvh']['runtime_min'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 65, 1)); + $RIFFchunk['amvh']['runtime_hrs'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 66, 2)); + + $info['video']['frame_rate'] = 1000000 / $RIFFchunk['amvh']['us_per_frame']; + $info['video']['resolution_x'] = $RIFFchunk['amvh']['resolution_x']; + $info['video']['resolution_y'] = $RIFFchunk['amvh']['resolution_y']; + $info['playtime_seconds'] = ($RIFFchunk['amvh']['runtime_hrs'] * 3600) + ($RIFFchunk['amvh']['runtime_min'] * 60) + $RIFFchunk['amvh']['runtime_sec']; + + // the rest is all hardcoded(?) and does not appear to be useful until you get to audio info at offset 256, even then everything is probably hardcoded + + if (substr($AMVheader, 68, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x38\x00\x00\x00") { + throw new Exception('expecting "LIST<0x00000000>strlstrh<0x38000000>" at offset '.($startoffset + 68).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 68, 20)).'"'); + } + // followed by 56 bytes of null: substr($AMVheader, 88, 56) -> 144 + if (substr($AMVheader, 144, 8) != 'strf'."\x24\x00\x00\x00") { + throw new Exception('expecting "strf<0x24000000>" at offset '.($startoffset + 144).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 144, 8)).'"'); + } + // followed by 36 bytes of null: substr($AMVheader, 144, 36) -> 180 + + if (substr($AMVheader, 188, 20) != 'LIST'."\x00\x00\x00\x00".'strlstrh'."\x30\x00\x00\x00") { + throw new Exception('expecting "LIST<0x00000000>strlstrh<0x30000000>" at offset '.($startoffset + 188).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 188, 20)).'"'); + } + // followed by 48 bytes of null: substr($AMVheader, 208, 48) -> 256 + if (substr($AMVheader, 256, 8) != 'strf'."\x14\x00\x00\x00") { + throw new Exception('expecting "strf<0x14000000>" at offset '.($startoffset + 256).', found "'.getid3_lib::PrintHexBytes(substr($AMVheader, 256, 8)).'"'); + } + // followed by 20 bytes of a modified WAVEFORMATEX: + // typedef struct { + // WORD wFormatTag; //(Fixme: this is equal to PCM's 0x01 format code) + // WORD nChannels; //(Fixme: this is always 1) + // DWORD nSamplesPerSec; //(Fixme: for all known sample files this is equal to 22050) + // DWORD nAvgBytesPerSec; //(Fixme: for all known sample files this is equal to 44100) + // WORD nBlockAlign; //(Fixme: this seems to be 2 in AMV files, is this correct ?) + // WORD wBitsPerSample; //(Fixme: this seems to be 16 in AMV files instead of the expected 4) + // WORD cbSize; //(Fixme: this seems to be 0 in AMV files) + // WORD reserved; + // } WAVEFORMATEX; + $RIFFchunk['strf']['wformattag'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 264, 2)); + $RIFFchunk['strf']['nchannels'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 266, 2)); + $RIFFchunk['strf']['nsamplespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 268, 4)); + $RIFFchunk['strf']['navgbytespersec'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 272, 4)); + $RIFFchunk['strf']['nblockalign'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 276, 2)); + $RIFFchunk['strf']['wbitspersample'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 278, 2)); + $RIFFchunk['strf']['cbsize'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 280, 2)); + $RIFFchunk['strf']['reserved'] = getid3_lib::LittleEndian2Int(substr($AMVheader, 282, 2)); + + + $info['audio']['lossless'] = false; + $info['audio']['sample_rate'] = $RIFFchunk['strf']['nsamplespersec']; + $info['audio']['channels'] = $RIFFchunk['strf']['nchannels']; + $info['audio']['bits_per_sample'] = $RIFFchunk['strf']['wbitspersample']; + $info['audio']['bitrate'] = $info['audio']['sample_rate'] * $info['audio']['channels'] * $info['audio']['bits_per_sample']; + $info['audio']['bitrate_mode'] = 'cbr'; + + + } catch (getid3_exception $e) { + if ($e->getCode() == 10) { + $this->warning('RIFFAMV parser: '.$e->getMessage()); + } else { + throw $e; + } + } + + return $RIFFchunk; + } + + public function ParseRIFF($startoffset, $maxoffset) { $info = &$this->getid3->info; @@ -1329,7 +1480,7 @@ class getid3_riff extends getid3_handler $getid3_temp->openfile($this->getid3->filename); $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; - $getid3_mp3 = new getid3_mp3($getid3_temp); + $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); if (isset($getid3_temp->info['mpeg']['audio'])) { $info['mpeg']['audio'] = $getid3_temp->info['mpeg']['audio']; @@ -1412,7 +1563,7 @@ class getid3_riff extends getid3_handler $getid3_temp->openfile($this->getid3->filename); $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; $getid3_temp->info['avdataend'] = $info['avdataend']; - $getid3_mp3 = new getid3_mp3($getid3_temp); + $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); $getid3_mp3->getOnlyMPEGaudioInfo($info['avdataoffset'], false); if (empty($getid3_temp->info['error'])) { $info['audio'] = $getid3_temp->info['audio']; @@ -2426,10 +2577,10 @@ class getid3_riff extends getid3_handler } private function EitherEndian2Int($byteword, $signed=false) { - if ($this->getid3->info['fileformat'] == 'riff') { + if ($this->container == 'riff') { return getid3_lib::LittleEndian2Int($byteword, $signed); } return getid3_lib::BigEndian2Int($byteword, false, $signed); } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio.ac3.php b/wp-includes/ID3/module.audio.ac3.php index 9834feb5b2..38ddf352f7 100644 --- a/wp-includes/ID3/module.audio.ac3.php +++ b/wp-includes/ID3/module.audio.ac3.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -470,4 +471,4 @@ class getid3_ac3 extends getid3_handler } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio.dts.php b/wp-includes/ID3/module.audio.dts.php index 79982cccfb..59831c8639 100644 --- a/wp-includes/ID3/module.audio.dts.php +++ b/wp-includes/ID3/module.audio.dts.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -287,4 +288,4 @@ class getid3_dts extends getid3_handler return false; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio.flac.php b/wp-includes/ID3/module.audio.flac.php index 6b9598c741..8fa0f4c68a 100644 --- a/wp-includes/ID3/module.audio.flac.php +++ b/wp-includes/ID3/module.audio.flac.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -439,4 +440,4 @@ class getid3_flac extends getid3_handler return (isset($lookup[$type_id]) ? $lookup[$type_id] : 'reserved'); } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio.mp3.php b/wp-includes/ID3/module.audio.mp3.php index e6ffea947b..98877a9304 100644 --- a/wp-includes/ID3/module.audio.mp3.php +++ b/wp-includes/ID3/module.audio.mp3.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -95,8 +96,8 @@ class getid3_mp3 extends getid3_handler // Not sure what version of LAME this is - look in padding of last frame for longer version string $PossibleLAMEversionStringOffset = $info['avdataend'] - $PossiblyLongerLAMEversion_FrameLength; - fseek($this->getid3->fp, $PossibleLAMEversionStringOffset); - $PossiblyLongerLAMEversion_Data = fread($this->getid3->fp, $PossiblyLongerLAMEversion_FrameLength); + $this->fseek($PossibleLAMEversionStringOffset); + $PossiblyLongerLAMEversion_Data = $this->fread($PossiblyLongerLAMEversion_FrameLength); switch (substr($CurrentDataLAMEversionString, -1)) { case 'a': case 'b': @@ -422,12 +423,12 @@ class getid3_mp3 extends getid3_handler $MPEGaudioEmphasisLookup = self::MPEGaudioEmphasisArray(); } - if (fseek($this->getid3->fp, $offset, SEEK_SET) != 0) { + if ($this->fseek($offset) != 0) { $info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset; return false; } - //$headerstring = fread($this->getid3->fp, 1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame - $headerstring = fread($this->getid3->fp, 226); // LAME header at offset 36 + 190 bytes of Xing/LAME data + //$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame + $headerstring = $this->fread(226); // LAME header at offset 36 + 190 bytes of Xing/LAME data // MP3 audio frame structure: // $aa $aa $aa $aa [$bb $bb] $cc... @@ -890,19 +891,21 @@ class getid3_mp3 extends getid3_handler if (($ExpectedNumberOfAudioBytes > 0) && ($ExpectedNumberOfAudioBytes != ($info['avdataend'] - $info['avdataoffset']))) { if ($ExpectedNumberOfAudioBytes > ($info['avdataend'] - $info['avdataoffset'])) { - if (isset($info['fileformat']) && ($info['fileformat'] == 'riff')) { + if ($this->isDependencyFor('matroska') || $this->isDependencyFor('riff')) { // ignore, audio data is broken into chunks so will always be data "missing" - } elseif (($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])) == 1) { - $info['warning'][] = 'Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)'; - } else { - $info['warning'][] = 'Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])).' bytes)'; + } + elseif (($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])) == 1) { + $this->warning('Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)'); + } + else { + $this->warning('Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($info['avdataend'] - $info['avdataoffset'])).' bytes)'); } } else { if ((($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes) == 1) { - // $prenullbytefileoffset = ftell($this->getid3->fp); - // fseek($this->getid3->fp, $info['avdataend'], SEEK_SET); - // $PossibleNullByte = fread($this->getid3->fp, 1); - // fseek($this->getid3->fp, $prenullbytefileoffset, SEEK_SET); + // $prenullbytefileoffset = $this->ftell(); + // $this->fseek($info['avdataend']); + // $PossibleNullByte = $this->fread(1); + // $this->fseek($prenullbytefileoffset); // if ($PossibleNullByte === "\x00") { $info['avdataend']--; // $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'; @@ -1118,8 +1121,8 @@ class getid3_mp3 extends getid3_handler public function FreeFormatFrameLength($offset, $deepscan=false) { $info = &$this->getid3->info; - fseek($this->getid3->fp, $offset, SEEK_SET); - $MPEGaudioData = fread($this->getid3->fp, 32768); + $this->fseek($offset); + $MPEGaudioData = $this->fread(32768); $SyncPattern1 = substr($MPEGaudioData, 0, 4); // may be different pattern due to padding @@ -1166,8 +1169,8 @@ class getid3_mp3 extends getid3_handler $ActualFrameLengthValues = array(); $nextoffset = $offset + $framelength; while ($nextoffset < ($info['avdataend'] - 6)) { - fseek($this->getid3->fp, $nextoffset - 1, SEEK_SET); - $NextSyncPattern = fread($this->getid3->fp, 6); + $this->fseek($nextoffset - 1); + $NextSyncPattern = $this->fread(6); if ((substr($NextSyncPattern, 1, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 1, strlen($SyncPattern2)) == $SyncPattern2)) { // good - found where expected $ActualFrameLengthValues[] = $framelength; @@ -1215,22 +1218,22 @@ class getid3_mp3 extends getid3_handler $Distribution['padding'] = array(); $info = &$this->getid3->info; - fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + $this->fseek($info['avdataoffset']); $max_frames_scan = 5000; $frames_scanned = 0; $previousvalidframe = $info['avdataoffset']; - while (ftell($this->getid3->fp) < $info['avdataend']) { + while ($this->ftell() < $info['avdataend']) { set_time_limit(30); - $head4 = fread($this->getid3->fp, 4); + $head4 = $this->fread(4); if (strlen($head4) < 4) { break; } if ($head4{0} != "\xFF") { for ($i = 1; $i < 4; $i++) { if ($head4{$i} == "\xFF") { - fseek($this->getid3->fp, $i - 4, SEEK_CUR); + $this->fseek($i - 4, SEEK_CUR); continue 2; } } @@ -1258,9 +1261,9 @@ class getid3_mp3 extends getid3_handler $LongMPEGfrequencyLookup[$head4]); } if ($MPEGaudioHeaderLengthCache[$head4] > 4) { - $WhereWeWere = ftell($this->getid3->fp); - fseek($this->getid3->fp, $MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR); - $next4 = fread($this->getid3->fp, 4); + $WhereWeWere = $this->ftell(); + $this->fseek($MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR); + $next4 = $this->fread(4); if ($next4{0} == "\xFF") { if (!isset($MPEGaudioHeaderDecodeCache[$next4])) { $MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4); @@ -1269,7 +1272,7 @@ class getid3_mp3 extends getid3_handler $MPEGaudioHeaderValidCache[$next4] = self::MPEGaudioHeaderValid($MPEGaudioHeaderDecodeCache[$next4], false, false); } if ($MPEGaudioHeaderValidCache[$next4]) { - fseek($this->getid3->fp, -4, SEEK_CUR); + $this->fseek(-4, SEEK_CUR); getid3_lib::safe_inc($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]); getid3_lib::safe_inc($Distribution['layer'][$LongMPEGlayerLookup[$head4]]); @@ -1277,7 +1280,7 @@ class getid3_mp3 extends getid3_handler getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]); getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]); if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) { - $pct_data_scanned = (ftell($this->getid3->fp) - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']); + $pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']); $info['warning'][] = 'too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.'; foreach ($Distribution as $key1 => $value1) { foreach ($value1 as $key2 => $value2) { @@ -1290,7 +1293,7 @@ class getid3_mp3 extends getid3_handler } } unset($next4); - fseek($this->getid3->fp, $WhereWeWere - 3, SEEK_SET); + $this->fseek($WhereWeWere - 3); } } @@ -1355,13 +1358,13 @@ class getid3_mp3 extends getid3_handler } - fseek($this->getid3->fp, $avdataoffset, SEEK_SET); + $this->fseek($avdataoffset); $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset); if ($sync_seek_buffer_size <= 0) { $info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset; return false; } - $header = fread($this->getid3->fp, $sync_seek_buffer_size); + $header = $this->fread($sync_seek_buffer_size); $sync_seek_buffer_size = strlen($header); $SynchSeekOffset = 0; while ($SynchSeekOffset < $sync_seek_buffer_size) { @@ -1473,7 +1476,7 @@ class getid3_mp3 extends getid3_handler $dummy = array('error'=>$info['error'], 'warning'=>$info['warning'], 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); $synchstartoffset = $info['avdataoffset']; - fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET); + $this->fseek($info['avdataoffset']); // you can play with these numbers: $max_frames_scan = 50000; @@ -1488,13 +1491,13 @@ class getid3_mp3 extends getid3_handler $pct_data_scanned = 0; for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) { $frames_scanned_this_segment = 0; - if (ftell($this->getid3->fp) >= $info['avdataend']) { + if ($this->ftell() >= $info['avdataend']) { break; } - $scan_start_offset[$current_segment] = max(ftell($this->getid3->fp), $info['avdataoffset'] + round($current_segment * (($info['avdataend'] - $info['avdataoffset']) / $max_scan_segments))); + $scan_start_offset[$current_segment] = max($this->ftell(), $info['avdataoffset'] + round($current_segment * (($info['avdataend'] - $info['avdataoffset']) / $max_scan_segments))); if ($current_segment > 0) { - fseek($this->getid3->fp, $scan_start_offset[$current_segment], SEEK_SET); - $buffer_4k = fread($this->getid3->fp, 4096); + $this->fseek($scan_start_offset[$current_segment]); + $buffer_4k = $this->fread(4096); for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) { if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) { @@ -1523,7 +1526,7 @@ class getid3_mp3 extends getid3_handler } $frames_scanned++; if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) { - $this_pct_scanned = (ftell($this->getid3->fp) - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']); + $this_pct_scanned = ($this->ftell() - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']); if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) { // file likely contains < $max_frames_scan, just scan as one segment $max_scan_segments = 1; @@ -2006,4 +2009,4 @@ class getid3_mp3 extends getid3_handler return (isset($LAMEpresetUsedLookup[$LAMEtag['preset_used_id']]) ? $LAMEpresetUsedLookup[$LAMEtag['preset_used_id']] : 'new/unknown preset: '.$LAMEtag['preset_used_id'].' - report to info@getid3.org'); } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.audio.ogg.php b/wp-includes/ID3/module.audio.ogg.php index a2a35aadf7..f3bb004711 100644 --- a/wp-includes/ID3/module.audio.ogg.php +++ b/wp-includes/ID3/module.audio.ogg.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -114,6 +115,66 @@ class getid3_ogg extends getid3_handler $info['audio']['bitrate_mode'] = 'vbr'; } + } elseif (substr($filedata, 0, 7) == "\x80".'theora') { + + // http://www.theora.org/doc/Theora.pdf (section 6.2) + + $info['ogg']['pageheader']['theora']['theora_magic'] = substr($filedata, $filedataoffset, 7); // hard-coded to "\x80.'theora' + $filedataoffset += 7; + $info['ogg']['pageheader']['theora']['version_major'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['version_minor'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['version_revision'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['frame_width_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2)); + $filedataoffset += 2; + $info['ogg']['pageheader']['theora']['frame_height_macroblocks'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2)); + $filedataoffset += 2; + $info['ogg']['pageheader']['theora']['resolution_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3)); + $filedataoffset += 3; + $info['ogg']['pageheader']['theora']['resolution_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3)); + $filedataoffset += 3; + $info['ogg']['pageheader']['theora']['picture_offset_x'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['picture_offset_y'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['frame_rate_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader']['theora']['frame_rate_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 4)); + $filedataoffset += 4; + $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3)); + $filedataoffset += 3; + $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3)); + $filedataoffset += 3; + $info['ogg']['pageheader']['theora']['color_space_id'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 1)); + $filedataoffset += 1; + $info['ogg']['pageheader']['theora']['nominal_bitrate'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 3)); + $filedataoffset += 3; + $info['ogg']['pageheader']['theora']['flags'] = getid3_lib::BigEndian2Int(substr($filedata, $filedataoffset, 2)); + $filedataoffset += 2; + + $info['ogg']['pageheader']['theora']['quality'] = ($info['ogg']['pageheader']['theora']['flags'] & 0xFC00) >> 10; + $info['ogg']['pageheader']['theora']['kfg_shift'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x03E0) >> 5; + $info['ogg']['pageheader']['theora']['pixel_format_id'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x0018) >> 3; + $info['ogg']['pageheader']['theora']['reserved'] = ($info['ogg']['pageheader']['theora']['flags'] & 0x0007) >> 0; // should be 0 + $info['ogg']['pageheader']['theora']['color_space'] = self::TheoraColorSpace($info['ogg']['pageheader']['theora']['color_space_id']); + $info['ogg']['pageheader']['theora']['pixel_format'] = self::TheoraPixelFormat($info['ogg']['pageheader']['theora']['pixel_format_id']); + + $info['video']['dataformat'] = 'theora'; + $info['mime_type'] = 'video/ogg'; + //$info['audio']['bitrate_mode'] = 'abr'; + //$info['audio']['lossless'] = false; + $info['video']['resolution_x'] = $info['ogg']['pageheader']['theora']['resolution_x']; + $info['video']['resolution_y'] = $info['ogg']['pageheader']['theora']['resolution_y']; + if ($info['ogg']['pageheader']['theora']['frame_rate_denominator'] > 0) { + $info['video']['frame_rate'] = (float) $info['ogg']['pageheader']['theora']['frame_rate_numerator'] / $info['ogg']['pageheader']['theora']['frame_rate_denominator']; + } + if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) { + $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; + } +$info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable'; + } elseif (substr($filedata, 0, 8) == "fishead\x00") { @@ -172,8 +233,8 @@ class getid3_ogg extends getid3_handler } elseif (substr($filedata, 1, 6) == 'theora') { - $info['video']['dataformat'] = 'theora'; - $info['error'][] = 'Ogg Theora not correctly handled in this version of getID3 ['.$this->getid3->version().']'; + $info['video']['dataformat'] = 'theora1'; + $info['error'][] = 'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']'; //break; } elseif (substr($filedata, 1, 6) == 'vorbis') { @@ -668,4 +729,28 @@ class getid3_ogg extends getid3_handler return round($qval, 1); // 5 or 4.9 } -} + public static function TheoraColorSpace($colorspace_id) { + // http://www.theora.org/doc/Theora.pdf (table 6.3) + static $TheoraColorSpaceLookup = array(); + if (empty($TheoraColorSpaceLookup)) { + $TheoraColorSpaceLookup[0] = 'Undefined'; + $TheoraColorSpaceLookup[1] = 'Rec. 470M'; + $TheoraColorSpaceLookup[2] = 'Rec. 470BG'; + $TheoraColorSpaceLookup[3] = 'Reserved'; + } + return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null); + } + + public static function TheoraPixelFormat($pixelformat_id) { + // http://www.theora.org/doc/Theora.pdf (table 6.4) + static $TheoraPixelFormatLookup = array(); + if (empty($TheoraPixelFormatLookup)) { + $TheoraPixelFormatLookup[0] = '4:2:0'; + $TheoraPixelFormatLookup[1] = 'Reserved'; + $TheoraPixelFormatLookup[2] = '4:2:2'; + $TheoraPixelFormatLookup[3] = '4:4:4'; + } + return (isset($TheoraPixelFormatLookup[$pixelformat_id]) ? $TheoraPixelFormatLookup[$pixelformat_id] : null); + } + +} \ No newline at end of file diff --git a/wp-includes/ID3/module.tag.apetag.php b/wp-includes/ID3/module.tag.apetag.php index afeede769c..5bd4b83509 100644 --- a/wp-includes/ID3/module.tag.apetag.php +++ b/wp-includes/ID3/module.tag.apetag.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -32,8 +33,8 @@ class getid3_apetag extends getid3_handler if ($this->overrideendoffset == 0) { - fseek($this->getid3->fp, 0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END); - $APEfooterID3v1 = fread($this->getid3->fp, $id3v1tagsize + $apetagheadersize + $lyrics3tagsize); + $this->fseek(0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END); + $APEfooterID3v1 = $this->fread($id3v1tagsize + $apetagheadersize + $lyrics3tagsize); //if (preg_match('/APETAGEX.{24}TAG.{125}$/i', $APEfooterID3v1)) { if (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $id3v1tagsize - $apetagheadersize, 8) == 'APETAGEX') { @@ -51,8 +52,8 @@ class getid3_apetag extends getid3_handler } else { - fseek($this->getid3->fp, $this->overrideendoffset - $apetagheadersize, SEEK_SET); - if (fread($this->getid3->fp, 8) == 'APETAGEX') { + $this->fseek($this->overrideendoffset - $apetagheadersize); + if ($this->fread(8) == 'APETAGEX') { $info['ape']['tag_offset_end'] = $this->overrideendoffset; } @@ -68,21 +69,21 @@ class getid3_apetag extends getid3_handler // shortcut $thisfile_ape = &$info['ape']; - fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $apetagheadersize, SEEK_SET); - $APEfooterData = fread($this->getid3->fp, 32); + $this->fseek($thisfile_ape['tag_offset_end'] - $apetagheadersize); + $APEfooterData = $this->fread(32); if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) { $info['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']; return false; } if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) { - fseek($this->getid3->fp, $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize, SEEK_SET); - $thisfile_ape['tag_offset_start'] = ftell($this->getid3->fp); - $APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize); + $this->fseek($thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize); + $thisfile_ape['tag_offset_start'] = $this->ftell(); + $APEtagData = $this->fread($thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize); } else { $thisfile_ape['tag_offset_start'] = $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize']; - fseek($this->getid3->fp, $thisfile_ape['tag_offset_start'], SEEK_SET); - $APEtagData = fread($this->getid3->fp, $thisfile_ape['footer']['raw']['tagsize']); + $this->fseek($thisfile_ape['tag_offset_start']); + $APEtagData = $this->fread($thisfile_ape['footer']['raw']['tagsize']); } $info['avdataend'] = $thisfile_ape['tag_offset_start']; @@ -367,4 +368,4 @@ class getid3_apetag extends getid3_handler return in_array(strtolower($itemkey), $APEtagItemIsUTF8Lookup); } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.tag.id3v1.php b/wp-includes/ID3/module.tag.id3v1.php index fd9069e04a..def281ae9c 100644 --- a/wp-includes/ID3/module.tag.id3v1.php +++ b/wp-includes/ID3/module.tag.id3v1.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -25,9 +26,9 @@ class getid3_id3v1 extends getid3_handler return false; } - fseek($this->getid3->fp, -256, SEEK_END); - $preid3v1 = fread($this->getid3->fp, 128); - $id3v1tag = fread($this->getid3->fp, 128); + $this->fseek(-256, SEEK_END); + $preid3v1 = $this->fread(128); + $id3v1tag = $this->fread(128); if (substr($id3v1tag, 0, 3) == 'TAG') { @@ -356,4 +357,4 @@ class getid3_id3v1 extends getid3_handler return $ID3v1Tag; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/module.tag.id3v2.php b/wp-includes/ID3/module.tag.id3v2.php index b08f9f9a3b..d1c4fce744 100644 --- a/wp-includes/ID3/module.tag.id3v2.php +++ b/wp-includes/ID3/module.tag.id3v2.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -51,8 +52,8 @@ class getid3_id3v2 extends getid3_handler $thisfile_id3v2_flags = &$thisfile_id3v2['flags']; - fseek($this->getid3->fp, $this->StartingOffset, SEEK_SET); - $header = fread($this->getid3->fp, 10); + $this->fseek($this->StartingOffset); + $header = $this->fread(10); if (substr($header, 0, 3) == 'ID3' && strlen($header) == 10) { $thisfile_id3v2['majorversion'] = ord($header{3}); @@ -131,7 +132,7 @@ class getid3_id3v2 extends getid3_handler } if ($sizeofframes > 0) { - $framedata = fread($this->getid3->fp, $sizeofframes); // read all frames from file into $framedata variable + $framedata = $this->fread($sizeofframes); // read all frames from file into $framedata variable // if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x) if (!empty($thisfile_id3v2_flags['unsynch']) && ($id3v2_majorversion <= 3)) { @@ -423,7 +424,7 @@ class getid3_id3v2 extends getid3_handler // ID3v2 size 4 * %0xxxxxxx if (isset($thisfile_id3v2_flags['isfooter']) && $thisfile_id3v2_flags['isfooter']) { - $footer = fread($this->getid3->fp, 10); + $footer = $this->fread(10); if (substr($footer, 0, 3) == '3DI') { $thisfile_id3v2['footer'] = true; $thisfile_id3v2['majorversion_footer'] = ord($footer{3}); @@ -642,7 +643,12 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['description'] = $frame_description; $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding))); if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data'])); + $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0)); + if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][$commentkey] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data'])); + } else { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data'])); + } } //unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain @@ -1077,7 +1083,12 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['description'] = $frame_description; $parsedFrame['data'] = $frame_text; if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (!empty($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0)); + if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][$commentkey] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + } else { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); + } } } @@ -1885,7 +1896,7 @@ class getid3_id3v2 extends getid3_handler $frame_offset += 2; $parsedFrame['bitsperpoint'] = ord(substr($parsedFrame['data'], $frame_offset++, 1)); $frame_bytesperpoint = ceil($parsedFrame['bitsperpoint'] / 8); - for ($i = 0; $i < $frame_indexpoints; $i++) { + for ($i = 0; $i < $parsedFrame['indexpoints']; $i++) { $parsedFrame['indexes'][$i] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, $frame_bytesperpoint)); $frame_offset += $frame_bytesperpoint; } @@ -3411,4 +3422,3 @@ class getid3_id3v2 extends getid3_handler } } - diff --git a/wp-includes/ID3/module.tag.lyrics3.php b/wp-includes/ID3/module.tag.lyrics3.php index 108d7aeeab..7891603e1d 100644 --- a/wp-includes/ID3/module.tag.lyrics3.php +++ b/wp-includes/ID3/module.tag.lyrics3.php @@ -3,6 +3,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// // See readme.txt for more details // ///////////////////////////////////////////////////////////////// @@ -27,8 +28,8 @@ class getid3_lyrics3 extends getid3_handler return false; } - fseek($this->getid3->fp, (0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] - $lyrics3_id3v1 = fread($this->getid3->fp, 128 + 9 + 6); + $this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] + $lyrics3_id3v1 = $this->fread(128 + 9 + 6); $lyrics3lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 $id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1 @@ -68,9 +69,9 @@ class getid3_lyrics3 extends getid3_handler if (isset($info['ape']['tag_offset_start']) && ($info['ape']['tag_offset_start'] > 15)) { - fseek($this->getid3->fp, $info['ape']['tag_offset_start'] - 15, SEEK_SET); - $lyrics3lsz = fread($this->getid3->fp, 6); - $lyrics3end = fread($this->getid3->fp, 9); + $this->fseek($info['ape']['tag_offset_start'] - 15); + $lyrics3lsz = $this->fread(6); + $lyrics3end = $this->fread(9); if ($lyrics3end == 'LYRICSEND') { // Lyrics3v1, APE, maybe ID3v1 @@ -101,20 +102,19 @@ class getid3_lyrics3 extends getid3_handler if (!isset($info['ape'])) { $GETID3_ERRORARRAY = &$info['warning']; - if (getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, false)) { - $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename); - $getid3_apetag = new getid3_apetag($getid3_temp); - $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start']; - $getid3_apetag->Analyze(); - if (!empty($getid3_temp->info['ape'])) { - $info['ape'] = $getid3_temp->info['ape']; - } - if (!empty($getid3_temp->info['replay_gain'])) { - $info['replay_gain'] = $getid3_temp->info['replay_gain']; - } - unset($getid3_temp, $getid3_apetag); + getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true); + $getid3_temp = new getID3(); + $getid3_temp->openfile($this->getid3->filename); + $getid3_apetag = new getid3_apetag($getid3_temp); + $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start']; + $getid3_apetag->Analyze(); + if (!empty($getid3_temp->info['ape'])) { + $info['ape'] = $getid3_temp->info['ape']; } + if (!empty($getid3_temp->info['replay_gain'])) { + $info['replay_gain'] = $getid3_temp->info['replay_gain']; + } + unset($getid3_temp, $getid3_apetag); } } @@ -132,11 +132,11 @@ class getid3_lyrics3 extends getid3_handler return false; } - fseek($this->getid3->fp, $endoffset, SEEK_SET); + $this->fseek($endoffset); if ($length <= 0) { return false; } - $rawdata = fread($this->getid3->fp, $length); + $rawdata = $this->fread($length); $ParsedLyrics3['raw']['lyrics3version'] = $version; $ParsedLyrics3['raw']['lyrics3tagsize'] = $length; @@ -169,7 +169,7 @@ class getid3_lyrics3 extends getid3_handler $ParsedLyrics3['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9)); $this->Lyrics3LyricsTimestampParse($ParsedLyrics3); } else { - $info['error'][] = '"LYRICSEND" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; + $info['error'][] = '"LYRICSEND" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; return false; } break; @@ -217,7 +217,7 @@ class getid3_lyrics3 extends getid3_handler $this->Lyrics3LyricsTimestampParse($ParsedLyrics3); } } else { - $info['error'][] = '"LYRICS200" expected at '.(ftell($this->getid3->fp) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; + $info['error'][] = '"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead'; return false; } break; @@ -291,4 +291,4 @@ class getid3_lyrics3 extends getid3_handler } return null; } -} +} \ No newline at end of file diff --git a/wp-includes/ID3/readme.txt b/wp-includes/ID3/readme.txt index 337e84f35e..b627cc2dcc 100644 --- a/wp-includes/ID3/readme.txt +++ b/wp-includes/ID3/readme.txt @@ -2,6 +2,7 @@ /// getID3() by James Heinrich // // available at http://getid3.sourceforge.net // // or http://www.getid3.org // +// also https://github.com/JamesHeinrich/getID3 // ///////////////////////////////////////////////////////////////// ***************************************************************** @@ -67,13 +68,13 @@ What does getID3() do? =========================================================================== Reads & parses (to varying degrees): -# tags: + ¤ tags: * APE (v1 and v2) * ID3v1 (& ID3v1.1) * ID3v2 (v2.4, v2.3, v2.2) * Lyrics3 (v1 & v2) -# audio-lossy: + ¤ audio-lossy: * MP3/MP2/MP1 * MPC / Musepack * Ogg (Vorbis, OggFLAC, Speex) @@ -85,7 +86,7 @@ Reads & parses (to varying degrees): * DSS * VQF -# audio-lossless: + ¤ audio-lossless: * AIFF * AU * Bonk @@ -104,7 +105,7 @@ Reads & parses (to varying degrees): * WAV (RIFF) * WavPack -# audio-video: + ¤ audio-video: * ASF: ASF, Windows Media Audio (WMA), Windows Media Video (WMV) * AVI (RIFF) * Flash @@ -114,7 +115,7 @@ Reads & parses (to varying degrees): * Quicktime (including MP4) * RealVideo -# still image: + ¤ still image: * BMP * GIF * JPEG @@ -123,7 +124,7 @@ Reads & parses (to varying degrees): * SWF (Flash) * PhotoCD -# data: + ¤ data: * ISO-9660 CD-ROM image (directory structure) * SZIP (limited support) * ZIP (directory structure) @@ -309,7 +310,7 @@ http://www.getid3.org/phpBB3/viewforum.php?f=7 (http://web.inter.nl.net/users/hvdh/lossless/lossless.htm) * Support for RIFF-INFO chunks * http://lotto.st-andrews.ac.uk/~njh/tag_interchange.html - (thanks Nick Humfrey ) + (thanks Nick Humfrey ) * http://abcavi.narod.ru/sof/abcavi/infotags.htm (thanks Kibi) * Better support for Bink video @@ -324,23 +325,23 @@ http://www.getid3.org/phpBB3/viewforum.php?f=7 * Support for IFF * Support for ICO * Support for ANI -* Support for EXE (comments, author, etc) (thanks p*quaedackers@planet*nl) +* Support for EXE (comments, author, etc) (thanks p*quaedackersØplanet*nl) * Support for DVD-IFO (region, subtitles, aspect ratio, etc) - (thanks p*quaedackers@planet*nl) + (thanks p*quaedackersØplanet*nl) * More complete support for SWF - parsing encapsulated MP3 and/or JPEG content - (thanks n8n8@yahoo*com) + (thanks n8n8Øyahoo*com) * Support for a2b * Optional scan-through-frames for AVI verification - (thanks rockcohen@massive-interactive*nl) -* Support for TTF (thanks info@butterflyx*com) + (thanks rockcohenØmassive-interactive*nl) +* Support for TTF (thanks infoØbutterflyx*com) * Support for DSS (http://www.getid3.org/phpBB3/viewtopic.php?t=171) * Support for SMAF (http://smaf-yamaha.com/what/demo.html) http://www.getid3.org/phpBB3/viewtopic.php?t=182 * Support for AMR (http://www.getid3.org/phpBB3/viewtopic.php?t=195) * Support for 3gpp (http://www.getid3.org/phpBB3/viewtopic.php?t=195) -* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2K@hotmail*com) +* Support for ID4 (http://www.wackysoft.cjb.net grizlyY2KØhotmail*com) * Parse XML data returned in Ogg comments -* Parse XML data from Quicktime SMIL metafiles (klausrath@mac*com) +* Parse XML data from Quicktime SMIL metafiles (klausrathØmac*com) * ID3v2 genre string creator function * More complete parsing of JPG * Support for all old-style ASF packets @@ -424,7 +425,7 @@ http://www.getid3.org/phpBB3/viewtopic.php?t=25 "movi" chunk that fits in the first 2GB, should issue error to show that playtime is incorrect. Other data should be mostly correct, assuming that data is constant throughout the file) - +* PHP <= v5 on Windows cannot read UTF-8 filenames Known Bugs/Issues in other programs @@ -600,4 +601,4 @@ Reference material: * http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm * http://trac.musepack.net/trac/wiki/SV8Specification * http://wyday.com/cuesharp/specification.php -* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html +* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html \ No newline at end of file