Media: update the getID3 library to version 1.9.14 to avoid fatal errors in PHP7.

Props MyThemeShop for the initial patch.
Fixes #41496.

Built from https://develop.svn.wordpress.org/trunk@41196


git-svn-id: http://core.svn.wordpress.org/trunk@41036 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Scott Taylor 2017-07-31 19:50:45 +00:00
parent 82d0a53e77
commit 6bcf4d6f63
15 changed files with 1712 additions and 687 deletions

View File

@ -293,6 +293,9 @@ class getid3_lib
return self::BigEndian2Int(strrev($byteword), false, $signed);
}
public static function LittleEndian2Bin($byteword) {
return self::BigEndian2Bin(strrev($byteword));
}
public static function BigEndian2Bin($byteword) {
$binvalue = '';
@ -414,6 +417,20 @@ class getid3_lib
return $newarray;
}
public static function flipped_array_merge_noclobber($array1, $array2) {
if (!is_array($array1) || !is_array($array2)) {
return false;
}
# naturally, this only works non-recursively
$newarray = array_flip($array1);
foreach (array_flip($array2) as $key => $val) {
if (!isset($newarray[$key])) {
$newarray[$key] = count($newarray);
}
}
return array_flip($newarray);
}
public static function ksort_recursive(&$theArray) {
ksort($theArray);
@ -946,8 +963,20 @@ class getid3_lib
return $string;
}
// mb_convert_encoding() availble
if (function_exists('mb_convert_encoding')) {
if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
switch ($out_charset) {
case 'ISO-8859-1':
$converted_string = rtrim($converted_string, "\x00");
break;
}
return $converted_string;
}
return $string;
}
// iconv() availble
if (function_exists('iconv')) {
else if (function_exists('iconv')) {
if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
switch ($out_charset) {
case 'ISO-8859-1':
@ -963,7 +992,7 @@ class getid3_lib
}
// iconv() not available
// neither mb_convert_encoding or iconv() is available
static $ConversionFunctionList = array();
if (empty($ConversionFunctionList)) {
$ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
@ -985,7 +1014,7 @@ class getid3_lib
$ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
return self::$ConversionFunction($string);
}
throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
}
public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
@ -1006,38 +1035,38 @@ class getid3_lib
$string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
$HTMLstring = '';
switch ($charset) {
switch (strtolower($charset)) {
case '1251':
case '1252':
case '866':
case '932':
case '936':
case '950':
case 'BIG5':
case 'BIG5-HKSCS':
case 'big5':
case 'big5-hkscs':
case 'cp1251':
case 'cp1252':
case 'cp866':
case 'EUC-JP':
case 'EUCJP':
case 'GB2312':
case 'euc-jp':
case 'eucjp':
case 'gb2312':
case 'ibm866':
case 'ISO-8859-1':
case 'ISO-8859-15':
case 'ISO8859-1':
case 'ISO8859-15':
case 'KOI8-R':
case 'iso-8859-1':
case 'iso-8859-15':
case 'iso8859-1':
case 'iso8859-15':
case 'koi8-r':
case 'koi8-ru':
case 'koi8r':
case 'Shift_JIS':
case 'SJIS':
case 'shift_jis':
case 'sjis':
case 'win-1251':
case 'Windows-1251':
case 'Windows-1252':
case 'windows-1251':
case 'windows-1252':
$HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
break;
case 'UTF-8':
case 'utf-8':
$strlen = strlen($string);
for ($i = 0; $i < $strlen; $i++) {
$char_ord_val = ord($string{$i});
@ -1065,7 +1094,7 @@ class getid3_lib
}
break;
case 'UTF-16LE':
case 'utf-16le':
for ($i = 0; $i < strlen($string); $i += 2) {
$charval = self::LittleEndian2Int(substr($string, $i, 2));
if (($charval >= 32) && ($charval <= 127)) {
@ -1076,7 +1105,7 @@ class getid3_lib
}
break;
case 'UTF-16BE':
case 'utf-16be':
for ($i = 0; $i < strlen($string); $i += 2) {
$charval = self::BigEndian2Int(substr($string, $i, 2));
if (($charval >= 32) && ($charval <= 127)) {
@ -1153,11 +1182,19 @@ class getid3_lib
public static function GetDataImageSize($imgData, &$imageinfo=array()) {
static $tempdir = '';
if (empty($tempdir)) {
if (function_exists('sys_get_temp_dir')) {
$tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
}
// yes this is ugly, feel free to suggest a better way
require_once(dirname(__FILE__).'/getid3.php');
$getid3_temp = new getID3();
$tempdir = $getid3_temp->tempdir;
unset($getid3_temp);
if (include_once(dirname(__FILE__).'/getid3.php')) {
if ($getid3_temp = new getID3()) {
if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
$tempdir = $getid3_temp_tempdir;
}
unset($getid3_temp, $getid3_temp_tempdir);
}
}
}
$GetDataImageSize = false;
if ($tempfilename = tempnam($tempdir, 'gI3')) {
@ -1165,6 +1202,9 @@ class getid3_lib
fwrite($tmp, $imgData);
fclose($tmp);
$GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
return false;
}
$GetDataImageSize['height'] = $GetDataImageSize[0];
$GetDataImageSize['width'] = $GetDataImageSize[1];
}
@ -1237,10 +1277,14 @@ class getid3_lib
}
if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
$value = (is_string($value) ? trim($value) : $value);
if (!is_numeric($key)) {
if (!is_int($key) && !ctype_digit($key)) {
$ThisFileInfo['comments'][$tagname][$key] = $value;
} else {
$ThisFileInfo['comments'][$tagname][] = $value;
if (isset($ThisFileInfo['comments'][$tagname])) {
$ThisFileInfo['comments'][$tagname] = array($value);
} else {
$ThisFileInfo['comments'][$tagname][] = $value;
}
}
}
}
@ -1248,6 +1292,18 @@ class getid3_lib
}
}
// attempt to standardize spelling of returned keys
$StandardizeFieldNames = array(
'tracknumber' => 'track_number',
'track' => 'track_number',
);
foreach ($StandardizeFieldNames as $badkey => $goodkey) {
if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
$ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
unset($ThisFileInfo['comments'][$badkey]);
}
}
// Copy to ['comments_html']
if (!empty($ThisFileInfo['comments'])) {
foreach ($ThisFileInfo['comments'] as $field => $values) {

View File

@ -22,6 +22,9 @@ if (!defined('GETID3_INCLUDEPATH')) {
if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
define('IMG_JPG', IMAGETYPE_JPEG);
}
if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE
define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
}
// attempt to define temp dir as something flexible but reliable
$temp_dir = ini_get('upload_tmp_dir');
@ -109,7 +112,7 @@ class getID3
protected $startup_error = '';
protected $startup_warning = '';
const VERSION = '1.9.9-20141121';
const VERSION = '1.9.14-201706111222';
const FREAD_BUFFER_SIZE = 32768;
const ATTACHMENTS_NONE = false;
@ -120,19 +123,19 @@ class getID3
// Check memory
$this->memory_limit = ini_get('memory_limit');
if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
// could be stored as "16M" rather than 16777216 for example
$this->memory_limit = $matches[1] * 1048576;
} elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
} elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
// could be stored as "2G" rather than 2147483648 for example
$this->memory_limit = $matches[1] * 1073741824;
}
if ($this->memory_limit <= 0) {
// memory limits probably disabled
} elseif ($this->memory_limit <= 4194304) {
$this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
$this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n";
} elseif ($this->memory_limit <= 12582912) {
$this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini';
$this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'."\n";
}
// Check safe_mode off
@ -140,27 +143,30 @@ class getID3
$this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
}
if (intval(ini_get('mbstring.func_overload')) > 0) {
$this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
// http://php.net/manual/en/mbstring.overload.php
// "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
// getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
$this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
}
// Check for magic_quotes_runtime
if (function_exists('get_magic_quotes_runtime')) {
if (get_magic_quotes_runtime()) {
return $this->startup_error('magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).');
$this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
}
}
// Check for magic_quotes_gpc
if (function_exists('magic_quotes_gpc')) {
if (get_magic_quotes_gpc()) {
return $this->startup_error('magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).');
$this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
}
}
// Load support library
if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
$this->startup_error .= 'getid3.lib.php is missing or corrupt';
$this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n";
}
if ($this->option_max_2gb_check === null) {
@ -179,7 +185,7 @@ class getID3
$helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
if (!is_dir($helperappsdir)) {
$this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
$this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n";
} elseif (strpos(realpath($helperappsdir), ' ') !== false) {
$DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
$path_so_far = array();
@ -199,7 +205,7 @@ class getID3
}
}
} else {
$this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.';
$this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'."\n";
}
}
$path_so_far[] = $value;
@ -209,6 +215,11 @@ class getID3
define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
}
if (!empty($this->startup_error)) {
echo $this->startup_error;
throw new getid3_exception($this->startup_error);
}
return true;
}
@ -236,13 +247,15 @@ class getID3
}
public function openfile($filename) {
public function openfile($filename, $filesize=null) {
try {
if (!empty($this->startup_error)) {
throw new getid3_exception($this->startup_error);
}
if (!empty($this->startup_warning)) {
$this->warning($this->startup_warning);
foreach (explode("\n", $this->startup_warning) as $startup_warning) {
$this->warning($startup_warning);
}
}
// init result array and set parameters
@ -252,12 +265,12 @@ class getID3
$this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
// remote files not supported
if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
if (preg_match('#^(ht|f)tp://#', $filename)) {
throw new getid3_exception('Remote files are not supported - please copy the file locally first');
}
$filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
$filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
// open local file
//if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
@ -280,7 +293,7 @@ class getID3
throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
}
$this->info['filesize'] = filesize($filename);
$this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
// set redundant parameters - might be needed in some include file
// 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);
@ -288,6 +301,17 @@ class getID3
$this->info['filename'] = getid3_lib::mb_basename($filename);
$this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
// set more parameters
$this->info['avdataoffset'] = 0;
$this->info['avdataend'] = $this->info['filesize'];
$this->info['fileformat'] = ''; // filled in later
$this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
$this->info['video']['dataformat'] = ''; // filled in later, unset if not used
$this->info['tags'] = array(); // filled in later, unset if not used
$this->info['error'] = array(); // filled in later, unset if not used
$this->info['warning'] = array(); // filled in later, unset if not used
$this->info['comments'] = array(); // filled in later, unset if not used
$this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
// option_max_2gb_check
if ($this->option_max_2gb_check) {
@ -314,18 +338,6 @@ class getID3
}
}
// set more parameters
$this->info['avdataoffset'] = 0;
$this->info['avdataend'] = $this->info['filesize'];
$this->info['fileformat'] = ''; // filled in later
$this->info['audio']['dataformat'] = ''; // filled in later, unset if not used
$this->info['video']['dataformat'] = ''; // filled in later, unset if not used
$this->info['tags'] = array(); // filled in later, unset if not used
$this->info['error'] = array(); // filled in later, unset if not used
$this->info['warning'] = array(); // filled in later, unset if not used
$this->info['comments'] = array(); // filled in later, unset if not used
$this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired
return true;
} catch (Exception $e) {
@ -335,9 +347,9 @@ class getID3
}
// public: analyze file
public function analyze($filename) {
public function analyze($filename, $filesize=null, $original_filename='') {
try {
if (!$this->openfile($filename)) {
if (!$this->openfile($filename, $filesize)) {
return $this->info;
}
@ -382,7 +394,7 @@ class getID3
$formattest = fread($this->fp, 32774);
// determine format
$determined_format = $this->GetFileFormat($formattest, $filename);
$determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
// unable to determine file format
if (!$determined_format) {
@ -419,14 +431,14 @@ class getID3
return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
}
// module requires iconv support
// module requires mb_convert_encoding/iconv support
// Check encoding/iconv support
if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
$errormessage = 'iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
$errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
if (GETID3_OS_ISWINDOWS) {
$errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
$errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
} else {
$errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
$errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
}
return $this->error($errormessage);
}
@ -561,7 +573,7 @@ class getID3
// AC-3 - audio - Dolby AC-3 / Dolby Digital
'ac3' => array(
'pattern' => '^\x0B\x77',
'pattern' => '^\\x0B\\x77',
'group' => 'audio',
'module' => 'ac3',
'mime_type' => 'audio/ac3',
@ -579,7 +591,7 @@ class getID3
/*
// AA - audio - Audible Audiobook
'aa' => array(
'pattern' => '^.{4}\x57\x90\x75\x36',
'pattern' => '^.{4}\\x57\\x90\\x75\\x36',
'group' => 'audio',
'module' => 'aa',
'mime_type' => 'audio/audible',
@ -587,7 +599,7 @@ class getID3
*/
// AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
'adts' => array(
'pattern' => '^\xFF[\xF0-\xF1\xF8-\xF9]',
'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
'group' => 'audio',
'module' => 'aac',
'mime_type' => 'application/octet-stream',
@ -597,7 +609,7 @@ class getID3
// AU - audio - NeXT/Sun AUdio (AU)
'au' => array(
'pattern' => '^\.snd',
'pattern' => '^\\.snd',
'group' => 'audio',
'module' => 'au',
'mime_type' => 'audio/basic',
@ -605,7 +617,7 @@ class getID3
// AMR - audio - Adaptive Multi Rate
'amr' => array(
'pattern' => '^\x23\x21AMR\x0A', // #!AMR[0A]
'pattern' => '^\\x23\\x21AMR\\x0A', // #!AMR[0A]
'group' => 'audio',
'module' => 'amr',
'mime_type' => 'audio/amr',
@ -621,15 +633,23 @@ class getID3
// BONK - audio - Bonk v0.9+
'bonk' => array(
'pattern' => '^\x00(BONK|INFO|META| ID3)',
'pattern' => '^\\x00(BONK|INFO|META| ID3)',
'group' => 'audio',
'module' => 'bonk',
'mime_type' => 'audio/xmms-bonk',
),
// DSF - audio - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital
'dsf' => array(
'pattern' => '^DSD ', // including trailing space: 44 53 44 20
'group' => 'audio',
'module' => 'dsf',
'mime_type' => 'audio/dsd',
),
// DSS - audio - Digital Speech Standard
'dss' => array(
'pattern' => '^[\x02-\x03]ds[s2]',
'pattern' => '^[\\x02-\\x06]ds[s2]',
'group' => 'audio',
'module' => 'dss',
'mime_type' => 'application/octet-stream',
@ -637,7 +657,7 @@ class getID3
// DTS - audio - Dolby Theatre System
'dts' => array(
'pattern' => '^\x7F\xFE\x80\x01',
'pattern' => '^\\x7F\\xFE\\x80\\x01',
'group' => 'audio',
'module' => 'dts',
'mime_type' => 'audio/dts',
@ -722,7 +742,7 @@ class getID3
// MPC - audio - Musepack / MPEGplus
'mpc' => array(
'pattern' => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
'pattern' => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
'group' => 'audio',
'module' => 'mpc',
'mime_type' => 'audio/x-musepack',
@ -730,7 +750,7 @@ class getID3
// MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS)
'mp3' => array(
'pattern' => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\x0B\x10-\x1B\x20-\x2B\x30-\x3B\x40-\x4B\x50-\x5B\x60-\x6B\x70-\x7B\x80-\x8B\x90-\x9B\xA0-\xAB\xB0-\xBB\xC0-\xCB\xD0-\xDB\xE0-\xEB\xF0-\xFB]',
'pattern' => '^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
'group' => 'audio',
'module' => 'mp3',
'mime_type' => 'audio/mpeg',
@ -738,7 +758,7 @@ class getID3
// OFR - audio - OptimFROG
'ofr' => array(
'pattern' => '^(\*RIFF|OFR)',
'pattern' => '^(\\*RIFF|OFR)',
'group' => 'audio',
'module' => 'optimfrog',
'mime_type' => 'application/octet-stream',
@ -764,7 +784,7 @@ class getID3
// TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org)
'tta' => array(
'pattern' => '^TTA', // could also be '^TTA(\x01|\x02|\x03|2|1)'
'pattern' => '^TTA', // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
'group' => 'audio',
'module' => 'tta',
'mime_type' => 'application/octet-stream',
@ -799,7 +819,7 @@ class getID3
// ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
'asf' => array(
'pattern' => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
'pattern' => '^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C',
'group' => 'audio-video',
'module' => 'asf',
'mime_type' => 'video/x-ms-asf',
@ -816,7 +836,7 @@ class getID3
// FLV - audio/video - FLash Video
'flv' => array(
'pattern' => '^FLV\x01',
'pattern' => '^FLV[\\x01]',
'group' => 'audio-video',
'module' => 'flv',
'mime_type' => 'video/x-flv',
@ -824,7 +844,7 @@ class getID3
// MKAV - audio/video - Mastroka
'matroska' => array(
'pattern' => '^\x1A\x45\xDF\xA3',
'pattern' => '^\\x1A\\x45\\xDF\\xA3',
'group' => 'audio-video',
'module' => 'matroska',
'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
@ -832,7 +852,7 @@ class getID3
// MPEG - audio/video - MPEG (Moving Pictures Experts Group)
'mpeg' => array(
'pattern' => '^\x00\x00\x01(\xBA|\xB3)',
'pattern' => '^\\x00\\x00\\x01[\\xB3\\xBA]',
'group' => 'audio-video',
'module' => 'mpeg',
'mime_type' => 'video/mpeg',
@ -869,13 +889,13 @@ class getID3
'pattern' => '^(RIFF|SDSS|FORM)',
'group' => 'audio-video',
'module' => 'riff',
'mime_type' => 'audio/x-wave',
'mime_type' => 'audio/x-wav',
'fail_ape' => 'WARNING',
),
// Real - audio/video - RealAudio, RealVideo
'real' => array(
'pattern' => '^(\\.RMF|\\.ra)',
'pattern' => '^\\.(RMF|ra)',
'group' => 'audio-video',
'module' => 'real',
'mime_type' => 'audio/x-realaudio',
@ -891,7 +911,7 @@ class getID3
// TS - audio/video - MPEG-2 Transport Stream
'ts' => array(
'pattern' => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern
'pattern' => '^(\\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern
'group' => 'audio-video',
'module' => 'ts',
'mime_type' => 'video/MP2T',
@ -922,7 +942,7 @@ class getID3
// JPEG - still image - Joint Photographic Experts Group (JPEG)
'jpg' => array(
'pattern' => '^\xFF\xD8\xFF',
'pattern' => '^\\xFF\\xD8\\xFF',
'group' => 'graphic',
'module' => 'jpg',
'mime_type' => 'image/jpeg',
@ -932,7 +952,7 @@ class getID3
// PCD - still image - Kodak Photo CD
'pcd' => array(
'pattern' => '^.{2048}PCD_IPI\x00',
'pattern' => '^.{2048}PCD_IPI\\x00',
'group' => 'graphic',
'module' => 'pcd',
'mime_type' => 'image/x-photo-cd',
@ -943,7 +963,7 @@ class getID3
// PNG - still image - Portable Network Graphics (PNG)
'png' => array(
'pattern' => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
'pattern' => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A',
'group' => 'graphic',
'module' => 'png',
'mime_type' => 'image/png',
@ -954,7 +974,7 @@ class getID3
// SVG - still image - Scalable Vector Graphics (SVG)
'svg' => array(
'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")',
'group' => 'graphic',
'module' => 'svg',
'mime_type' => 'image/svg+xml',
@ -965,7 +985,7 @@ class getID3
// TIFF - still image - Tagged Information File Format (TIFF)
'tiff' => array(
'pattern' => '^(II\x2A\x00|MM\x00\x2A)',
'pattern' => '^(II\\x2A\\x00|MM\\x00\\x2A)',
'group' => 'graphic',
'module' => 'tiff',
'mime_type' => 'image/tiff',
@ -976,7 +996,7 @@ class getID3
// EFAX - still image - eFax (TIFF derivative)
'efax' => array(
'pattern' => '^\xDC\xFE',
'pattern' => '^\\xDC\\xFE',
'group' => 'graphic',
'module' => 'efax',
'mime_type' => 'image/efax',
@ -1000,7 +1020,7 @@ class getID3
// RAR - data - RAR compressed data
'rar' => array(
'pattern' => '^Rar\!',
'pattern' => '^Rar\\!',
'group' => 'archive',
'module' => 'rar',
'mime_type' => 'application/octet-stream',
@ -1010,7 +1030,7 @@ class getID3
// SZIP - audio/data - SZIP compressed data
'szip' => array(
'pattern' => '^SZ\x0A\x04',
'pattern' => '^SZ\\x0A\\x04',
'group' => 'archive',
'module' => 'szip',
'mime_type' => 'application/octet-stream',
@ -1020,7 +1040,7 @@ class getID3
// TAR - data - TAR compressed data
'tar' => array(
'pattern' => '^.{100}[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20\x00]{12}[0-9\x20\x00]{12}',
'pattern' => '^.{100}[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20\\x00]{12}[0-9\\x20\\x00]{12}',
'group' => 'archive',
'module' => 'tar',
'mime_type' => 'application/x-tar',
@ -1030,7 +1050,7 @@ class getID3
// GZIP - data - GZIP compressed data
'gz' => array(
'pattern' => '^\x1F\x8B\x08',
'pattern' => '^\\x1F\\x8B\\x08',
'group' => 'archive',
'module' => 'gzip',
'mime_type' => 'application/x-gzip',
@ -1040,7 +1060,7 @@ class getID3
// ZIP - data - ZIP compressed data
'zip' => array(
'pattern' => '^PK\x03\x04',
'pattern' => '^PK\\x03\\x04',
'group' => 'archive',
'module' => 'zip',
'mime_type' => 'application/zip',
@ -1053,7 +1073,7 @@ class getID3
// PAR2 - data - Parity Volume Set Specification 2.0
'par2' => array (
'pattern' => '^PAR2\x00PKT',
'pattern' => '^PAR2\\x00PKT',
'group' => 'misc',
'module' => 'par2',
'mime_type' => 'application/octet-stream',
@ -1063,7 +1083,7 @@ class getID3
// PDF - data - Portable Document Format
'pdf' => array(
'pattern' => '^\x25PDF',
'pattern' => '^\\x25PDF',
'group' => 'misc',
'module' => 'pdf',
'mime_type' => 'application/pdf',
@ -1073,7 +1093,7 @@ class getID3
// MSOFFICE - data - ZIP compressed data
'msoffice' => array(
'pattern' => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
'pattern' => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
'group' => 'misc',
'module' => 'msoffice',
'mime_type' => 'application/octet-stream',
@ -1114,14 +1134,14 @@ class getID3
}
if (preg_match('#\.mp[123a]$#i', $filename)) {
if (preg_match('#\\.mp[123a]$#i', $filename)) {
// Too many mp3 encoders on the market put gabage in front of mpeg files
// use assume format on these if format detection failed
$GetFileFormatArray = $this->GetFileFormatArray();
$info = $GetFileFormatArray['mp3'];
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
return $info;
} elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
} elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
// there's not really a useful consistent "magic" at the beginning of .cue files to identify them
// so until I think of something better, just go by filename if all other format checks fail
// and verify there's at least one instance of "TRACK xx AUDIO" in the file
@ -1222,13 +1242,14 @@ class getID3
continue;
}
$this->CharConvert($this->info['tags'][$tag_name], $this->info[$comment_name]['encoding']); // only copy gets converted!
if ($this->option_tags_html) {
foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
$this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
}
}
$this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!
}
}
@ -1352,8 +1373,8 @@ class getID3
if (!empty($VorbisCommentError)) {
$this->info['warning'][] = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError;
$this->info[$algorithm.'_data'] = false;
$this->warning('Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError);
$this->info[$algorithm.'_data'] = false;
} else {
@ -1582,6 +1603,17 @@ class getID3
return true;
}
public static function is_writable ($filename) {
$ret = is_writable($filename);
if (!$ret) {
$perms = fileperms($filename);
$ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
}
return $ret;
}
}
@ -1661,7 +1693,23 @@ abstract class getid3_handler {
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);
//return fread($this->getid3->fp, $bytes);
/*
* http://www.getid3.org/phpBB3/viewtopic.php?t=1930
* "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
* It seems to assume that fread() would always return as many bytes as were requested.
* However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
* The call may return only part of the requested data and a new call is needed to get more."
*/
$contents = '';
do {
$part = fread($this->getid3->fp, $bytes);
$partLength = strlen($part);
$bytes -= $partLength;
$contents .= $part;
} while (($bytes > 0) && ($partLength > 0));
return $contents;
}
protected function fseek($bytes, $whence=SEEK_SET) {
@ -1741,7 +1789,7 @@ abstract class getid3_handler {
// set up destination path
$dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory
if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory
throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
}
$dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');

View File

@ -266,14 +266,14 @@ class getid3_asf extends getid3_handler {
$offset += 16;
$thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
$info['warning'][] = 'header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')';
$this->warning('header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')');
//return false;
break;
}
$thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
$offset += 2;
if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
$info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"';
$this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"');
//return false;
break;
}
@ -316,7 +316,7 @@ class getid3_asf extends getid3_handler {
$offset += 16;
$thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
$info['warning'][] = 'codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}';
$this->warning('codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
//return false;
break;
}
@ -349,7 +349,7 @@ class getid3_asf extends getid3_handler {
if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
$info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"';
$this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"');
} else {
list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
@ -412,7 +412,7 @@ class getid3_asf extends getid3_handler {
break;
default:
$info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')';
$this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')');
break;
}
@ -458,7 +458,7 @@ class getid3_asf extends getid3_handler {
$offset += 16;
$thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
$info['warning'][] = 'script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}';
$this->warning('script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
//return false;
break;
}
@ -517,7 +517,7 @@ class getid3_asf extends getid3_handler {
$offset += 16;
$thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
$info['warning'][] = 'marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}';
$this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
break;
}
$thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
@ -525,7 +525,7 @@ class getid3_asf extends getid3_handler {
$thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
$offset += 2;
if ($thisfile_asf_markerobject['reserved_2'] != 0) {
$info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"';
$this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"');
break;
}
$thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
@ -576,7 +576,7 @@ class getid3_asf extends getid3_handler {
$thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
$offset += 16;
if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
$info['warning'][] = 'bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}';
$this->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}');
//return false;
break;
}
@ -637,7 +637,7 @@ class getid3_asf extends getid3_handler {
break;
default:
$info['warning'][] = 'error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}';
$this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}');
//return false;
break;
}
@ -761,7 +761,7 @@ class getid3_asf extends getid3_handler {
break;
default:
$info['warning'][] = 'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')';
$this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')');
//return false;
break;
}
@ -962,9 +962,9 @@ class getid3_asf extends getid3_handler {
default:
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
if ($this->GUIDname($NextObjectGUIDtext)) {
$info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
$this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
} else {
$info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
}
$offset += ($NextObjectSize - 16 - 8);
break;
@ -1183,7 +1183,7 @@ class getid3_asf extends getid3_handler {
$thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
$offset += 2;
if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
$info['warning'][] = 'data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"';
$this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');
//return false;
break;
}
@ -1319,9 +1319,9 @@ class getid3_asf extends getid3_handler {
default:
// Implementations shall ignore any standard or non-standard object that they do not know how to handle.
if ($this->GUIDname($NextObjectGUIDtext)) {
$info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8);
$this->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 '.($this->ftell() - 16 - 8);
$this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8));
}
$this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
break;
@ -1405,7 +1405,7 @@ class getid3_asf extends getid3_handler {
break;
default:
$info['warning'][] = 'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw'];
$this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']);
break;
}
@ -1917,9 +1917,9 @@ class getid3_asf extends getid3_handler {
default:
$unhandled_sections++;
if ($this->GUIDname($thisObject['guid_text'])) {
$this->getid3->info['warning'][] = 'unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8);
$this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8));
} else {
$this->getid3->info['warning'][] = 'unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8);
$this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8));
}
break;
}

View File

@ -93,7 +93,7 @@ class getid3_flv extends getid3_handler {
$TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
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']).'"';
$this->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;
}
@ -541,7 +541,7 @@ class AMFReader {
// Long string
default:
$value = '(unknown or unsupported data type)';
break;
break;
}
return $value;

View File

@ -234,7 +234,7 @@ class getid3_matroska extends getid3_handler
try {
$this->parseEBML($info);
} catch (Exception $e) {
$info['error'][] = 'EBML parser: '.$e->getMessage();
$this->error('EBML parser: '.$e->getMessage());
}
// calculate playtime
@ -330,11 +330,13 @@ class getid3_matroska extends getid3_handler
break;
case 'A_AC3':
case 'A_EAC3':
case 'A_DTS':
case 'A_MPEG/L3':
case 'A_MPEG/L2':
case 'A_FLAC':
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true);
$module_dataformat = ($track_info['dataformat'] == 'mp2' ? 'mp3' : ($track_info['dataformat'] == 'eac3' ? 'ac3' : $track_info['dataformat']));
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.$module_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');
@ -352,7 +354,7 @@ class getid3_matroska extends getid3_handler
}
// analyze
$class = 'getid3_'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
$class = 'getid3_'.$module_dataformat;
$header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
$getid3_audio = new $class($getid3_temp, __CLASS__);
if ($track_info['dataformat'] == 'flac') {
@ -457,6 +459,7 @@ class getid3_matroska extends getid3_handler
default:
$this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
break;
}
$info['audio']['streams'][] = $track_info;
@ -524,6 +527,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('header', __LINE__, $element_data);
break;
}
unset($element_data['offset'], $element_data['end']);
@ -562,15 +566,20 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); }
break;
}
if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
if (!isset($seek_entry['target_id'])) {
$this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']);
break;
}
if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required
$info['matroska']['seek'][] = $seek_entry;
}
break;
default:
$this->unhandledElement('seekhead', __LINE__, $seek_entry);
break;
}
}
break;
@ -653,6 +662,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('track.video', __LINE__, $sub_subelement);
break;
}
}
break;
@ -678,6 +688,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('track.audio', __LINE__, $sub_subelement);
break;
}
}
break;
@ -713,6 +724,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
break;
}
}
break;
@ -736,24 +748,28 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
break;
}
}
break;
default:
$this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
break;
}
}
break;
default:
$this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
break;
}
}
break;
default:
$this->unhandledElement('track', __LINE__, $subelement);
break;
}
}
@ -762,6 +778,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('tracks', __LINE__, $track_entry);
break;
}
}
break;
@ -825,6 +842,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
break;
}
}
$info_entry[$subelement['id_name']] = $chaptertranslate_entry;
@ -832,6 +850,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('info', __LINE__, $subelement);
break;
}
}
$info['matroska']['info'][] = $info_entry;
@ -868,6 +887,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
break;
}
}
$cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
@ -879,6 +899,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
break;
}
}
$cues_entry[] = $cuepoint_entry;
@ -886,6 +907,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('cues', __LINE__, $subelement);
break;
}
}
$info['matroska']['cues'] = $cues_entry;
@ -927,6 +949,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
break;
}
}
$tag_entry[$sub_subelement['id_name']] = $targets_entry;
@ -938,6 +961,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
break;
}
}
$tags_entry[] = $tag_entry;
@ -945,6 +969,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('tags', __LINE__, $subelement);
break;
}
}
$info['matroska']['tags'] = $tags_entry;
@ -985,6 +1010,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
break;
}
}
$info['matroska']['attachments'][] = $attachedfile_entry;
@ -992,6 +1018,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('attachments', __LINE__, $subelement);
break;
}
}
break;
@ -1051,6 +1078,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
break;
}
}
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
@ -1070,6 +1098,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
break;
}
}
$chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
@ -1077,6 +1106,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
break;
}
}
$editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
@ -1084,6 +1114,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
break;
}
}
$info['matroska']['chapters'][] = $editionentry_entry;
@ -1091,6 +1122,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('chapters', __LINE__, $subelement);
break;
}
}
break;
@ -1119,6 +1151,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
break;
}
}
$cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
@ -1149,6 +1182,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
break;
}
}
$cluster_entry[$subelement['id_name']][] = $cluster_block_group;
@ -1160,6 +1194,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('cluster', __LINE__, $subelement);
break;
}
$this->current_offset = $subelement['end'];
}
@ -1181,12 +1216,14 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('segment', __LINE__, $element_data);
break;
}
}
break;
default:
$this->unhandledElement('root', __LINE__, $top_element);
break;
}
}
}
@ -1339,6 +1376,7 @@ class getid3_matroska extends getid3_handler
default:
$this->unhandledElement('tag.simpletag', __LINE__, $element);
break;
}
}
@ -1490,6 +1528,7 @@ class getid3_matroska extends getid3_handler
$CodecIDlist['A_AAC'] = 'aac';
$CodecIDlist['A_AAC/MPEG2/LC'] = 'aac';
$CodecIDlist['A_AC3'] = 'ac3';
$CodecIDlist['A_EAC3'] = 'eac3';
$CodecIDlist['A_DTS'] = 'dts';
$CodecIDlist['A_FLAC'] = 'flac';
$CodecIDlist['A_MPEG/L1'] = 'mp1';

File diff suppressed because it is too large Load Diff

View File

@ -190,7 +190,7 @@ class getid3_riff extends getid3_handler {
$thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
$thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
$info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
$this->error('Corrupt RIFF file: bitrate_audio == zero');
return false;
}
$thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
@ -199,7 +199,7 @@ class getid3_riff extends getid3_handler {
$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
$info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
$this->warning('Audio codec = '.$thisfile_audio['codec']);
}
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
@ -302,10 +302,10 @@ class getid3_riff extends getid3_handler {
list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
$thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
} else {
$info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
$this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
}
} else {
$info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
$this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
}
$thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
$thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title'];
@ -385,10 +385,10 @@ class getid3_riff extends getid3_handler {
$SNDM_thisTagOffset += $SNDM_thisTagDataSize;
if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
$info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
$this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
break;
} elseif ($SNDM_thisTagSize <= 0) {
$info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
$this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
break;
}
$SNDM_startoffset += $SNDM_thisTagSize;
@ -397,7 +397,7 @@ class getid3_riff extends getid3_handler {
if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
$thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
} else {
$info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
$this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
}
}
@ -428,13 +428,15 @@ class getid3_riff extends getid3_handler {
}
if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
$samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
$thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
$timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
$thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
$h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600);
$m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60);
$s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
$f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
$thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f);
$thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f));
unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
}
unset($parsedXML);
}
@ -570,7 +572,7 @@ class getid3_riff extends getid3_handler {
// byte, in which case - skip warning
} else {
// Short by more than one byte, throw warning
$info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
}
break;
@ -579,11 +581,11 @@ class getid3_riff extends getid3_handler {
if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
// output file appears to be incorrectly *not* padded to nearest WORD boundary
// Output less severe warning
$info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
$this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
} else {
// Short by more than one byte, throw warning
$info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
$this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
$info['avdataend'] = $info['filesize'];
}
break;
@ -592,7 +594,7 @@ class getid3_riff extends getid3_handler {
if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
$info['avdataend']--;
$info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
}
}
if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
@ -619,7 +621,7 @@ class getid3_riff extends getid3_handler {
$info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
}
if ($info['avdataend'] > $info['filesize']) {
$info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)';
$this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
$info['avdataend'] = $info['filesize'];
}
}
@ -660,7 +662,7 @@ class getid3_riff extends getid3_handler {
$thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L)
if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
$info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
$this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
return false;
}
@ -858,7 +860,7 @@ class getid3_riff extends getid3_handler {
break;
default:
$info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
$this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
break;
}
@ -963,7 +965,7 @@ class getid3_riff extends getid3_handler {
// structures rounded to 2-byte boundary, but dumb encoders
// forget to pad end of file to make this actually work
} else {
$info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
$this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
}
$info['avdataend'] = $info['filesize'];
}
@ -1020,7 +1022,7 @@ class getid3_riff extends getid3_handler {
}
$thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate'];
if ($thisfile_audio['sample_rate'] == 0) {
$info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
$this->error('Corrupted AIFF file: sample_rate == zero');
return false;
}
$info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
@ -1080,7 +1082,7 @@ class getid3_riff extends getid3_handler {
$info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
$info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
if ($info['avdataend'] > $info['filesize']) {
$info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
$this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
}
}
@ -1112,7 +1114,7 @@ class getid3_riff extends getid3_handler {
break;
default:
$info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';
$this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
break;
}
}
@ -1130,7 +1132,7 @@ class getid3_riff extends getid3_handler {
break;
default:
$info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
$this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
break;
}
@ -1170,9 +1172,59 @@ class getid3_riff extends getid3_handler {
}
break;
case 'WEBP':
// https://developers.google.com/speed/webp/docs/riff_container
// https://tools.ietf.org/html/rfc6386
// https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
$info['fileformat'] = 'webp';
$info['mime_type'] = 'image/webp';
if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
$old_offset = $this->ftell();
$this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
$WEBP_VP8_header = $this->fread(10);
$this->fseek($old_offset);
if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
$thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
$thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
$thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
$thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0;
$thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
$thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
$thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
$thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
$info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
$info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
} else {
$this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
}
}
if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
$old_offset = $this->ftell();
$this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
$WEBP_VP8L_header = $this->fread(10);
$this->fseek($old_offset);
if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
$width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
$thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1;
$thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1;
$thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1));
$thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3));
$info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
$info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
} else {
$this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
}
}
break;
default:
$info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
$this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
//unset($info['fileformat']);
}
@ -1185,7 +1237,7 @@ class getid3_riff extends getid3_handler {
foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
$thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
$info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
$this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
}
}
@ -1509,7 +1561,7 @@ class getid3_riff extends getid3_handler {
$info['ac3'] = $getid3_temp->info['ac3'];
if (!empty($getid3_temp->info['warning'])) {
foreach ($getid3_temp->info['warning'] as $key => $value) {
$info['warning'][] = $value;
$this->warning($value);
}
}
}
@ -2583,4 +2635,4 @@ class getid3_riff extends getid3_handler {
return getid3_lib::BigEndian2Int($byteword, false, $signed);
}
}
}

View File

@ -20,7 +20,7 @@ class getid3_ac3 extends getid3_handler
private $AC3header = array();
private $BSIoffset = 0;
const syncword = "\x0B\x77";
const syncword = 0x0B77;
public function Analyze() {
$info = &$this->getid3->info;
@ -55,53 +55,389 @@ class getid3_ac3 extends getid3_handler
// } /* end of syncinfo */
$this->fseek($info['avdataoffset']);
$this->AC3header['syncinfo'] = $this->fread(5);
$tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
$this->AC3header['syncinfo'] = getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
$this->AC3header['bsi'] = getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
$thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
unset($tempAC3header);
if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) {
$thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
$offset = 2;
} else {
if ($this->AC3header['syncinfo'] !== self::syncword) {
if (!$this->isDependencyFor('matroska')) {
unset($info['fileformat'], $info['ac3']);
return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"');
return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
}
$offset = 0;
$this->fseek(-2, SEEK_CUR);
}
$info['audio']['dataformat'] = 'ac3';
$info['audio']['bitrate_mode'] = 'cbr';
$info['audio']['lossless'] = false;
$thisfile_ac3_raw['synchinfo']['crc1'] = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2));
$ac3_synchinfo_fscod_frmsizecod = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
$thisfile_ac3_raw['synchinfo']['fscod'] = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
$thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']);
if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) {
$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
}
$thisfile_ac3_raw_bsi['crc1'] = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); // 5.4.1.3
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); // 5.4.1.4
if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
$this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
}
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']);
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']);
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
$this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
$ac3_bsi_offset = 0;
if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
}
$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5);
if ($thisfile_ac3_raw_bsi['bsid'] > 8) {
// Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
// If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
// Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
}
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); // 5.4.2.10 compr: Compression Gain Word, 8 Bits
$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
}
$thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1); // 5.4.2.11 langcode: Language Code Exists, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); // 5.4.2.12 langcod: Language Code, 8 Bits
}
$thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1); // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); // 5.4.2.15 roomtyp: Room Type, 2 Bits
$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
$thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
}
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB'; // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
}
$thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
}
$thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
$thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
}
$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
$thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
$thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2); // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
$thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits
$thisfile_ac3['timecode1'] = 0;
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >> 9) * 3600; // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0<>23
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >> 3) * 60; // The next 6 bits represent the time in minutes, with valid values of 0<>59
$thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >> 0) * 8; // The final 3 bits represents the time in 8 second increments, with valid values of 0<>7 (representing 0, 8, 16, ... 56 seconds)
}
if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
$thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits
$thisfile_ac3['timecode2'] = 0;
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) * 1; // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0<>7 (representing 0-7 seconds)
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >> 6) * (1 / 30); // The next 5 bits represents the time in frames, with valid values from 0<>29 (one frame = 1/30th of a second)
$thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >> 0) * ((1 / 30) / 60); // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0<>63
}
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
$thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0<>63, indicating 1<>64 additional bytes, respectively.
$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
}
} elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
$info['audio']['dataformat'] = 'eac3';
$thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2);
$thisfile_ac3_raw_bsi['substreamid'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['frmsiz'] = $this->readHeaderBSI(11);
$thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2);
if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
$thisfile_ac3_raw_bsi['fscod2'] = $this->readHeaderBSI(2);
$thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
} else {
$thisfile_ac3_raw_bsi['numblkscod'] = $this->readHeaderBSI(2);
}
$thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['compr']) {
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
}
}
if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
$thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
$thisfile_ac3_raw_bsi['chanmap'] = $this->readHeaderBSI(8);
}
}
$thisfile_ac3_raw_bsi['flags']['mixmdat'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
$thisfile_ac3_raw_bsi['dmixmod'] = $this->readHeaderBSI(2);
}
if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
$thisfile_ac3_raw_bsi['ltrtcmixlev'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['lorocmixlev'] = $this->readHeaderBSI(3);
}
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
$thisfile_ac3_raw_bsi['ltrtsurmixlev'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['lorosurmixlev'] = $this->readHeaderBSI(3);
}
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
$thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
$thisfile_ac3_raw_bsi['lfemixlevcod'] = $this->readHeaderBSI(5);
}
}
if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
$thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
$thisfile_ac3_raw_bsi['pgmscl'] = $this->readHeaderBSI(6);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
$thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
$thisfile_ac3_raw_bsi['pgmscl2'] = $this->readHeaderBSI(6);
}
}
$thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
$thisfile_ac3_raw_bsi['extpgmscl'] = $this->readHeaderBSI(6);
}
$thisfile_ac3_raw_bsi['mixdef'] = $this->readHeaderBSI(2);
if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3);
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI(12);
} elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
$mixdefbitsread = 0;
$thisfile_ac3_raw_bsi['mixdeflen'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
$thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
$thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
$thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
$thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
$thisfile_ac3_raw_bsi['flags']['extpgmlscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
$thisfile_ac3_raw_bsi['extpgmlscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['extpgmcscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
$thisfile_ac3_raw_bsi['extpgmcscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['extpgmrscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
$thisfile_ac3_raw_bsi['extpgmrscl'] = $this->readHeaderBSI(4);
}
$thisfile_ac3_raw_bsi['flags']['extpgmlsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
$thisfile_ac3_raw_bsi['extpgmlsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['extpgmrsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
$thisfile_ac3_raw_bsi['extpgmrsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
$thisfile_ac3_raw_bsi['extpgmlfescl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['dmixscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
$thisfile_ac3_raw_bsi['dmixscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['addch'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['addch']) {
$thisfile_ac3_raw_bsi['flags']['extpgmaux1scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
$thisfile_ac3_raw_bsi['extpgmaux1scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
$thisfile_ac3_raw_bsi['flags']['extpgmaux2scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
$thisfile_ac3_raw_bsi['extpgmaux2scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4;
}
}
}
$thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
$thisfile_ac3_raw_bsi['spchdat'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
$thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
$thisfile_ac3_raw_bsi['spchdat1'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
$thisfile_ac3_raw_bsi['spchan1att'] = $this->readHeaderBSI(2); $mixdefbitsread += 2;
$thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
$thisfile_ac3_raw_bsi['spchdat2'] = $this->readHeaderBSI(5); $mixdefbitsread += 5;
$thisfile_ac3_raw_bsi['spchan2att'] = $this->readHeaderBSI(3); $mixdefbitsread += 3;
}
}
}
$mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
$mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
$thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI($mixdata_bits);
$thisfile_ac3_raw_bsi['mixdatafill'] = $this->readHeaderBSI($mixdata_fill);
unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
}
if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
$thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
$thisfile_ac3_raw_bsi['panmean'] = $this->readHeaderBSI(8);
$thisfile_ac3_raw_bsi['paninfo'] = $this->readHeaderBSI(6);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
$thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
$thisfile_ac3_raw_bsi['panmean2'] = $this->readHeaderBSI(8);
$thisfile_ac3_raw_bsi['paninfo2'] = $this->readHeaderBSI(6);
}
}
}
$thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
$thisfile_ac3_raw_bsi['blkmixcfginfo'][0] = $this->readHeaderBSI(5);
} else {
for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
$thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
$thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk] = $this->readHeaderBSI(5);
}
}
}
}
}
}
$thisfile_ac3_raw_bsi['flags']['infomdat'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['flags']['copyrightb'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['flags']['origbs'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['acmod'] == 2) { // if in 2/0 mode
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
$thisfile_ac3_raw_bsi['dheadphonmod'] = $this->readHeaderBSI(2);
}
if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { // if both surround channels exist
$thisfile_ac3_raw_bsi['dsurexmod'] = $this->readHeaderBSI(2);
}
$thisfile_ac3_raw_bsi['flags']['audprodi'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
$thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
$thisfile_ac3_raw_bsi['flags']['audprodi2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
$thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
}
}
if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
$thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
}
}
if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { // if both surround channels exist
$thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
}
if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { // if bit stream converted from AC-3
if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
$thisfile_ac3_raw_bsi['flags']['blkid'] = 1;
} else {
$thisfile_ac3_raw_bsi['flags']['blkid'] = (bool) $this->readHeaderBSI(1);
}
if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
$thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6);
}
}
$thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
$thisfile_ac3_raw_bsi['addbsil'] = $this->readHeaderBSI(6);
$thisfile_ac3_raw_bsi['addbsi'] = $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
}
} else {
$this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
unset($info['ac3']);
return false;
}
$thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
$thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
} else {
$thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
}
if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
$info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
} else {
$this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
}
if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
$thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
$thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
} elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
// this isn't right, but it's (usually) close, roughly 5% less than it should be.
// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
$thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
// kludge-fix to make it approximately the expected value, still not "right":
$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
}
$info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
$thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
$ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
@ -123,114 +459,14 @@ class getid3_ac3 extends getid3_handler
}
$info['audio']['channels'] = $thisfile_ac3['num_channels'];
if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
// If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
$thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
$thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
}
if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
// If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
$thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
$thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
// When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
$thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
$thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
}
$thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon'];
if ($thisfile_ac3_raw_bsi['lfeon']) {
//$info['audio']['channels']++;
$thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
$info['audio']['channels'] .= '.1';
}
$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']);
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
$thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
$thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
$thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
$thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['compre_flag']) {
$thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
$thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
}
$thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['langcode_flag']) {
$thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);
}
$thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['audprodie']) {
$thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);
$thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
$thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
}
if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {
// If acmod is 0, then two completely independent program channels (dual mono)
// are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
// a number of additional items are present in BSI or audblk to fully describe Ch2.
// This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
// The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
$thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
$thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
$thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['compre_flag2']) {
$thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
$thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
}
$thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['langcode_flag2']) {
$thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);
}
$thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['audprodie2']) {
$thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
$thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);
$thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
$thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
}
}
$thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1);
$thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['timecode1_flag']) {
$thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);
}
$thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
$thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
}
$thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);
if ($thisfile_ac3_raw_bsi['addbsi_flag']) {
$thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);
$this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
$thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
$this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
}
return true;
}
@ -251,6 +487,16 @@ class getid3_ac3 extends getid3_handler
return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
}
public static function sampleRateCodeLookup2($fscod2) {
static $sampleRateCodeLookup2 = array(
0 => 24000,
1 => 22050,
2 => 16000,
3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
);
return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
}
public static function serviceTypeLookup($bsmod, $acmod) {
static $serviceTypeLookup = array();
if (empty($serviceTypeLookup)) {
@ -409,31 +655,32 @@ class getid3_ac3 extends getid3_handler
}
public static function frameSizeLookup($frmsizecod, $fscod) {
$padding = (bool) ($frmsizecod % 2);
$framesizeid = floor($frmsizecod / 2);
// LSB is whether padding is used or not
$padding = (bool) ($frmsizecod & 0x01);
$framesizeid = ($frmsizecod & 0x3E) >> 1;
static $frameSizeLookup = array();
if (empty($frameSizeLookup)) {
$frameSizeLookup = array (
0 => array(128, 138, 192),
1 => array(40, 160, 174, 240),
2 => array(48, 192, 208, 288),
3 => array(56, 224, 242, 336),
4 => array(64, 256, 278, 384),
5 => array(80, 320, 348, 480),
6 => array(96, 384, 416, 576),
7 => array(112, 448, 486, 672),
8 => array(128, 512, 556, 768),
9 => array(160, 640, 696, 960),
10 => array(192, 768, 834, 1152),
11 => array(224, 896, 974, 1344),
12 => array(256, 1024, 1114, 1536),
13 => array(320, 1280, 1392, 1920),
14 => array(384, 1536, 1670, 2304),
15 => array(448, 1792, 1950, 2688),
16 => array(512, 2048, 2228, 3072),
17 => array(576, 2304, 2506, 3456),
18 => array(640, 2560, 2786, 3840)
0 => array( 128, 138, 192), // 32 kbps
1 => array( 160, 174, 240), // 40 kbps
2 => array( 192, 208, 288), // 48 kbps
3 => array( 224, 242, 336), // 56 kbps
4 => array( 256, 278, 384), // 64 kbps
5 => array( 320, 348, 480), // 80 kbps
6 => array( 384, 416, 576), // 96 kbps
7 => array( 448, 486, 672), // 112 kbps
8 => array( 512, 556, 768), // 128 kbps
9 => array( 640, 696, 960), // 160 kbps
10 => array( 768, 834, 1152), // 192 kbps
11 => array( 896, 974, 1344), // 224 kbps
12 => array(1024, 1114, 1536), // 256 kbps
13 => array(1280, 1392, 1920), // 320 kbps
14 => array(1536, 1670, 2304), // 384 kbps
15 => array(1792, 1950, 2688), // 448 kbps
16 => array(2048, 2228, 3072), // 512 kbps
17 => array(2304, 2506, 3456), // 576 kbps
18 => array(2560, 2786, 3840) // 640 kbps
);
}
if (($fscod == 1) && $padding) {
@ -444,19 +691,21 @@ class getid3_ac3 extends getid3_handler
}
public static function bitrateLookup($frmsizecod) {
$framesizeid = floor($frmsizecod / 2);
// LSB is whether padding is used or not
$padding = (bool) ($frmsizecod & 0x01);
$framesizeid = ($frmsizecod & 0x3E) >> 1;
static $bitrateLookup = array(
0 => 32000,
1 => 40000,
2 => 48000,
3 => 56000,
4 => 64000,
5 => 80000,
6 => 96000,
7 => 112000,
8 => 128000,
9 => 160000,
0 => 32000,
1 => 40000,
2 => 48000,
3 => 56000,
4 => 64000,
5 => 80000,
6 => 96000,
7 => 112000,
8 => 128000,
9 => 160000,
10 => 192000,
11 => 224000,
12 => 256000,
@ -465,10 +714,20 @@ class getid3_ac3 extends getid3_handler
15 => 448000,
16 => 512000,
17 => 576000,
18 => 640000
18 => 640000,
);
return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
}
public static function blocksPerSyncFrame($numblkscod) {
static $blocksPerSyncFrameLookup = array(
0 => 1,
1 => 2,
2 => 3,
3 => 6,
);
return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false);
}
}

View File

@ -34,7 +34,7 @@ class getid3_mp3 extends getid3_handler
if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
if ($this->allow_bruteforce) {
$info['error'][] = 'Rescanning file in BruteForce mode';
$this->error('Rescanning file in BruteForce mode');
$this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
}
}
@ -72,7 +72,7 @@ class getid3_mp3 extends getid3_handler
}
}
$info['warning'][] = $synchoffsetwarning;
$this->warning($synchoffsetwarning);
}
@ -134,7 +134,7 @@ class getid3_mp3 extends getid3_handler
break;
default:
$info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';
$this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"');
break;
}
}
@ -424,7 +424,7 @@ class getid3_mp3 extends getid3_handler
}
if ($this->fseek($offset) != 0) {
$info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;
$this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset);
return false;
}
//$headerstring = $this->fread(1441); // worst-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
@ -437,19 +437,19 @@ class getid3_mp3 extends getid3_handler
// and $cc... is the audio data
$head4 = substr($headerstring, 0, 4);
$head4_key = getid3_lib::PrintHexBytes($head4, true, false, false);
static $MPEGaudioHeaderDecodeCache = array();
if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) {
$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key];
} else {
$MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4);
$MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
$MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray;
}
static $MPEGaudioHeaderValidCache = array();
if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache
//$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache
//$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)
$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);
}
// shortcut
@ -459,10 +459,10 @@ class getid3_mp3 extends getid3_handler
$thisfile_mpeg_audio = &$info['mpeg']['audio'];
if ($MPEGaudioHeaderValidCache[$head4]) {
if ($MPEGaudioHeaderValidCache[$head4_key]) {
$thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
} else {
$info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;
$this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);
return false;
}
@ -490,7 +490,7 @@ class getid3_mp3 extends getid3_handler
if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) {
// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
$info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
$this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1');
$thisfile_mpeg_audio['raw']['bitrate'] = 0;
}
$thisfile_mpeg_audio['padding'] = (bool) $thisfile_mpeg_audio['raw']['padding'];
@ -512,7 +512,7 @@ class getid3_mp3 extends getid3_handler
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] <= 192000)) {
// these are ok
} else {
$info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
$this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
return false;
}
break;
@ -523,7 +523,7 @@ class getid3_mp3 extends getid3_handler
if (($thisfile_mpeg_audio['bitrate'] == 'free') || ($thisfile_mpeg_audio['bitrate'] == 64000) || ($thisfile_mpeg_audio['bitrate'] >= 96000)) {
// these are ok
} else {
$info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';
$this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.');
return false;
}
break;
@ -545,7 +545,7 @@ class getid3_mp3 extends getid3_handler
if (isset($thisfile_mpeg_audio['framelength'])) {
$nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength'];
} else {
$info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';
$this->error('Frame at offset('.$offset.') is has an invalid frame length.');
return false;
}
@ -648,9 +648,20 @@ class getid3_mp3 extends getid3_handler
}
//if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
//if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
$used_filesize = 0;
if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
$used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
} elseif (!empty($info['filesize'])) {
$used_filesize = $info['filesize'];
$used_filesize -= intval(@$info['id3v2']['headerlength']);
$used_filesize -= (isset($info['id3v1']) ? 128 : 0);
$used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
$this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
}
$framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
$framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
if ($thisfile_mpeg_audio['layer'] == '1') {
// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
@ -837,7 +848,7 @@ class getid3_mp3 extends getid3_handler
$thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF);
$thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame);
if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) {
$info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';
$this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org');
}
if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) {
// this may change if 3.90.4 ever comes out
@ -881,7 +892,7 @@ class getid3_mp3 extends getid3_handler
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
}
if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') {
$info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
$this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.');
}
}
@ -908,12 +919,12 @@ class getid3_mp3 extends getid3_handler
// $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';
// $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
// } else {
// $info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
// $this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
// }
} else {
$info['warning'][] = 'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
$this->warning('Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($info['avdataend'] - $info['avdataoffset']).' ('.(($info['avdataend'] - $info['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)');
}
}
}
@ -931,7 +942,7 @@ class getid3_mp3 extends getid3_handler
$info['audio']['bitrate'] = (($framebytelength - intval($thisfile_mpeg_audio['padding'])) * $thisfile_mpeg_audio['sample_rate']) / 144;
}
} else {
$info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';
$this->error('Error calculating frame length of free-format MP3 without Xing/LAME header');
}
}
}
@ -948,7 +959,7 @@ class getid3_mp3 extends getid3_handler
}
$thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
$info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
$info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate'];
$thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
}
break;
@ -1074,7 +1085,7 @@ class getid3_mp3 extends getid3_handler
public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
$info = &$this->getid3->info;
$firstframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
$firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
$this->decodeMPEGaudioHeader($offset, $firstframetestarray, false);
for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) {
@ -1084,7 +1095,7 @@ class getid3_mp3 extends getid3_handler
return true;
}
$nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
if ($ScanAsCBR) {
// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header
@ -1098,7 +1109,7 @@ class getid3_mp3 extends getid3_handler
if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
} else {
$info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';
$this->error('Frame at offset ('.$offset.') is has an invalid frame length.');
return false;
}
@ -1110,7 +1121,7 @@ class getid3_mp3 extends getid3_handler
} else {
// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
$info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
$this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.');
return false;
}
@ -1153,10 +1164,10 @@ class getid3_mp3 extends getid3_handler
$framelength = $framelength2;
}
if (!$framelength) {
$info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;
$this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset);
return false;
} else {
$info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
$this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)');
$info['audio']['codec'] = 'LAME';
$info['audio']['encoder'] = 'LAME3.88';
$SyncPattern1 = substr($SyncPattern1, 0, 3);
@ -1183,7 +1194,7 @@ class getid3_mp3 extends getid3_handler
$ActualFrameLengthValues[] = ($framelength + 1);
$nextoffset++;
} else {
$info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;
$this->error('Did not find expected free-format sync pattern at offset '.$nextoffset);
return false;
}
$nextoffset += $framelength;
@ -1281,7 +1292,7 @@ class getid3_mp3 extends getid3_handler
getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
$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.';
$this->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) {
$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned);
@ -1308,13 +1319,13 @@ class getid3_mp3 extends getid3_handler
$info['mpeg']['audio']['version_distribution'] = $Distribution['version'];
$info['mpeg']['audio']['padding_distribution'] = $Distribution['padding'];
if (count($Distribution['version']) > 1) {
$info['error'][] = 'Corrupt file - more than one MPEG version detected';
$this->error('Corrupt file - more than one MPEG version detected');
}
if (count($Distribution['layer']) > 1) {
$info['error'][] = 'Corrupt file - more than one MPEG layer detected';
$this->error('Corrupt file - more than one MPEG layer detected');
}
if (count($Distribution['frequency']) > 1) {
$info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';
$this->error('Corrupt file - more than one MPEG sample rate detected');
}
@ -1326,7 +1337,7 @@ class getid3_mp3 extends getid3_handler
}
$info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']);
if ($info['mpeg']['audio']['frame_count'] == 0) {
$info['error'][] = 'no MPEG audio frames found';
$this->error('no MPEG audio frames found');
return false;
}
$info['mpeg']['audio']['bitrate'] = ($bittotal / $info['mpeg']['audio']['frame_count']);
@ -1361,7 +1372,7 @@ class getid3_mp3 extends getid3_handler
$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;
$this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset);
return false;
}
$header = $this->fread($sync_seek_buffer_size);
@ -1372,7 +1383,7 @@ class getid3_mp3 extends getid3_handler
if ($SynchSeekOffset > $sync_seek_buffer_size) {
// if a synch's not found within the first 128k bytes, then give up
$info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';
$this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB');
if (isset($info['audio']['bitrate'])) {
unset($info['audio']['bitrate']);
}
@ -1386,7 +1397,7 @@ class getid3_mp3 extends getid3_handler
} elseif (feof($this->getid3->fp)) {
$info['error'][] = 'Could not find valid MPEG audio synch before end of file';
$this->error('Could not find valid MPEG audio synch before end of file');
if (isset($info['audio']['bitrate'])) {
unset($info['audio']['bitrate']);
}
@ -1401,7 +1412,7 @@ class getid3_mp3 extends getid3_handler
}
if (($SynchSeekOffset + 1) >= strlen($header)) {
$info['error'][] = 'Could not find valid MPEG synch before end of file';
$this->error('Could not find valid MPEG synch before end of file');
return false;
}
@ -1444,9 +1455,9 @@ class getid3_mp3 extends getid3_handler
if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) {
$info = $dummy;
$info['avdataoffset'] = $GarbageOffsetEnd;
$info['warning'][] = 'apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd;
$this->warning('apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);
} else {
$info['warning'][] = 'using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')';
$this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');
}
}
}
@ -1539,7 +1550,7 @@ class getid3_mp3 extends getid3_handler
}
}
if ($pct_data_scanned > 0) {
$info['warning'][] = 'too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.';
$this->warning('too many MPEG audio frames to scan, only scanned '.$frames_scanned.' frames in '.$max_scan_segments.' segments ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
foreach ($info['mpeg']['audio'] as $key1 => $value1) {
if (!preg_match('#_distribution$#i', $key1)) {
continue;
@ -1551,7 +1562,7 @@ class getid3_mp3 extends getid3_handler
}
if ($SynchErrorsFound > 0) {
$info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';
$this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis');
//return false;
}
@ -1564,7 +1575,7 @@ class getid3_mp3 extends getid3_handler
}
}
if ($framecounter == 0) {
$info['error'][] = 'Corrupt MP3 file: framecounter == zero';
$this->error('Corrupt MP3 file: framecounter == zero');
return false;
}
$info['mpeg']['audio']['frame_count'] = getid3_lib::CastAsInt($framecounter);
@ -1599,7 +1610,7 @@ class getid3_mp3 extends getid3_handler
if (empty($info['mpeg']['audio'])) {
$info['error'][] = 'could not find valid MPEG synch before end of file';
$this->error('could not find valid MPEG synch before end of file');
if (isset($info['audio']['bitrate'])) {
unset($info['audio']['bitrate']);
}

View File

@ -26,13 +26,13 @@ class getid3_ogg extends getid3_handler
// Warn about illegal tags - only vorbiscomments are allowed
if (isset($info['id3v2'])) {
$info['warning'][] = 'Illegal ID3v2 tag present.';
$this->warning('Illegal ID3v2 tag present.');
}
if (isset($info['id3v1'])) {
$info['warning'][] = 'Illegal ID3v1 tag present.';
$this->warning('Illegal ID3v1 tag present.');
}
if (isset($info['ape'])) {
$info['warning'][] = 'Illegal APE tag present.';
$this->warning('Illegal APE tag present.');
}
@ -44,7 +44,7 @@ class getid3_ogg extends getid3_handler
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo;
if ($this->ftell() >= $this->getid3->fread_buffer_size()) {
$info['error'][] = 'Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)';
$this->error('Could not find start of Ogg page in the first '.$this->getid3->fread_buffer_size().' bytes (this might not be an Ogg-Vorbis file?)');
unset($info['fileformat']);
unset($info['ogg']);
return false;
@ -179,7 +179,7 @@ class getid3_ogg extends getid3_handler
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';
$this->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") {
@ -240,7 +240,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
} elseif (substr($filedata, 1, 6) == 'theora') {
$info['video']['dataformat'] = 'theora1';
$info['error'][] = 'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']';
$this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']');
//break;
} elseif (substr($filedata, 1, 6) == 'vorbis') {
@ -248,7 +248,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
} else {
$info['error'][] = 'unexpected';
$this->error('unexpected');
//break;
}
//} while ($oggpageinfo['page_seqno'] == 0);
@ -256,12 +256,12 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$this->fseek($oggpageinfo['page_start_offset']);
$info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']';
$this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
//return false;
} else {
$info['error'][] = 'Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"';
$this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"');
unset($info['ogg']);
unset($info['mime_type']);
return false;
@ -284,7 +284,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
case 'flac':
$flac = new getid3_flac($this->getid3);
if (!$flac->parseMETAdata()) {
$info['error'][] = 'Failed to parse FLAC headers';
$this->error('Failed to parse FLAC headers');
return false;
}
unset($flac);
@ -299,7 +299,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
$info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
if(substr($filedata, 0, 8) != 'OpusTags') {
$info['error'][] = 'Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"';
$this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"');
return false;
}
@ -311,7 +311,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
// Last Page - Number of Samples
if (!getid3_lib::intValueSupported($info['avdataend'])) {
$info['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)';
$this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)');
} else {
@ -323,7 +323,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$info['ogg']['pageheader']['eos'] = $this->ParseOggPageHeader();
$info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position'];
if ($info['ogg']['samples'] == 0) {
$info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero';
$this->error('Corrupt Ogg file: eos.number of samples == zero');
return false;
}
if (!empty($info['audio']['sample_rate'])) {
@ -342,7 +342,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
}
if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) {
if ($info['audio']['bitrate'] == 0) {
$info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero';
$this->error('Corrupt Ogg file: bitrate_audio == zero');
return false;
}
$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $info['audio']['bitrate']);
@ -395,7 +395,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$info['ogg']['samplerate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4));
$filedataoffset += 4;
if ($info['ogg']['samplerate'] == 0) {
$info['error'][] = 'Corrupt Ogg file: sample rate == zero';
$this->error('Corrupt Ogg file: sample rate == zero');
return false;
}
$info['audio']['sample_rate'] = $info['ogg']['samplerate'];
@ -443,7 +443,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$filedataoffset += 1;
if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
$info['error'][] = 'Unknown opus version number (only accepting 1-15)';
$this->error('Unknown opus version number (only accepting 1-15)');
return false;
}
@ -451,7 +451,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$filedataoffset += 1;
if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
$info['error'][] = 'Invalid channel count in opus header (must not be zero)';
$this->error('Invalid channel count in opus header (must not be zero)');
return false;
}
@ -562,6 +562,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
default:
return false;
break;
}
$VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
@ -580,7 +581,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
if ($i >= 10000) {
// https://github.com/owncloud/music/issues/212#issuecomment-43082336
$info['warning'][] = 'Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments';
$this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments');
break;
}
@ -618,7 +619,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
$commentdataoffset += 4;
while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) {
if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) {
$info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments';
$this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments');
break 2;
}
@ -642,12 +643,12 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
//$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) {
$info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
$this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
break;
}
$readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1);
if ($readlength <= 0) {
$info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();
$this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell());
break;
}
$commentdata .= $this->fread($readlength);
@ -661,7 +662,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
if (!$commentstring) {
// no comment?
$info['warning'][] = 'Blank Ogg comment ['.$i.']';
$this->warning('Blank Ogg comment ['.$i.']');
} elseif (strstr($commentstring, '=')) {
@ -711,7 +712,7 @@ $info['warning'][] = 'Ogg Theora (v3) not fully supported in this version of get
} else {
$info['warning'][] = '[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring;
$this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring);
}
unset($ThisFileInfo_ogg_comments_raw[$i]);

View File

@ -23,7 +23,7 @@ class getid3_apetag extends getid3_handler
$info = &$this->getid3->info;
if (!getid3_lib::intValueSupported($info['filesize'])) {
$info['warning'][] = 'Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
$this->warning('Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
return false;
}
@ -72,7 +72,7 @@ class getid3_apetag extends getid3_handler
$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'];
$this->error('Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']);
return false;
}
@ -88,7 +88,7 @@ class getid3_apetag extends getid3_handler
$info['avdataend'] = $thisfile_ape['tag_offset_start'];
if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) {
$info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data';
$this->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data');
unset($info['id3v1']);
foreach ($info['warning'] as $key => $value) {
if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
@ -104,7 +104,7 @@ class getid3_apetag extends getid3_handler
if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) {
$offset += $apetagheadersize;
} else {
$info['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start'];
$this->error('Error parsing APE header at offset '.$thisfile_ape['tag_offset_start']);
return false;
}
}
@ -119,7 +119,7 @@ class getid3_apetag extends getid3_handler
$item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
$offset += 4;
if (strstr(substr($APEtagData, $offset), "\x00") === false) {
$info['error'][] = 'Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset);
$this->error('Cannot find null-byte (0x00) separator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset));
return false;
}
$ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset;
@ -154,7 +154,7 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
$thisfile_replaygain['track']['originator'] = 'unspecified';
} else {
$info['warning'][] = 'MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -163,10 +163,10 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
$thisfile_replaygain['track']['originator'] = 'unspecified';
if ($thisfile_replaygain['track']['peak'] <= 0) {
$info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
$this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
}
} else {
$info['warning'][] = 'MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -175,7 +175,7 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
$thisfile_replaygain['album']['originator'] = 'unspecified';
} else {
$info['warning'][] = 'MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -184,10 +184,10 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
$thisfile_replaygain['album']['originator'] = 'unspecified';
if ($thisfile_replaygain['album']['peak'] <= 0) {
$info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
$this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
}
} else {
$info['warning'][] = 'MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -198,7 +198,7 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
$thisfile_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false);
} else {
$info['warning'][] = 'MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -208,7 +208,7 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
$thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
} else {
$info['warning'][] = 'MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -218,7 +218,7 @@ class getid3_apetag extends getid3_handler
$thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
$thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
} else {
$info['warning'][] = 'MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
$this->warning('MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
}
break;
@ -253,19 +253,23 @@ class getid3_apetag extends getid3_handler
case 'cover art (studio)':
// list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html
if (is_array($thisfile_ape_items_current['data'])) {
$info['warning'][] = 'APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8';
$this->warning('APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8');
$thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']);
}
list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2);
$thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00");
$thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']);
$thisfile_ape_items_current['image_mime'] = '';
$imageinfo = array();
$imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
$thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
do {
$thisfile_ape_items_current['image_mime'] = '';
$imageinfo = array();
$imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
if (($imagechunkcheck === false) || !isset($imagechunkcheck[2])) {
$this->warning('APEtag "'.$item_key.'" contains invalid image data');
break;
}
$thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
if ($this->inline_attachments === false) {
// skip entirely
unset($thisfile_ape_items_current['data']);
@ -276,15 +280,15 @@ class getid3_apetag extends getid3_handler
} elseif (is_int($this->inline_attachments)) {
if ($this->inline_attachments < $thisfile_ape_items_current['data_length']) {
// too big, skip
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)';
$this->warning('attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)');
unset($thisfile_ape_items_current['data']);
break;
}
} elseif (is_string($this->inline_attachments)) {
$this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR);
if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) {
if (!is_dir($this->inline_attachments) || !getID3::is_writable($this->inline_attachments)) {
// cannot write, skip
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)';
$this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)');
unset($thisfile_ape_items_current['data']);
break;
}
@ -292,10 +296,10 @@ class getid3_apetag extends getid3_handler
// if we get this far, must be OK
if (is_string($this->inline_attachments)) {
$destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset'];
if (!file_exists($destination_filename) || is_writable($destination_filename)) {
if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) {
file_put_contents($destination_filename, $thisfile_ape_items_current['data']);
} else {
$info['warning'][] = 'attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)';
$this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)');
}
$thisfile_ape_items_current['data_filename'] = $destination_filename;
unset($thisfile_ape_items_current['data']);

View File

@ -22,7 +22,7 @@ class getid3_id3v1 extends getid3_handler
$info = &$this->getid3->info;
if (!getid3_lib::intValueSupported($info['filesize'])) {
$info['warning'][] = 'Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
$this->warning('Unable to check for ID3v1 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
return false;
}
@ -60,6 +60,26 @@ class getid3_id3v1 extends getid3_handler
foreach ($ParsedID3v1 as $key => $value) {
$ParsedID3v1['comments'][$key][0] = $value;
}
// ID3v1 encoding detection hack START
// ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
// Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
$ID3v1encoding = 'ISO-8859-1';
foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
foreach ($valuearray as $key => $value) {
if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
$ID3v1encoding = $id3v1_bad_encoding;
break 3;
} elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
$ID3v1encoding = $id3v1_bad_encoding;
break 3;
}
}
}
}
}
// ID3v1 encoding detection hack END
// ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
$GoodFormatID3v1tag = $this->GenerateID3v1Tag(
@ -73,13 +93,14 @@ class getid3_id3v1 extends getid3_handler
$ParsedID3v1['padding_valid'] = true;
if ($id3v1tag !== $GoodFormatID3v1tag) {
$ParsedID3v1['padding_valid'] = false;
$info['warning'][] = 'Some ID3v1 fields do not use NULL characters for padding';
$this->warning('Some ID3v1 fields do not use NULL characters for padding');
}
$ParsedID3v1['tag_offset_end'] = $info['filesize'];
$ParsedID3v1['tag_offset_start'] = $ParsedID3v1['tag_offset_end'] - 128;
$info['id3v1'] = $ParsedID3v1;
$info['id3v1']['encoding'] = $ID3v1encoding;
}
if (substr($preid3v1, 0, 3) == 'TAG') {
@ -95,7 +116,7 @@ class getid3_id3v1 extends getid3_handler
// a Lyrics3 tag footer was found before the last ID3v1, assume false "TAG" synch
} else {
// APE and Lyrics3 footers not found - assume double ID3v1
$info['warning'][] = 'Duplicate ID3v1 tag detected - this has been known to happen with iTunes';
$this->warning('Duplicate ID3v1 tag detected - this has been known to happen with iTunes');
$info['avdataend'] -= 128;
}
}

View File

@ -71,7 +71,7 @@ class getid3_id3v2 extends getid3_handler
if ($id3v2_majorversion > 4) { // this script probably won't correctly parse ID3v2.5.x and above (if it ever exists)
$info['error'][] = 'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion'];
$this->error('this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion']);
return false;
}
@ -241,7 +241,7 @@ class getid3_id3v2 extends getid3_handler
}
if ($thisfile_id3v2['exthead']['length'] != $extended_header_offset) {
$info['warning'][] = 'ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')';
$this->warning('ID3v2.4 extended header length mismatch (expecting '.intval($thisfile_id3v2['exthead']['length']).', found '.intval($extended_header_offset).')');
}
}
@ -260,7 +260,7 @@ class getid3_id3v2 extends getid3_handler
if ($framedata{$i} != "\x00") {
$thisfile_id3v2['padding']['valid'] = false;
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
$info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
break;
}
}
@ -300,7 +300,7 @@ class getid3_id3v2 extends getid3_handler
} elseif (($frame_name == "\x00".'MP3') || ($frame_name == "\x00\x00".'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) {
// MP3ext known broken frames - "ok" for the purposes of this test
} elseif (($id3v2_majorversion == 4) && ($this->IsValidID3v2FrameName(substr($framedata, getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) {
$info['warning'][] = 'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3';
$this->warning('ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3');
$id3v2_majorversion = 3;
$frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer
}
@ -322,16 +322,16 @@ class getid3_id3v2 extends getid3_handler
if ($framedata{$i} != "\x00") {
$thisfile_id3v2['padding']['valid'] = false;
$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
$info['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';
$this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
break;
}
}
break; // skip rest of ID3v2 header
}
if ($frame_name == 'COM ') {
$info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably others too)]';
$frame_name = 'COMM';
if ($iTunesBrokenFrameNameFixed = self::ID3v22iTunesBrokenFrameName($frame_name)) {
$this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by iTunes (versions "X v2.0.3", "v3.0.1", "v7.0.0.70" are known-guilty, probably others too)]. Translated frame name from "'.str_replace("\x00", ' ', $frame_name).'" to "'.$iTunesBrokenFrameNameFixed.'" for parsing.');
$frame_name = $iTunesBrokenFrameNameFixed;
}
if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) {
@ -355,28 +355,28 @@ class getid3_id3v2 extends getid3_handler
// next frame is valid, just skip the current frame
$framedata = substr($framedata, $frame_size);
$info['warning'][] = 'Next ID3v2 frame is valid, skipping current frame.';
$this->warning('Next ID3v2 frame is valid, skipping current frame.');
} else {
// next frame is invalid too, abort processing
//unset($framedata);
$framedata = null;
$info['error'][] = 'Next ID3v2 frame is also invalid, aborting processing.';
$this->error('Next ID3v2 frame is also invalid, aborting processing.');
}
} elseif ($frame_size == strlen($framedata)) {
// this is the last frame, just skip
$info['warning'][] = 'This was the last ID3v2 frame.';
$this->warning('This was the last ID3v2 frame.');
} else {
// next frame is invalid too, abort processing
//unset($framedata);
$framedata = null;
$info['warning'][] = 'Invalid ID3v2 frame size, aborting.';
$this->warning('Invalid ID3v2 frame size, aborting.');
}
if (!$this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion)) {
@ -389,21 +389,21 @@ class getid3_id3v2 extends getid3_handler
case "\x00".'MP':
case ' MP':
case 'MP3':
$info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]';
$this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))). [Note: this particular error has been known to happen with tags edited by "MP3ext (www.mutschler.de/mp3ext/)"]');
break;
default:
$info['warning'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).';
$this->warning('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: !IsValidID3v2FrameName("'.str_replace("\x00", ' ', $frame_name).'", '.$id3v2_majorversion.'))).');
break;
}
} elseif (!isset($framedata) || ($frame_size > strlen($framedata))) {
$info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).';
$this->error('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag). (ERROR: $frame_size ('.$frame_size.') > strlen($framedata) ('.(isset($framedata) ? strlen($framedata) : 'null').')).');
} else {
$info['error'][] = 'error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).';
$this->error('error parsing "'.$frame_name.'" ('.$framedataoffset.' bytes into the ID3v2.'.$id3v2_majorversion.' tag).');
}
@ -442,10 +442,14 @@ class getid3_id3v2 extends getid3_handler
} // end footer
if (isset($thisfile_id3v2['comments']['genre'])) {
$genres = array();
foreach ($thisfile_id3v2['comments']['genre'] as $key => $value) {
unset($thisfile_id3v2['comments']['genre'][$key]);
$thisfile_id3v2['comments'] = getid3_lib::array_merge_noclobber($thisfile_id3v2['comments'], array('genre'=>$this->ParseID3v2GenreString($value)));
foreach ($this->ParseID3v2GenreString($value) as $genre) {
$genres[] = $genre;
}
}
$thisfile_id3v2['comments']['genre'] = array_unique($genres);
unset($key, $value, $genres, $genre);
}
if (isset($thisfile_id3v2['comments']['track'])) {
@ -500,9 +504,28 @@ class getid3_id3v2 extends getid3_handler
// ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
// ID3v2.4.x: '21' $00 'Eurodisco' $00
$clean_genres = array();
// hack-fixes for some badly-written ID3v2.3 taggers, while trying not to break correctly-written tags
if (($this->getid3->info['id3v2']['majorversion'] == 3) && !preg_match('#[\x00]#', $genrestring)) {
// note: MusicBrainz Picard incorrectly stores plaintext genres separated by "/" when writing in ID3v2.3 mode, hack-fix here:
// replace / with NULL, then replace back the two ID3v1 genres that legitimately have "/" as part of the single genre name
if (preg_match('#/#', $genrestring)) {
$genrestring = str_replace('/', "\x00", $genrestring);
$genrestring = str_replace('Pop'."\x00".'Funk', 'Pop/Funk', $genrestring);
$genrestring = str_replace('Rock'."\x00".'Rock', 'Folk/Rock', $genrestring);
}
// some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
if (preg_match('#;#', $genrestring)) {
$genrestring = str_replace(';', "\x00", $genrestring);
}
}
if (strpos($genrestring, "\x00") === false) {
$genrestring = preg_replace('#\(([0-9]{1,3})\)#', '$1'."\x00", $genrestring);
}
$genre_elements = explode("\x00", $genrestring);
foreach ($genre_elements as $element) {
$element = trim($element);
@ -571,14 +594,14 @@ class getid3_id3v2 extends getid3_handler
if ($parsedFrame['flags']['compression']) {
$parsedFrame['decompressed_size'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 0, 4));
if (!function_exists('gzuncompress')) {
$info['warning'][] = 'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"';
$this->warning('gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame['frame_name'].'"');
} else {
if ($decompresseddata = @gzuncompress(substr($parsedFrame['data'], 4))) {
//if ($decompresseddata = @gzuncompress($parsedFrame['data'])) {
$parsedFrame['data'] = $decompresseddata;
unset($decompresseddata);
} else {
$info['warning'][] = 'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"';
$this->warning('gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame['frame_name'].'"');
}
}
}
@ -586,7 +609,7 @@ class getid3_id3v2 extends getid3_handler
if (!empty($parsedFrame['flags']['DataLengthIndicator'])) {
if ($parsedFrame['data_length_indicator'] != strlen($parsedFrame['data'])) {
$info['warning'][] = 'ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data';
$this->warning('ID3v2 frame "'.$parsedFrame['frame_name'].'" should be '.$parsedFrame['data_length_indicator'].' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame['data']).' bytes of data');
}
}
@ -601,7 +624,7 @@ class getid3_id3v2 extends getid3_handler
default:
break;
}
$info['warning'][] = $warning;
$this->warning($warning);
} elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'UFID')) || // 4.1 UFID Unique file identifier
(($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'UFI'))) { // 4.1 UFI Unique file identifier
@ -627,7 +650,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
@ -635,7 +658,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$parsedFrame['encodingid'] = $frame_textencoding;
@ -664,7 +688,7 @@ class getid3_id3v2 extends getid3_handler
$frame_offset = 0;
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
}
$parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
@ -720,7 +744,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
@ -728,8 +752,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
@ -783,7 +807,7 @@ class getid3_id3v2 extends getid3_handler
$frame_offset = 0;
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
}
$parsedFrame['encodingid'] = $frame_textencoding;
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
@ -961,7 +985,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_language = substr($parsedFrame['data'], $frame_offset, 3);
@ -971,7 +995,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
@ -979,7 +1004,6 @@ class getid3_id3v2 extends getid3_handler
$parsedFrame['encodingid'] = $frame_textencoding;
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
$parsedFrame['data'] = $parsedFrame['data'];
$parsedFrame['language'] = $frame_language;
$parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
$parsedFrame['description'] = $frame_description;
@ -1009,7 +1033,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_language = substr($parsedFrame['data'], $frame_offset, 3);
@ -1061,7 +1085,7 @@ class getid3_id3v2 extends getid3_handler
if (strlen($parsedFrame['data']) < 5) {
$info['warning'][] = 'Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset'];
$this->warning('Invalid data (too short) for "'.$parsedFrame['frame_name'].'" frame at offset '.$parsedFrame['dataoffset']);
} else {
@ -1069,7 +1093,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_language = substr($parsedFrame['data'], $frame_offset, 3);
@ -1079,7 +1103,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
@ -1132,7 +1157,7 @@ class getid3_id3v2 extends getid3_handler
$frame_offset += 2;
$parsedFrame[$RVA2channelcounter]['bitspeakvolume'] = ord(substr($frame_remainingdata, $frame_offset++, 1));
if (($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] < 1) || ($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] > 4)) {
$info['warning'][] = 'ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value';
$this->warning('ID3v2::RVA2 frame['.$RVA2channelcounter.'] contains invalid '.$parsedFrame[$RVA2channelcounter]['bitspeakvolume'].'-byte bits-representing-peak value');
break;
}
$frame_bytespeakvolume = ceil($parsedFrame[$RVA2channelcounter]['bitspeakvolume'] / 8);
@ -1341,7 +1366,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
@ -1376,14 +1401,15 @@ class getid3_id3v2 extends getid3_handler
$frame_picturetype = ord(substr($parsedFrame['data'], $frame_offset++, 1));
if ($frame_offset >= $parsedFrame['datalength']) {
$info['warning'][] = 'data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset);
$this->warning('data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset));
} else {
$frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$parsedFrame['encodingid'] = $frame_textencoding;
@ -1402,14 +1428,15 @@ class getid3_id3v2 extends getid3_handler
$parsedFrame['image_mime'] = '';
$imageinfo = array();
$imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo);
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
$parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
if ($imagechunkcheck[0]) {
$parsedFrame['image_width'] = $imagechunkcheck[0];
}
if ($imagechunkcheck[1]) {
$parsedFrame['image_height'] = $imagechunkcheck[1];
if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
$parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
if ($imagechunkcheck[0]) {
$parsedFrame['image_width'] = $imagechunkcheck[0];
}
if ($imagechunkcheck[1]) {
$parsedFrame['image_height'] = $imagechunkcheck[1];
}
}
}
@ -1425,16 +1452,16 @@ class getid3_id3v2 extends getid3_handler
} elseif (is_int($this->getid3->option_save_attachments)) {
if ($this->getid3->option_save_attachments < $parsedFrame['data_length']) {
// too big, skip
$info['warning'][] = 'attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)';
$this->warning('attachment at '.$frame_offset.' is too large to process inline ('.number_format($parsedFrame['data_length']).' bytes)');
unset($parsedFrame['data']);
break;
}
*/
} elseif (is_string($this->getid3->option_save_attachments)) {
$dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
if (!is_dir($dir) || !is_writable($dir)) {
if (!is_dir($dir) || !getID3::is_writable($dir)) {
// cannot write, skip
$info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)';
$this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)');
unset($parsedFrame['data']);
break;
}
@ -1442,10 +1469,10 @@ class getid3_id3v2 extends getid3_handler
// if we get this far, must be OK
if (is_string($this->getid3->option_save_attachments)) {
$destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset;
if (!file_exists($destination_filename) || is_writable($destination_filename)) {
if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) {
file_put_contents($destination_filename, $parsedFrame['data']);
} else {
$info['warning'][] = 'attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)';
$this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)');
}
$parsedFrame['data_filename'] = $destination_filename;
unset($parsedFrame['data']);
@ -1482,7 +1509,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
@ -1507,7 +1534,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
@ -1589,7 +1617,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$frame_offset = $frame_terminatorpos + strlen("\x00");
@ -1614,7 +1643,7 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
$frame_ownerid = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_ownerid) === 0) {
$frame_ownerid == '';
$frame_ownerid = '';
}
$frame_offset = $frame_terminatorpos + strlen("\x00");
$parsedFrame['ownerid'] = $frame_ownerid;
@ -1683,7 +1712,7 @@ class getid3_id3v2 extends getid3_handler
$frame_offset = 0;
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
}
$frame_language = substr($parsedFrame['data'], $frame_offset, 3);
$frame_offset += 3;
@ -1710,7 +1739,7 @@ class getid3_id3v2 extends getid3_handler
$frame_offset = 0;
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
}
$parsedFrame['encodingid'] = $frame_textencoding;
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
@ -1724,7 +1753,7 @@ class getid3_id3v2 extends getid3_handler
$parsedFrame['pricepaid']['value'] = substr($frame_pricepaid, 3);
$parsedFrame['purchasedate'] = substr($parsedFrame['data'], $frame_offset, 8);
if (!$this->IsValidDateStampString($parsedFrame['purchasedate'])) {
if ($this->IsValidDateStampString($parsedFrame['purchasedate'])) {
$parsedFrame['purchasedateunix'] = mktime (0, 0, 0, substr($parsedFrame['purchasedate'], 4, 2), substr($parsedFrame['purchasedate'], 6, 2), substr($parsedFrame['purchasedate'], 0, 4));
}
$frame_offset += 8;
@ -1751,7 +1780,7 @@ class getid3_id3v2 extends getid3_handler
$frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
$frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
$info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
$this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding');
$frame_textencoding_terminator = "\x00";
}
@ -1789,7 +1818,8 @@ class getid3_id3v2 extends getid3_handler
$frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
}
$frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
if (ord($frame_description) === 0) {
if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
// if description only contains a BOM or terminator then make it blank
$frame_description = '';
}
$frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
@ -2006,7 +2036,7 @@ class getid3_id3v2 extends getid3_handler
$subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
$frame_offset += 2;
if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
$info['warning'][] = 'CHAP subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)';
$this->warning('CHAP subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
break;
}
$subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
@ -2043,7 +2073,7 @@ class getid3_id3v2 extends getid3_handler
}
$parsedFrame['subframes'][] = $subframe;
} else {
$info['warning'][] = 'ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)';
$this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
}
}
unset($subframe_rawdata, $subframe, $encoding_converted_text);
@ -2103,7 +2133,7 @@ class getid3_id3v2 extends getid3_handler
$subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
$frame_offset += 2;
if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
$info['warning'][] = 'CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)';
$this->warning('CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
break;
}
$subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
@ -2140,7 +2170,7 @@ class getid3_id3v2 extends getid3_handler
}
$parsedFrame['subframes'][] = $subframe;
} else {
$info['warning'][] = 'ID3v2.CTOC subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)';
$this->warning('ID3v2.CTOC subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
}
}
unset($subframe_rawdata, $subframe, $encoding_converted_text);
@ -3623,5 +3653,89 @@ class getid3_id3v2 extends getid3_handler
return (($majorversion == 2) ? 6 : 10);
}
}
public static function ID3v22iTunesBrokenFrameName($frame_name) {
// iTunes (multiple versions) has been known to write ID3v2.3 style frames
// but use ID3v2.2 frame names, right-padded using either [space] or [null]
// to make them fit in the 4-byte frame name space of the ID3v2.3 frame.
// This function will detect and translate the corrupt frame name into ID3v2.3 standard.
static $ID3v22_iTunes_BrokenFrames = array(
'BUF' => 'RBUF', // Recommended buffer size
'CNT' => 'PCNT', // Play counter
'COM' => 'COMM', // Comments
'CRA' => 'AENC', // Audio encryption
'EQU' => 'EQUA', // Equalisation
'ETC' => 'ETCO', // Event timing codes
'GEO' => 'GEOB', // General encapsulated object
'IPL' => 'IPLS', // Involved people list
'LNK' => 'LINK', // Linked information
'MCI' => 'MCDI', // Music CD identifier
'MLL' => 'MLLT', // MPEG location lookup table
'PIC' => 'APIC', // Attached picture
'POP' => 'POPM', // Popularimeter
'REV' => 'RVRB', // Reverb
'RVA' => 'RVAD', // Relative volume adjustment
'SLT' => 'SYLT', // Synchronised lyric/text
'STC' => 'SYTC', // Synchronised tempo codes
'TAL' => 'TALB', // Album/Movie/Show title
'TBP' => 'TBPM', // BPM (beats per minute)
'TCM' => 'TCOM', // Composer
'TCO' => 'TCON', // Content type
'TCP' => 'TCMP', // Part of a compilation
'TCR' => 'TCOP', // Copyright message
'TDA' => 'TDAT', // Date
'TDY' => 'TDLY', // Playlist delay
'TEN' => 'TENC', // Encoded by
'TFT' => 'TFLT', // File type
'TIM' => 'TIME', // Time
'TKE' => 'TKEY', // Initial key
'TLA' => 'TLAN', // Language(s)
'TLE' => 'TLEN', // Length
'TMT' => 'TMED', // Media type
'TOA' => 'TOPE', // Original artist(s)/performer(s)
'TOF' => 'TOFN', // Original filename
'TOL' => 'TOLY', // Original lyricist(s)/text writer(s)
'TOR' => 'TORY', // Original release year
'TOT' => 'TOAL', // Original album/movie/show title
'TP1' => 'TPE1', // Lead performer(s)/Soloist(s)
'TP2' => 'TPE2', // Band/orchestra/accompaniment
'TP3' => 'TPE3', // Conductor/performer refinement
'TP4' => 'TPE4', // Interpreted, remixed, or otherwise modified by
'TPA' => 'TPOS', // Part of a set
'TPB' => 'TPUB', // Publisher
'TRC' => 'TSRC', // ISRC (international standard recording code)
'TRD' => 'TRDA', // Recording dates
'TRK' => 'TRCK', // Track number/Position in set
'TS2' => 'TSO2', // Album-Artist sort order
'TSA' => 'TSOA', // Album sort order
'TSC' => 'TSOC', // Composer sort order
'TSI' => 'TSIZ', // Size
'TSP' => 'TSOP', // Performer sort order
'TSS' => 'TSSE', // Software/Hardware and settings used for encoding
'TST' => 'TSOT', // Title sort order
'TT1' => 'TIT1', // Content group description
'TT2' => 'TIT2', // Title/songname/content description
'TT3' => 'TIT3', // Subtitle/Description refinement
'TXT' => 'TEXT', // Lyricist/Text writer
'TXX' => 'TXXX', // User defined text information frame
'TYE' => 'TYER', // Year
'UFI' => 'UFID', // Unique file identifier
'ULT' => 'USLT', // Unsynchronised lyric/text transcription
'WAF' => 'WOAF', // Official audio file webpage
'WAR' => 'WOAR', // Official artist/performer webpage
'WAS' => 'WOAS', // Official audio source webpage
'WCM' => 'WCOM', // Commercial information
'WCP' => 'WCOP', // Copyright/Legal information
'WPB' => 'WPUB', // Publishers official webpage
'WXX' => 'WXXX', // User defined URL link frame
);
if (strlen($frame_name) == 4) {
if ((substr($frame_name, 3, 1) == ' ') || (substr($frame_name, 3, 1) == "\x00")) {
if (isset($ID3v22_iTunes_BrokenFrames[substr($frame_name, 0, 3)])) {
return $ID3v22_iTunes_BrokenFrames[substr($frame_name, 0, 3)];
}
}
}
return false;
}
}

View File

@ -24,7 +24,7 @@ class getid3_lyrics3 extends getid3_handler
// http://www.volweb.cz/str/tags.htm
if (!getid3_lib::intValueSupported($info['filesize'])) {
$info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
$this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
return false;
}
@ -80,7 +80,7 @@ class getid3_lyrics3 extends getid3_handler
$lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
$info['avdataend'] = $lyrics3offset;
$lyrics3version = 1;
$info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
$this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
} elseif ($lyrics3end == 'LYRICS200') {
// Lyrics3v2, APE, maybe ID3v1
@ -88,7 +88,7 @@ class getid3_lyrics3 extends getid3_handler
$lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
$lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
$lyrics3version = 2;
$info['warning'][] = 'APE tag located after Lyrics3, will probably break Lyrics3 compatability';
$this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
}
@ -117,7 +117,7 @@ class getid3_lyrics3 extends getid3_handler
}
unset($getid3_temp, $getid3_apetag);
} else {
$info['warning'][] = 'Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)';
$this->warning('Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)');
}
}
@ -132,7 +132,7 @@ class getid3_lyrics3 extends getid3_handler
$info = &$this->getid3->info;
if (!getid3_lib::intValueSupported($endoffset)) {
$info['warning'][] = 'Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';
$this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
return false;
}
@ -150,7 +150,7 @@ class getid3_lyrics3 extends getid3_handler
if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') {
if (strpos($rawdata, 'LYRICSBEGIN') !== false) {
$info['warning'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version;
$this->warning('"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version);
$info['avdataend'] = $endoffset + strpos($rawdata, 'LYRICSBEGIN');
$rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN'));
$length = strlen($rawdata);
@ -159,7 +159,7 @@ class getid3_lyrics3 extends getid3_handler
} else {
$info['error'][] = '"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead';
$this->error('"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead');
return false;
}
@ -173,7 +173,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 '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
$this->error('"LYRICSEND" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
return false;
}
break;
@ -221,20 +221,20 @@ class getid3_lyrics3 extends getid3_handler
$this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
}
} else {
$info['error'][] = '"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
$this->error('"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
return false;
}
break;
default:
$info['error'][] = 'Cannot process Lyrics3 version '.$version.' (only v1 and v2)';
$this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)');
return false;
break;
}
if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] <= $ParsedLyrics3['tag_offset_end'])) {
$info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data';
$this->warning('ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data');
unset($info['id3v1']);
foreach ($info['warning'] as $key => $value) {
if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.9-alpha-41195';
$wp_version = '4.9-alpha-41196';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.