Changeset 41196
- Timestamp:
- 07/31/2017 07:49:31 PM (7 years ago)
- Location:
- trunk/src/wp-includes/ID3
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/getid3.lib.php
r32979 r41196 294 294 } 295 295 296 public static function LittleEndian2Bin($byteword) { 297 return self::BigEndian2Bin(strrev($byteword)); 298 } 296 299 297 300 public static function BigEndian2Bin($byteword) { … … 413 416 } 414 417 return $newarray; 418 } 419 420 public static function flipped_array_merge_noclobber($array1, $array2) { 421 if (!is_array($array1) || !is_array($array2)) { 422 return false; 423 } 424 # naturally, this only works non-recursively 425 $newarray = array_flip($array1); 426 foreach (array_flip($array2) as $key => $val) { 427 if (!isset($newarray[$key])) { 428 $newarray[$key] = count($newarray); 429 } 430 } 431 return array_flip($newarray); 415 432 } 416 433 … … 947 964 } 948 965 966 // mb_convert_encoding() availble 967 if (function_exists('mb_convert_encoding')) { 968 if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) { 969 switch ($out_charset) { 970 case 'ISO-8859-1': 971 $converted_string = rtrim($converted_string, "\x00"); 972 break; 973 } 974 return $converted_string; 975 } 976 return $string; 977 } 949 978 // iconv() availble 950 if (function_exists('iconv')) {979 else if (function_exists('iconv')) { 951 980 if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) { 952 981 switch ($out_charset) { … … 964 993 965 994 966 // iconv() notavailable995 // neither mb_convert_encoding or iconv() is available 967 996 static $ConversionFunctionList = array(); 968 997 if (empty($ConversionFunctionList)) { … … 986 1015 return self::$ConversionFunction($string); 987 1016 } 988 throw new Exception('PHP does not ha veiconv() support - cannot convert from '.$in_charset.' to '.$out_charset);1017 throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset); 989 1018 } 990 1019 … … 1007 1036 $HTMLstring = ''; 1008 1037 1009 switch ( $charset) {1038 switch (strtolower($charset)) { 1010 1039 case '1251': 1011 1040 case '1252': … … 1014 1043 case '936': 1015 1044 case '950': 1016 case ' BIG5':1017 case ' BIG5-HKSCS':1045 case 'big5': 1046 case 'big5-hkscs': 1018 1047 case 'cp1251': 1019 1048 case 'cp1252': 1020 1049 case 'cp866': 1021 case ' EUC-JP':1022 case ' EUCJP':1023 case ' GB2312':1050 case 'euc-jp': 1051 case 'eucjp': 1052 case 'gb2312': 1024 1053 case 'ibm866': 1025 case ' ISO-8859-1':1026 case ' ISO-8859-15':1027 case ' ISO8859-1':1028 case ' ISO8859-15':1029 case ' KOI8-R':1054 case 'iso-8859-1': 1055 case 'iso-8859-15': 1056 case 'iso8859-1': 1057 case 'iso8859-15': 1058 case 'koi8-r': 1030 1059 case 'koi8-ru': 1031 1060 case 'koi8r': 1032 case ' Shift_JIS':1033 case ' SJIS':1061 case 'shift_jis': 1062 case 'sjis': 1034 1063 case 'win-1251': 1035 case ' Windows-1251':1036 case ' Windows-1252':1064 case 'windows-1251': 1065 case 'windows-1252': 1037 1066 $HTMLstring = htmlentities($string, ENT_COMPAT, $charset); 1038 1067 break; 1039 1068 1040 case ' UTF-8':1069 case 'utf-8': 1041 1070 $strlen = strlen($string); 1042 1071 for ($i = 0; $i < $strlen; $i++) { … … 1066 1095 break; 1067 1096 1068 case ' UTF-16LE':1097 case 'utf-16le': 1069 1098 for ($i = 0; $i < strlen($string); $i += 2) { 1070 1099 $charval = self::LittleEndian2Int(substr($string, $i, 2)); … … 1077 1106 break; 1078 1107 1079 case ' UTF-16BE':1108 case 'utf-16be': 1080 1109 for ($i = 0; $i < strlen($string); $i += 2) { 1081 1110 $charval = self::BigEndian2Int(substr($string, $i, 2)); … … 1154 1183 static $tempdir = ''; 1155 1184 if (empty($tempdir)) { 1185 if (function_exists('sys_get_temp_dir')) { 1186 $tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52 1187 } 1188 1156 1189 // yes this is ugly, feel free to suggest a better way 1157 require_once(dirname(__FILE__).'/getid3.php'); 1158 $getid3_temp = new getID3(); 1159 $tempdir = $getid3_temp->tempdir; 1160 unset($getid3_temp); 1190 if (include_once(dirname(__FILE__).'/getid3.php')) { 1191 if ($getid3_temp = new getID3()) { 1192 if ($getid3_temp_tempdir = $getid3_temp->tempdir) { 1193 $tempdir = $getid3_temp_tempdir; 1194 } 1195 unset($getid3_temp, $getid3_temp_tempdir); 1196 } 1197 } 1161 1198 } 1162 1199 $GetDataImageSize = false; … … 1166 1203 fclose($tmp); 1167 1204 $GetDataImageSize = @getimagesize($tempfilename, $imageinfo); 1205 if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) { 1206 return false; 1207 } 1168 1208 $GetDataImageSize['height'] = $GetDataImageSize[0]; 1169 1209 $GetDataImageSize['width'] = $GetDataImageSize[1]; … … 1238 1278 if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) { 1239 1279 $value = (is_string($value) ? trim($value) : $value); 1240 if (!is_ numeric($key)) {1280 if (!is_int($key) && !ctype_digit($key)) { 1241 1281 $ThisFileInfo['comments'][$tagname][$key] = $value; 1242 1282 } else { 1243 $ThisFileInfo['comments'][$tagname][] = $value; 1283 if (isset($ThisFileInfo['comments'][$tagname])) { 1284 $ThisFileInfo['comments'][$tagname] = array($value); 1285 } else { 1286 $ThisFileInfo['comments'][$tagname][] = $value; 1287 } 1244 1288 } 1245 1289 } 1246 1290 } 1247 1291 } 1292 } 1293 } 1294 1295 // attempt to standardize spelling of returned keys 1296 $StandardizeFieldNames = array( 1297 'tracknumber' => 'track_number', 1298 'track' => 'track_number', 1299 ); 1300 foreach ($StandardizeFieldNames as $badkey => $goodkey) { 1301 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { 1302 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; 1303 unset($ThisFileInfo['comments'][$badkey]); 1248 1304 } 1249 1305 } -
trunk/src/wp-includes/ID3/getid3.php
r32979 r41196 22 22 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { 23 23 define('IMG_JPG', IMAGETYPE_JPEG); 24 } 25 if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE 26 define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); 24 27 } 25 28 … … 110 113 protected $startup_warning = ''; 111 114 112 const VERSION = '1.9. 9-20141121';115 const VERSION = '1.9.14-201706111222'; 113 116 const FREAD_BUFFER_SIZE = 32768; 114 117 … … 121 124 // Check memory 122 125 $this->memory_limit = ini_get('memory_limit'); 123 if (preg_match('#([0-9]+) M#i', $this->memory_limit, $matches)) {126 if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) { 124 127 // could be stored as "16M" rather than 16777216 for example 125 128 $this->memory_limit = $matches[1] * 1048576; 126 } elseif (preg_match('#([0-9]+) G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0129 } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0 127 130 // could be stored as "2G" rather than 2147483648 for example 128 131 $this->memory_limit = $matches[1] * 1073741824; … … 131 134 // memory limits probably disabled 132 135 } elseif ($this->memory_limit <= 4194304) { 133 $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini' ;136 $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n"; 134 137 } elseif ($this->memory_limit <= 12582912) { 135 $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' ;138 $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"; 136 139 } 137 140 … … 141 144 } 142 145 143 if (intval(ini_get('mbstring.func_overload')) > 0) { 144 $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.'); 146 if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) { 147 // http://php.net/manual/en/mbstring.overload.php 148 // "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" 149 // 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. 150 $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"; 145 151 } 146 152 … … 148 154 if (function_exists('get_magic_quotes_runtime')) { 149 155 if (get_magic_quotes_runtime()) { 150 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).');156 $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"; 151 157 } 152 158 } … … 155 161 if (function_exists('magic_quotes_gpc')) { 156 162 if (get_magic_quotes_gpc()) { 157 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).');163 $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"; 158 164 } 159 165 } … … 161 167 // Load support library 162 168 if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { 163 $this->startup_error .= 'getid3.lib.php is missing or corrupt' ;169 $this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n"; 164 170 } 165 171 … … 180 186 181 187 if (!is_dir($helperappsdir)) { 182 $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist' ;188 $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n"; 183 189 } elseif (strpos(realpath($helperappsdir), ' ') !== false) { 184 190 $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir)); … … 200 206 } 201 207 } else { 202 $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.' ;208 $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"; 203 209 } 204 210 } … … 208 214 } 209 215 define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR); 216 } 217 218 if (!empty($this->startup_error)) { 219 echo $this->startup_error; 220 throw new getid3_exception($this->startup_error); 210 221 } 211 222 … … 237 248 238 249 239 public function openfile($filename ) {250 public function openfile($filename, $filesize=null) { 240 251 try { 241 252 if (!empty($this->startup_error)) { … … 243 254 } 244 255 if (!empty($this->startup_warning)) { 245 $this->warning($this->startup_warning); 256 foreach (explode("\n", $this->startup_warning) as $startup_warning) { 257 $this->warning($startup_warning); 258 } 246 259 } 247 260 … … 253 266 254 267 // remote files not supported 255 if (preg_match(' /^(ht|f)tp:\/\//', $filename)) {268 if (preg_match('#^(ht|f)tp://#', $filename)) { 256 269 throw new getid3_exception('Remote files are not supported - please copy the file locally first'); 257 270 } 258 271 259 272 $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); 260 $filename = preg_replace('#( .+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);273 $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename); 261 274 262 275 // open local file … … 281 294 } 282 295 283 $this->info['filesize'] = filesize($filename);296 $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename)); 284 297 // set redundant parameters - might be needed in some include file 285 298 // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion … … 289 302 $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename']; 290 303 304 // set more parameters 305 $this->info['avdataoffset'] = 0; 306 $this->info['avdataend'] = $this->info['filesize']; 307 $this->info['fileformat'] = ''; // filled in later 308 $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used 309 $this->info['video']['dataformat'] = ''; // filled in later, unset if not used 310 $this->info['tags'] = array(); // filled in later, unset if not used 311 $this->info['error'] = array(); // filled in later, unset if not used 312 $this->info['warning'] = array(); // filled in later, unset if not used 313 $this->info['comments'] = array(); // filled in later, unset if not used 314 $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired 291 315 292 316 // option_max_2gb_check … … 315 339 } 316 340 317 // set more parameters318 $this->info['avdataoffset'] = 0;319 $this->info['avdataend'] = $this->info['filesize'];320 $this->info['fileformat'] = ''; // filled in later321 $this->info['audio']['dataformat'] = ''; // filled in later, unset if not used322 $this->info['video']['dataformat'] = ''; // filled in later, unset if not used323 $this->info['tags'] = array(); // filled in later, unset if not used324 $this->info['error'] = array(); // filled in later, unset if not used325 $this->info['warning'] = array(); // filled in later, unset if not used326 $this->info['comments'] = array(); // filled in later, unset if not used327 $this->info['encoding'] = $this->encoding; // required by id3v2 and iso modules - can be unset at the end if desired328 329 341 return true; 330 342 … … 336 348 337 349 // public: analyze file 338 public function analyze($filename ) {350 public function analyze($filename, $filesize=null, $original_filename='') { 339 351 try { 340 if (!$this->openfile($filename )) {352 if (!$this->openfile($filename, $filesize)) { 341 353 return $this->info; 342 354 } … … 383 395 384 396 // determine format 385 $determined_format = $this->GetFileFormat($formattest, $filename);397 $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename)); 386 398 387 399 // unable to determine file format … … 420 432 } 421 433 422 // module requires iconv support434 // module requires mb_convert_encoding/iconv support 423 435 // Check encoding/iconv support 424 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'))) {425 $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. ';436 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'))) { 437 $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. '; 426 438 if (GETID3_OS_ISWINDOWS) { 427 $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copyiconv.dll from c:/php/dlls to c:/windows/system32';439 $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'; 428 440 } else { 429 $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the--with-iconv switch';441 $errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch'; 430 442 } 431 443 return $this->error($errormessage); … … 562 574 // AC-3 - audio - Dolby AC-3 / Dolby Digital 563 575 'ac3' => array( 564 'pattern' => '^\ x0B\x77',576 'pattern' => '^\\x0B\\x77', 565 577 'group' => 'audio', 566 578 'module' => 'ac3', … … 580 592 // AA - audio - Audible Audiobook 581 593 'aa' => array( 582 'pattern' => '^.{4}\ x57\x90\x75\x36',594 'pattern' => '^.{4}\\x57\\x90\\x75\\x36', 583 595 'group' => 'audio', 584 596 'module' => 'aa', … … 588 600 // AAC - audio - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3) 589 601 'adts' => array( 590 'pattern' => '^\ xFF[\xF0-\xF1\xF8-\xF9]',602 'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]', 591 603 'group' => 'audio', 592 604 'module' => 'aac', … … 598 610 // AU - audio - NeXT/Sun AUdio (AU) 599 611 'au' => array( 600 'pattern' => '^\ .snd',612 'pattern' => '^\\.snd', 601 613 'group' => 'audio', 602 614 'module' => 'au', … … 606 618 // AMR - audio - Adaptive Multi Rate 607 619 'amr' => array( 608 'pattern' => '^\ x23\x21AMR\x0A', // #!AMR[0A]620 'pattern' => '^\\x23\\x21AMR\\x0A', // #!AMR[0A] 609 621 'group' => 'audio', 610 622 'module' => 'amr', … … 622 634 // BONK - audio - Bonk v0.9+ 623 635 'bonk' => array( 624 'pattern' => '^\ x00(BONK|INFO|META| ID3)',636 'pattern' => '^\\x00(BONK|INFO|META| ID3)', 625 637 'group' => 'audio', 626 638 'module' => 'bonk', … … 628 640 ), 629 641 642 // DSF - audio - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital 643 'dsf' => array( 644 'pattern' => '^DSD ', // including trailing space: 44 53 44 20 645 'group' => 'audio', 646 'module' => 'dsf', 647 'mime_type' => 'audio/dsd', 648 ), 649 630 650 // DSS - audio - Digital Speech Standard 631 651 'dss' => array( 632 'pattern' => '^[\ x02-\x03]ds[s2]',652 'pattern' => '^[\\x02-\\x06]ds[s2]', 633 653 'group' => 'audio', 634 654 'module' => 'dss', … … 638 658 // DTS - audio - Dolby Theatre System 639 659 'dts' => array( 640 'pattern' => '^\ x7F\xFE\x80\x01',660 'pattern' => '^\\x7F\\xFE\\x80\\x01', 641 661 'group' => 'audio', 642 662 'module' => 'dts', … … 723 743 // MPC - audio - Musepack / MPEGplus 724 744 'mpc' => array( 725 '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])',745 '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])', 726 746 'group' => 'audio', 727 747 'module' => 'mpc', … … 731 751 // MP3 - audio - MPEG-audio Layer 3 (very similar to AAC-ADTS) 732 752 'mp3' => array( 733 '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]',753 '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]', 734 754 'group' => 'audio', 735 755 'module' => 'mp3', … … 739 759 // OFR - audio - OptimFROG 740 760 'ofr' => array( 741 'pattern' => '^(\ *RIFF|OFR)',761 'pattern' => '^(\\*RIFF|OFR)', 742 762 'group' => 'audio', 743 763 'module' => 'optimfrog', … … 765 785 // TTA - audio - TTA Lossless Audio Compressor (http://tta.corecodec.org) 766 786 'tta' => array( 767 'pattern' => '^TTA', // could also be '^TTA(\ x01|\x02|\x03|2|1)'787 'pattern' => '^TTA', // could also be '^TTA(\\x01|\\x02|\\x03|2|1)' 768 788 'group' => 'audio', 769 789 'module' => 'tta', … … 800 820 // ASF - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio 801 821 'asf' => array( 802 'pattern' => '^\ x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',822 'pattern' => '^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C', 803 823 'group' => 'audio-video', 804 824 'module' => 'asf', … … 817 837 // FLV - audio/video - FLash Video 818 838 'flv' => array( 819 'pattern' => '^FLV \x01',839 'pattern' => '^FLV[\\x01]', 820 840 'group' => 'audio-video', 821 841 'module' => 'flv', … … 825 845 // MKAV - audio/video - Mastroka 826 846 'matroska' => array( 827 'pattern' => '^\ x1A\x45\xDF\xA3',847 'pattern' => '^\\x1A\\x45\\xDF\\xA3', 828 848 'group' => 'audio-video', 829 849 'module' => 'matroska', … … 833 853 // MPEG - audio/video - MPEG (Moving Pictures Experts Group) 834 854 'mpeg' => array( 835 'pattern' => '^\ x00\x00\x01(\xBA|\xB3)',855 'pattern' => '^\\x00\\x00\\x01[\\xB3\\xBA]', 836 856 'group' => 'audio-video', 837 857 'module' => 'mpeg', … … 870 890 'group' => 'audio-video', 871 891 'module' => 'riff', 872 'mime_type' => 'audio/x-wav e',892 'mime_type' => 'audio/x-wav', 873 893 'fail_ape' => 'WARNING', 874 894 ), … … 876 896 // Real - audio/video - RealAudio, RealVideo 877 897 'real' => array( 878 'pattern' => '^ (\\.RMF|\\.ra)',898 'pattern' => '^\\.(RMF|ra)', 879 899 'group' => 'audio-video', 880 900 'module' => 'real', … … 892 912 // TS - audio/video - MPEG-2 Transport Stream 893 913 'ts' => array( 894 'pattern' => '^(\ x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern914 'pattern' => '^(\\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G". Check for at least 10 packets matching this pattern 895 915 'group' => 'audio-video', 896 916 'module' => 'ts', … … 923 943 // JPEG - still image - Joint Photographic Experts Group (JPEG) 924 944 'jpg' => array( 925 'pattern' => '^\ xFF\xD8\xFF',945 'pattern' => '^\\xFF\\xD8\\xFF', 926 946 'group' => 'graphic', 927 947 'module' => 'jpg', … … 933 953 // PCD - still image - Kodak Photo CD 934 954 'pcd' => array( 935 'pattern' => '^.{2048}PCD_IPI\ x00',955 'pattern' => '^.{2048}PCD_IPI\\x00', 936 956 'group' => 'graphic', 937 957 'module' => 'pcd', … … 944 964 // PNG - still image - Portable Network Graphics (PNG) 945 965 'png' => array( 946 'pattern' => '^\ x89\x50\x4E\x47\x0D\x0A\x1A\x0A',966 'pattern' => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A', 947 967 'group' => 'graphic', 948 968 'module' => 'png', … … 955 975 // SVG - still image - Scalable Vector Graphics (SVG) 956 976 'svg' => array( 957 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http: \/\/www\.w3\.org\/2000\/svg")',977 'pattern' => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")', 958 978 'group' => 'graphic', 959 979 'module' => 'svg', … … 966 986 // TIFF - still image - Tagged Information File Format (TIFF) 967 987 'tiff' => array( 968 'pattern' => '^(II\ x2A\x00|MM\x00\x2A)',988 'pattern' => '^(II\\x2A\\x00|MM\\x00\\x2A)', 969 989 'group' => 'graphic', 970 990 'module' => 'tiff', … … 977 997 // EFAX - still image - eFax (TIFF derivative) 978 998 'efax' => array( 979 'pattern' => '^\ xDC\xFE',999 'pattern' => '^\\xDC\\xFE', 980 1000 'group' => 'graphic', 981 1001 'module' => 'efax', … … 1001 1021 // RAR - data - RAR compressed data 1002 1022 'rar' => array( 1003 'pattern' => '^Rar\ !',1023 'pattern' => '^Rar\\!', 1004 1024 'group' => 'archive', 1005 1025 'module' => 'rar', … … 1011 1031 // SZIP - audio/data - SZIP compressed data 1012 1032 'szip' => array( 1013 'pattern' => '^SZ\ x0A\x04',1033 'pattern' => '^SZ\\x0A\\x04', 1014 1034 'group' => 'archive', 1015 1035 'module' => 'szip', … … 1021 1041 // TAR - data - TAR compressed data 1022 1042 'tar' => array( 1023 '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}',1043 '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}', 1024 1044 'group' => 'archive', 1025 1045 'module' => 'tar', … … 1031 1051 // GZIP - data - GZIP compressed data 1032 1052 'gz' => array( 1033 'pattern' => '^\ x1F\x8B\x08',1053 'pattern' => '^\\x1F\\x8B\\x08', 1034 1054 'group' => 'archive', 1035 1055 'module' => 'gzip', … … 1041 1061 // ZIP - data - ZIP compressed data 1042 1062 'zip' => array( 1043 'pattern' => '^PK\ x03\x04',1063 'pattern' => '^PK\\x03\\x04', 1044 1064 'group' => 'archive', 1045 1065 'module' => 'zip', … … 1054 1074 // PAR2 - data - Parity Volume Set Specification 2.0 1055 1075 'par2' => array ( 1056 'pattern' => '^PAR2\ x00PKT',1076 'pattern' => '^PAR2\\x00PKT', 1057 1077 'group' => 'misc', 1058 1078 'module' => 'par2', … … 1064 1084 // PDF - data - Portable Document Format 1065 1085 'pdf' => array( 1066 'pattern' => '^\ x25PDF',1086 'pattern' => '^\\x25PDF', 1067 1087 'group' => 'misc', 1068 1088 'module' => 'pdf', … … 1074 1094 // MSOFFICE - data - ZIP compressed data 1075 1095 'msoffice' => array( 1076 'pattern' => '^\ xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document1096 'pattern' => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document 1077 1097 'group' => 'misc', 1078 1098 'module' => 'msoffice', … … 1115 1135 1116 1136 1117 if (preg_match('#\ .mp[123a]$#i', $filename)) {1137 if (preg_match('#\\.mp[123a]$#i', $filename)) { 1118 1138 // Too many mp3 encoders on the market put gabage in front of mpeg files 1119 1139 // use assume format on these if format detection failed … … 1122 1142 $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; 1123 1143 return $info; 1124 } elseif (preg_match(' /\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {1144 } elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) { 1125 1145 // there's not really a useful consistent "magic" at the beginning of .cue files to identify them 1126 1146 // so until I think of something better, just go by filename if all other format checks fail … … 1223 1243 } 1224 1244 1245 $this->CharConvert($this->info['tags'][$tag_name], $this->info[$comment_name]['encoding']); // only copy gets converted! 1246 1225 1247 if ($this->option_tags_html) { 1226 1248 foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) { 1227 $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $ encoding);1249 $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']); 1228 1250 } 1229 1251 } 1230 1252 1231 $this->CharConvert($this->info['tags'][$tag_name], $encoding); // only copy gets converted!1232 1253 } 1233 1254 … … 1353 1374 if (!empty($VorbisCommentError)) { 1354 1375 1355 $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;1356 $this->info[$algorithm.'_data'] 1376 $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); 1377 $this->info[$algorithm.'_data'] = false; 1357 1378 1358 1379 } else { … … 1583 1604 } 1584 1605 1606 public static function is_writable ($filename) { 1607 $ret = is_writable($filename); 1608 1609 if (!$ret) { 1610 $perms = fileperms($filename); 1611 $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002); 1612 } 1613 1614 return $ret; 1615 } 1616 1585 1617 } 1586 1618 … … 1662 1694 throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); 1663 1695 } 1664 return fread($this->getid3->fp, $bytes); 1696 1697 //return fread($this->getid3->fp, $bytes); 1698 /* 1699 * http://www.getid3.org/phpBB3/viewtopic.php?t=1930 1700 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread(). 1701 * It seems to assume that fread() would always return as many bytes as were requested. 1702 * 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. 1703 * The call may return only part of the requested data and a new call is needed to get more." 1704 */ 1705 $contents = ''; 1706 do { 1707 $part = fread($this->getid3->fp, $bytes); 1708 $partLength = strlen($part); 1709 $bytes -= $partLength; 1710 $contents .= $part; 1711 } while (($bytes > 0) && ($partLength > 0)); 1712 return $contents; 1665 1713 } 1666 1714 … … 1742 1790 // set up destination path 1743 1791 $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); 1744 if (!is_dir($dir) || ! is_writable($dir)) { // check supplied directory1792 if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory 1745 1793 throw new Exception('supplied path ('.$dir.') does not exist, or is not writable'); 1746 1794 } -
trunk/src/wp-includes/ID3/module.audio-video.asf.php
r32979 r41196 267 267 $thisfile_asf_headerextensionobject['reserved_1_guid'] = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']); 268 268 if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) { 269 $ 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).')';269 $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).')'); 270 270 //return false; 271 271 break; … … 274 274 $offset += 2; 275 275 if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) { 276 $ info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"';276 $this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"'); 277 277 //return false; 278 278 break; … … 317 317 $thisfile_asf_codeclistobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']); 318 318 if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) { 319 $ 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}';319 $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}'); 320 320 //return false; 321 321 break; … … 350 350 351 351 if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) { 352 $ info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"';352 $this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"'); 353 353 } else { 354 354 … … 413 413 414 414 default: 415 $ info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')';415 $this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')'); 416 416 break; 417 417 } … … 459 459 $thisfile_asf_scriptcommandobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']); 460 460 if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) { 461 $ 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}';461 $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}'); 462 462 //return false; 463 463 break; … … 518 518 $thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']); 519 519 if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) { 520 $ 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}';520 $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}'); 521 521 break; 522 522 } … … 526 526 $offset += 2; 527 527 if ($thisfile_asf_markerobject['reserved_2'] != 0) { 528 $ info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"';528 $this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"'); 529 529 break; 530 530 } … … 577 577 $offset += 16; 578 578 if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) { 579 $ 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).'}';579 $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).'}'); 580 580 //return false; 581 581 break; … … 638 638 639 639 default: 640 $ 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).'}';640 $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).'}'); 641 641 //return false; 642 642 break; … … 762 762 763 763 default: 764 $ info['warning'][] = 'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')';764 $this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')'); 765 765 //return false; 766 766 break; … … 963 963 // Implementations shall ignore any standard or non-standard object that they do not know how to handle. 964 964 if ($this->GUIDname($NextObjectGUIDtext)) { 965 $ info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);965 $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8)); 966 966 } else { 967 $ info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);967 $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8)); 968 968 } 969 969 $offset += ($NextObjectSize - 16 - 8); … … 1184 1184 $offset += 2; 1185 1185 if ($thisfile_asf_dataobject['reserved'] != 0x0101) { 1186 $ info['warning'][] = 'data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"';1186 $this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'); 1187 1187 //return false; 1188 1188 break; … … 1320 1320 // Implementations shall ignore any standard or non-standard object that they do not know how to handle. 1321 1321 if ($this->GUIDname($NextObjectGUIDtext)) { 1322 $ info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8);1322 $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8)); 1323 1323 } else { 1324 $ info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8);1324 $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8)); 1325 1325 } 1326 1326 $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR); … … 1406 1406 1407 1407 default: 1408 $ info['warning'][] = 'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw'];1408 $this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']); 1409 1409 break; 1410 1410 … … 1918 1918 $unhandled_sections++; 1919 1919 if ($this->GUIDname($thisObject['guid_text'])) { 1920 $this-> getid3->info['warning'][] = 'unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8);1920 $this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8)); 1921 1921 } else { 1922 $this-> getid3->info['warning'][] = 'unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8);1922 $this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8)); 1923 1923 } 1924 1924 break; -
trunk/src/wp-includes/ID3/module.audio-video.flv.php
r32979 r41196 94 94 95 95 if ($info['flv']['header']['signature'] != self::magic) { 96 $ info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"';96 $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"'); 97 97 unset($info['flv'], $info['fileformat']); 98 98 return false; … … 542 542 default: 543 543 $value = '(unknown or unsupported data type)'; 544 break;544 break; 545 545 } 546 546 -
trunk/src/wp-includes/ID3/module.audio-video.matroska.php
r32979 r41196 235 235 $this->parseEBML($info); 236 236 } catch (Exception $e) { 237 $ info['error'][] = 'EBML parser: '.$e->getMessage();237 $this->error('EBML parser: '.$e->getMessage()); 238 238 } 239 239 … … 331 331 332 332 case 'A_AC3': 333 case 'A_EAC3': 333 334 case 'A_DTS': 334 335 case 'A_MPEG/L3': 335 336 case 'A_MPEG/L2': 336 337 case 'A_FLAC': 337 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true); 338 $module_dataformat = ($track_info['dataformat'] == 'mp2' ? 'mp3' : ($track_info['dataformat'] == 'eac3' ? 'ac3' : $track_info['dataformat'])); 339 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.$module_dataformat.'.php', __FILE__, true); 338 340 339 341 if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) { … … 353 355 354 356 // analyze 355 $class = 'getid3_'. ($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);357 $class = 'getid3_'.$module_dataformat; 356 358 $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat']; 357 359 $getid3_audio = new $class($getid3_temp, __CLASS__); … … 458 460 default: 459 461 $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"'); 462 break; 460 463 } 461 464 … … 525 528 default: 526 529 $this->unhandledElement('header', __LINE__, $element_data); 530 break; 527 531 } 528 532 … … 563 567 default: 564 568 $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry); } 569 break; 565 570 } 566 567 if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required 571 if (!isset($seek_entry['target_id'])) { 572 $this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']); 573 break; 574 } 575 if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required 568 576 $info['matroska']['seek'][] = $seek_entry; 569 577 } … … 572 580 default: 573 581 $this->unhandledElement('seekhead', __LINE__, $seek_entry); 582 break; 574 583 } 575 584 } … … 654 663 default: 655 664 $this->unhandledElement('track.video', __LINE__, $sub_subelement); 665 break; 656 666 } 657 667 } … … 679 689 default: 680 690 $this->unhandledElement('track.audio', __LINE__, $sub_subelement); 691 break; 681 692 } 682 693 } … … 714 725 default: 715 726 $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); 727 break; 716 728 } 717 729 } … … 737 749 default: 738 750 $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); 751 break; 739 752 } 740 753 } … … 743 756 default: 744 757 $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement); 758 break; 745 759 } 746 760 } … … 749 763 default: 750 764 $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement); 765 break; 751 766 } 752 767 } … … 755 770 default: 756 771 $this->unhandledElement('track', __LINE__, $subelement); 772 break; 757 773 } 758 774 } … … 763 779 default: 764 780 $this->unhandledElement('tracks', __LINE__, $track_entry); 781 break; 765 782 } 766 783 } … … 826 843 default: 827 844 $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement); 845 break; 828 846 } 829 847 } … … 833 851 default: 834 852 $this->unhandledElement('info', __LINE__, $subelement); 853 break; 835 854 } 836 855 } … … 869 888 default: 870 889 $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement); 890 break; 871 891 } 872 892 } … … 880 900 default: 881 901 $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement); 902 break; 882 903 } 883 904 } … … 887 908 default: 888 909 $this->unhandledElement('cues', __LINE__, $subelement); 910 break; 889 911 } 890 912 } … … 928 950 default: 929 951 $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement); 952 break; 930 953 } 931 954 } … … 939 962 default: 940 963 $this->unhandledElement('tags.tag', __LINE__, $sub_subelement); 964 break; 941 965 } 942 966 } … … 946 970 default: 947 971 $this->unhandledElement('tags', __LINE__, $subelement); 972 break; 948 973 } 949 974 } … … 986 1011 default: 987 1012 $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement); 1013 break; 988 1014 } 989 1015 } … … 993 1019 default: 994 1020 $this->unhandledElement('attachments', __LINE__, $subelement); 1021 break; 995 1022 } 996 1023 } … … 1052 1079 default: 1053 1080 $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement); 1081 break; 1054 1082 } 1055 1083 } … … 1071 1099 default: 1072 1100 $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement); 1101 break; 1073 1102 } 1074 1103 } … … 1078 1107 default: 1079 1108 $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement); 1109 break; 1080 1110 } 1081 1111 } … … 1085 1115 default: 1086 1116 $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement); 1117 break; 1087 1118 } 1088 1119 } … … 1092 1123 default: 1093 1124 $this->unhandledElement('chapters', __LINE__, $subelement); 1125 break; 1094 1126 } 1095 1127 } … … 1120 1152 default: 1121 1153 $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement); 1154 break; 1122 1155 } 1123 1156 } … … 1150 1183 default: 1151 1184 $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement); 1185 break; 1152 1186 } 1153 1187 } … … 1161 1195 default: 1162 1196 $this->unhandledElement('cluster', __LINE__, $subelement); 1197 break; 1163 1198 } 1164 1199 $this->current_offset = $subelement['end']; … … 1182 1217 default: 1183 1218 $this->unhandledElement('segment', __LINE__, $element_data); 1219 break; 1184 1220 } 1185 1221 } … … 1188 1224 default: 1189 1225 $this->unhandledElement('root', __LINE__, $top_element); 1226 break; 1190 1227 } 1191 1228 } … … 1340 1377 default: 1341 1378 $this->unhandledElement('tag.simpletag', __LINE__, $element); 1379 break; 1342 1380 } 1343 1381 } … … 1491 1529 $CodecIDlist['A_AAC/MPEG2/LC'] = 'aac'; 1492 1530 $CodecIDlist['A_AC3'] = 'ac3'; 1531 $CodecIDlist['A_EAC3'] = 'eac3'; 1493 1532 $CodecIDlist['A_DTS'] = 'dts'; 1494 1533 $CodecIDlist['A_FLAC'] = 'flac'; -
trunk/src/wp-includes/ID3/module.audio-video.quicktime.php
r32979 r41196 36 36 $offset = 0; 37 37 $atomcounter = 0; 38 $atom_data_read_buffer_size = ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 2) : $this->getid3->option_fread_buffer_size * 1024); // allow [default: 32MB] if PHP configured with no memory_limit38 $atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB] 39 39 while ($offset < $info['avdataend']) { 40 40 if (!getid3_lib::intValueSupported($offset)) { 41 $ info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';41 $this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions'); 42 42 break; 43 43 } … … 58 58 59 59 if (($offset + $atomsize) > $info['avdataend']) { 60 $ info['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)';60 $this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)'); 61 61 return false; 62 62 } … … 80 80 $info['avdataend'] = $info['avdataend_tmp']; 81 81 unset($info['avdataend_tmp']); 82 } 83 84 if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) { 85 $durations = $this->quicktime_time_to_sample_table($info); 86 for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) { 87 $bookmark = array(); 88 $bookmark['title'] = $info['quicktime']['comments']['chapters'][$i]; 89 if (isset($durations[$i])) { 90 $bookmark['duration_sample'] = $durations[$i]['sample_duration']; 91 if ($i > 0) { 92 $bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample']; 93 } else { 94 $bookmark['start_sample'] = 0; 95 } 96 if ($time_scale = $this->quicktime_bookmark_time_scale($info)) { 97 $bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale; 98 $bookmark['start_seconds'] = $bookmark['start_sample'] / $time_scale; 99 } 100 } 101 $info['quicktime']['bookmarks'][] = $bookmark; 102 } 103 } 104 105 if (isset($info['quicktime']['temp_meta_key_names'])) { 106 unset($info['quicktime']['temp_meta_key_names']); 107 } 108 109 if (!empty($info['quicktime']['comments']['location.ISO6709'])) { 110 // https://en.wikipedia.org/wiki/ISO_6709 111 foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) { 112 $latitude = false; 113 $longitude = false; 114 $altitude = false; 115 if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) { 116 @list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches; 117 118 if (strlen($lat_deg) == 2) { // [+-]DD.D 119 $latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec); 120 } elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M 121 $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60); 122 } elseif (strlen($lat_deg) == 6) { // [+-]DDMMSS.S 123 $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600); 124 } 125 126 if (strlen($lon_deg) == 3) { // [+-]DDD.D 127 $longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec); 128 } elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M 129 $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60); 130 } elseif (strlen($lon_deg) == 7) { // [+-]DDDMMSS.S 131 $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600); 132 } 133 134 if (strlen($alt_deg) == 3) { // [+-]DDD.D 135 $altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec); 136 } elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M 137 $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60); 138 } elseif (strlen($alt_deg) == 7) { // [+-]DDDMMSS.S 139 $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600); 140 } 141 142 if ($latitude !== false) { 143 $info['quicktime']['comments']['gps_latitude'][] = (($lat_sign == '-') ? -1 : 1) * floatval($latitude); 144 } 145 if ($longitude !== false) { 146 $info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude); 147 } 148 if ($altitude !== false) { 149 $info['quicktime']['comments']['gps_altitude'][] = (($alt_sign == '-') ? -1 : 1) * floatval($altitude); 150 } 151 } 152 if ($latitude === false) { 153 $this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug'); 154 } 155 break; 156 } 82 157 } 83 158 … … 99 174 } 100 175 } 101 if ( ($info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) {176 if ($info['audio']['dataformat'] == 'mp4') { 102 177 $info['fileformat'] = 'mp4'; 103 $info['mime_type'] = 'audio/mp4'; 104 unset($info['video']['dataformat']); 178 if (empty($info['video']['resolution_x'])) { 179 $info['mime_type'] = 'audio/mp4'; 180 unset($info['video']['dataformat']); 181 } else { 182 $info['mime_type'] = 'video/mp4'; 183 } 105 184 } 106 185 … … 121 200 public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { 122 201 // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm 202 // https://code.google.com/p/mp4v2/wiki/iTunesMetadata 123 203 124 204 $info = &$this->getid3->info; … … 223 303 224 304 305 case "\xA9".'alb': // ALBum 306 case "\xA9".'ART': // 307 case "\xA9".'art': // ARTist 308 case "\xA9".'aut': // 309 case "\xA9".'cmt': // CoMmenT 310 case "\xA9".'com': // COMposer 311 case "\xA9".'cpy': // 312 case "\xA9".'day': // content created year 313 case "\xA9".'dir': // 314 case "\xA9".'ed1': // 315 case "\xA9".'ed2': // 316 case "\xA9".'ed3': // 317 case "\xA9".'ed4': // 318 case "\xA9".'ed5': // 319 case "\xA9".'ed6': // 320 case "\xA9".'ed7': // 321 case "\xA9".'ed8': // 322 case "\xA9".'ed9': // 323 case "\xA9".'enc': // 324 case "\xA9".'fmt': // 325 case "\xA9".'gen': // GENre 326 case "\xA9".'grp': // GRouPing 327 case "\xA9".'hst': // 328 case "\xA9".'inf': // 329 case "\xA9".'lyr': // LYRics 330 case "\xA9".'mak': // 331 case "\xA9".'mod': // 332 case "\xA9".'nam': // full NAMe 333 case "\xA9".'ope': // 334 case "\xA9".'PRD': // 335 case "\xA9".'prf': // 336 case "\xA9".'req': // 337 case "\xA9".'src': // 338 case "\xA9".'swr': // 339 case "\xA9".'too': // encoder 340 case "\xA9".'trk': // TRacK 341 case "\xA9".'url': // 342 case "\xA9".'wrn': // 343 case "\xA9".'wrt': // WRiTer 344 case '----': // itunes specific 225 345 case 'aART': // Album ARTist 346 case 'akID': // iTunes store account type 347 case 'apID': // Purchase Account 348 case 'atID': // 226 349 case 'catg': // CaTeGory 350 case 'cmID': // 351 case 'cnID': // 227 352 case 'covr': // COVeR artwork 228 353 case 'cpil': // ComPILation … … 231 356 case 'disk': // DISK number 232 357 case 'egid': // Episode Global ID 358 case 'geID': // 233 359 case 'gnre': // GeNRE 360 case 'hdvd': // HD ViDeo 234 361 case 'keyw': // KEYWord 235 case 'ldes': 362 case 'ldes': // Long DEScription 236 363 case 'pcst': // PodCaST 237 364 case 'pgap': // GAPless Playback 365 case 'plID': // 238 366 case 'purd': // PURchase Date 239 367 case 'purl': // Podcast URL 240 case 'rati': 241 case 'rndu': 242 case 'rpdu': 368 case 'rati': // 369 case 'rndu': // 370 case 'rpdu': // 243 371 case 'rtng': // RaTiNG 244 case 'stik': 372 case 'sfID': // iTunes store country 373 case 'soaa': // SOrt Album Artist 374 case 'soal': // SOrt ALbum 375 case 'soar': // SOrt ARtist 376 case 'soco': // SOrt COmposer 377 case 'sonm': // SOrt NaMe 378 case 'sosn': // SOrt Show Name 379 case 'stik': // 245 380 case 'tmpo': // TeMPO (BPM) 246 381 case 'trkn': // TRacK Number 382 case 'tven': // tvEpisodeID 247 383 case 'tves': // TV EpiSode 248 384 case 'tvnn': // TV Network Name 249 385 case 'tvsh': // TV SHow Name 250 386 case 'tvsn': // TV SeasoN 251 case 'akID': // iTunes store account type252 case 'apID':253 case 'atID':254 case 'cmID':255 case 'cnID':256 case 'geID':257 case 'plID':258 case 'sfID': // iTunes store country259 case "\xA9".'alb': // ALBum260 case "\xA9".'art': // ARTist261 case "\xA9".'ART':262 case "\xA9".'aut':263 case "\xA9".'cmt': // CoMmenT264 case "\xA9".'com': // COMposer265 case "\xA9".'cpy':266 case "\xA9".'day': // content created year267 case "\xA9".'dir':268 case "\xA9".'ed1':269 case "\xA9".'ed2':270 case "\xA9".'ed3':271 case "\xA9".'ed4':272 case "\xA9".'ed5':273 case "\xA9".'ed6':274 case "\xA9".'ed7':275 case "\xA9".'ed8':276 case "\xA9".'ed9':277 case "\xA9".'enc':278 case "\xA9".'fmt':279 case "\xA9".'gen': // GENre280 case "\xA9".'grp': // GRouPing281 case "\xA9".'hst':282 case "\xA9".'inf':283 case "\xA9".'lyr': // LYRics284 case "\xA9".'mak':285 case "\xA9".'mod':286 case "\xA9".'nam': // full NAMe287 case "\xA9".'ope':288 case "\xA9".'PRD':289 case "\xA9".'prd':290 case "\xA9".'prf':291 case "\xA9".'req':292 case "\xA9".'src':293 case "\xA9".'swr':294 case "\xA9".'too': // encoder295 case "\xA9".'trk': // TRacK296 case "\xA9".'url':297 case "\xA9".'wrn':298 case "\xA9".'wrt': // WRiTer299 case '----': // itunes specific300 387 if ($atom_parent == 'udta') { 301 388 // User data atom handler … … 319 406 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); 320 407 if ($boxsmallsize <= 1) { 321 $ info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);408 $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 322 409 $atom_structure['data'] = null; 323 410 $atomoffset = strlen($atom_data); … … 329 416 break; 330 417 default: 331 $ info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset;418 $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset); 332 419 $atom_structure['data'] = $atom_data; 333 420 break; … … 341 428 $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); 342 429 if ($boxsize <= 1) { 343 $ info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);430 $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 344 431 $atom_structure['data'] = null; 345 432 $atomoffset = strlen($atom_data); … … 362 449 switch ($atomname) { 363 450 case 'cpil': 451 case 'hdvd': 364 452 case 'pcst': 365 453 case 'pgap': 454 // 8-bit integer (boolean) 366 455 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 367 456 break; 368 457 369 458 case 'tmpo': 459 // 16-bit integer 370 460 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); 371 461 break; … … 373 463 case 'disk': 374 464 case 'trkn': 465 // binary 375 466 $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); 376 467 $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); … … 380 471 381 472 case 'gnre': 473 // enum 382 474 $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 383 475 $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); … … 385 477 386 478 case 'rtng': 479 // 8-bit integer 387 480 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 388 481 $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); … … 390 483 391 484 case 'stik': 485 // 8-bit integer (enum) 392 486 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 393 487 $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); … … 395 489 396 490 case 'sfID': 491 // 32-bit integer 397 492 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 398 493 $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); … … 404 499 break; 405 500 501 case 'plID': 502 // 64-bit integer 503 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8)); 504 break; 505 506 case 'covr': 507 $atom_structure['data'] = substr($boxdata, 8); 508 // not a foolproof check, but better than nothing 509 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { 510 $atom_structure['image_mime'] = 'image/jpeg'; 511 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { 512 $atom_structure['image_mime'] = 'image/png'; 513 } elseif (preg_match('#^GIF#', $atom_structure['data'])) { 514 $atom_structure['image_mime'] = 'image/gif'; 515 } 516 break; 517 518 case 'atID': 519 case 'cnID': 520 case 'geID': 521 case 'tves': 522 case 'tvsn': 406 523 default: 524 // 32-bit integer 407 525 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 408 526 } … … 415 533 if ($atomname == 'covr') { 416 534 // not a foolproof check, but better than nothing 417 if (preg_match('#^\ xFF\xD8\xFF#', $atom_structure['data'])) {535 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { 418 536 $atom_structure['image_mime'] = 'image/jpeg'; 419 } elseif (preg_match('#^\ x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) {537 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { 420 538 $atom_structure['image_mime'] = 'image/png'; 421 539 } elseif (preg_match('#^GIF#', $atom_structure['data'])) { … … 429 547 430 548 default: 431 $ info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset;549 $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset); 432 550 $atom_structure['data'] = $atom_data; 433 551 … … 477 595 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); 478 596 } else { 479 $ info['warning'][] = 'Error decompressing compressed MOV atom at offset '.$atom_structure['offset'];597 $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); 480 598 } 481 599 break; … … 596 714 $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; 597 715 } else { 598 $ info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')';716 $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); 599 717 } 600 718 break; … … 605 723 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 606 724 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 725 726 // see: https://github.com/JamesHeinrich/getID3/issues/111 727 // Some corrupt files have been known to have high bits set in the number_entries field 728 // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000 729 // Workaround: mask off the upper byte and throw a warning if it's nonzero 730 if ($atom_structure['number_entries'] > 0x000FFFFF) { 731 if ($atom_structure['number_entries'] > 0x00FFFFFF) { 732 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF)); 733 $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF); 734 } else { 735 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111'); 736 } 737 } 738 607 739 $stsdEntriesDataOffset = 8; 608 740 for ($i = 0; $i < $atom_structure['number_entries']; $i++) { … … 802 934 $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']); 803 935 if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { 804 $ info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).';936 $this->warning('QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).'); 805 937 } 806 938 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { … … 929 1061 $atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4)); 930 1062 $drefDataOffset += 4; 931 $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4);1063 $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4); 932 1064 $drefDataOffset += 4; 933 1065 $atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1)); … … 935 1067 $atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000 936 1068 $drefDataOffset += 3; 937 $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));1069 $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); 938 1070 $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); 939 1071 … … 1002 1134 1003 1135 if ($atom_structure['time_scale'] == 0) { 1004 $ info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';1136 $this->error('Corrupt Quicktime file: mdhd.time_scale == zero'); 1005 1137 return false; 1006 1138 } 1007 $info['quicktime']['time_scale'] = ( isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);1139 $info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']); 1008 1140 1009 1141 $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); … … 1020 1152 $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format" 1021 1153 $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00 1022 $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT'1154 $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT' 1023 1155 $atom_structure['atom_index'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01 1024 1156 … … 1030 1162 $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box, 1031 1163 $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields 1032 $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region.1164 $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region. 1033 1165 break; 1034 1166 … … 1116 1248 1117 1249 if ($atom_structure['time_scale'] == 0) { 1118 $ info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';1250 $this->error('Corrupt Quicktime file: mvhd.time_scale == zero'); 1119 1251 return false; 1120 1252 } 1121 1253 $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); 1122 1254 $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); 1123 $info['quicktime']['time_scale'] = ( isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);1255 $info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']); 1124 1256 $info['quicktime']['display_scale'] = $atom_structure['matrix_a']; 1125 1257 $info['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; … … 1241 1373 1242 1374 // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field 1243 while (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) 1375 while (($mdat_offset < (strlen($atom_data) - 8)) 1376 && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) 1244 1377 && ($chapter_string_length < 1000) 1245 1378 && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2)) 1246 && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) { 1379 && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) { 1380 list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches; 1247 1381 $mdat_offset += (2 + $chapter_string_length); 1248 @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0]; 1249 } 1250 1382 @$info['quicktime']['comments']['chapters'][] = $chapter_string; 1383 1384 // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled) 1385 if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8 1386 $mdat_offset += 12; 1387 } 1388 } 1251 1389 1252 1390 … … 1266 1404 if (!empty($getid3_temp->info['warning'])) { 1267 1405 foreach ($getid3_temp->info['warning'] as $value) { 1268 $ info['warning'][] = $value;1406 $this->warning($value); 1269 1407 } 1270 1408 } … … 1369 1507 } 1370 1508 } else { 1371 $ info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.';1509 $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.'); 1372 1510 } 1373 1511 break; … … 1398 1536 1399 1537 case "\x00\x00\x00\x00": 1400 case 'meta': // METAdata atom1401 1538 // some kind of metacontainer, may contain a big data dump such as: 1402 1539 // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4 1403 1540 // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt 1404 1541 1405 1406 1407 1542 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1543 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); 1544 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 1408 1545 //$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 1409 1546 break; 1410 1547 1548 case 'meta': // METAdata atom 1549 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html 1550 1551 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1552 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); 1553 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 1554 break; 1555 1411 1556 case 'data': // metaDATA atom 1557 static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other 1412 1558 // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data 1413 1559 $atom_structure['language'] = substr($atom_data, 4 + 0, 2); 1414 1560 $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2)); 1415 1561 $atom_structure['data'] = substr($atom_data, 4 + 4); 1416 break; 1562 $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++]; 1563 1564 if ($atom_structure['key_name'] && $atom_structure['data']) { 1565 @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data']; 1566 } 1567 break; 1568 1569 case 'keys': // KEYS that may be present in the metadata atom. 1570 // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21 1571 // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom. 1572 // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys". 1573 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 1574 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); 1575 $atom_structure['entry_count'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 1576 $keys_atom_offset = 8; 1577 for ($i = 1; $i <= $atom_structure['entry_count']; $i++) { 1578 $atom_structure['keys'][$i]['key_size'] = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4)); 1579 $atom_structure['keys'][$i]['key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4); 1580 $atom_structure['keys'][$i]['key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8); 1581 $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace 1582 1583 $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value']; 1584 } 1585 break; 1586 1587 case 'gps ': 1588 // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730 1589 // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data. 1590 // The first row is version/metadata/notsure, I skip that. 1591 // The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file. 1592 1593 $GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size 1594 if (strlen($atom_data) > 0) { 1595 if ((strlen($atom_data) % $GPS_rowsize) == 0) { 1596 $atom_structure['gps_toc'] = array(); 1597 foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) { 1598 $atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize)); 1599 } 1600 1601 $atom_structure['gps_entries'] = array(); 1602 $previous_offset = $this->ftell(); 1603 foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) { 1604 if ($key == 0) { 1605 // "The first row is version/metadata/notsure, I skip that." 1606 continue; 1607 } 1608 $this->fseek($gps_pointer['offset']); 1609 $GPS_free_data = $this->fread($gps_pointer['size']); 1610 1611 /* 1612 // 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead 1613 1614 // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730 1615 // The structure of the GPS data atom (the 'free' atoms mentioned above) is following: 1616 // hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48) 1617 // For those unfamiliar with python struct: 1618 // I = int 1619 // s = is string (size 1, in this case) 1620 // f = float 1621 1622 //$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48)); 1623 */ 1624 1625 // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62 1626 // $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67 1627 // $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F 1628 // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D 1629 if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) { 1630 $GPS_this_GPRMC = array(); 1631 list( 1632 $GPS_this_GPRMC['raw']['gprmc'], 1633 $GPS_this_GPRMC['raw']['timestamp'], 1634 $GPS_this_GPRMC['raw']['status'], 1635 $GPS_this_GPRMC['raw']['latitude'], 1636 $GPS_this_GPRMC['raw']['latitude_direction'], 1637 $GPS_this_GPRMC['raw']['longitude'], 1638 $GPS_this_GPRMC['raw']['longitude_direction'], 1639 $GPS_this_GPRMC['raw']['knots'], 1640 $GPS_this_GPRMC['raw']['angle'], 1641 $GPS_this_GPRMC['raw']['datestamp'], 1642 $GPS_this_GPRMC['raw']['variation'], 1643 $GPS_this_GPRMC['raw']['variation_direction'], 1644 $dummy, 1645 $GPS_this_GPRMC['raw']['checksum'], 1646 ) = $matches; 1647 1648 $hour = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2); 1649 $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2); 1650 $second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2); 1651 $ms = substr($GPS_this_GPRMC['raw']['timestamp'], 6); // may contain decimal seconds 1652 $day = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2); 1653 $month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2); 1654 $year = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2); 1655 $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess 1656 $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms; 1657 1658 $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void 1659 1660 foreach (array('latitude','longitude') as $latlon) { 1661 preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches); 1662 list($dummy, $deg, $min) = $matches; 1663 $GPS_this_GPRMC[$latlon] = $deg + ($min / 60); 1664 } 1665 $GPS_this_GPRMC['latitude'] *= (($GPS_this_GPRMC['raw']['latitude_direction'] == 'S') ? -1 : 1); 1666 $GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1); 1667 1668 $GPS_this_GPRMC['heading'] = $GPS_this_GPRMC['raw']['angle']; 1669 $GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots']; 1670 $GPS_this_GPRMC['speed_kmh'] = $GPS_this_GPRMC['raw']['knots'] * 1.852; 1671 if ($GPS_this_GPRMC['raw']['variation']) { 1672 $GPS_this_GPRMC['variation'] = $GPS_this_GPRMC['raw']['variation']; 1673 $GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1); 1674 } 1675 1676 $atom_structure['gps_entries'][$key] = $GPS_this_GPRMC; 1677 1678 @$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array( 1679 'latitude' => $GPS_this_GPRMC['latitude'], 1680 'longitude' => $GPS_this_GPRMC['longitude'], 1681 'speed_kmh' => $GPS_this_GPRMC['speed_kmh'], 1682 'heading' => $GPS_this_GPRMC['heading'], 1683 ); 1684 1685 } else { 1686 $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']); 1687 } 1688 } 1689 $this->fseek($previous_offset); 1690 1691 } else { 1692 $this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset); 1693 } 1694 } else { 1695 $this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset); 1696 } 1697 break; 1698 1699 case 'loci':// 3GP location (El Loco) 1700 $info['quicktime']['comments']['gps_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 1701 $info['quicktime']['comments']['gps_lang'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 1702 $loffset = 0; 1703 $info['quicktime']['comments']['gps_location'] = $this->LociString(substr($atom_data, 6), $loffset); 1704 $loci_data=substr($atom_data, 6 + $loffset); 1705 $info['quicktime']['comments']['gps_role'] = getid3_lib::BigEndian2Int(substr($loci_data, 0, 1)); 1706 $info['quicktime']['comments']['gps_longitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4)); 1707 $info['quicktime']['comments']['gps_latitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4)); 1708 $info['quicktime']['comments']['gps_altitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4)); 1709 $info['quicktime']['comments']['gps_body'] = $this->LociString(substr($loci_data, 13), $loffset); 1710 $info['quicktime']['comments']['gps_notes'] = $this->LociString(substr($loci_data, 13 + $loffset), $loffset); 1711 break; 1417 1712 1418 1713 default: 1419 $ info['warning'][] = 'Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;1714 $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset); 1420 1715 $atom_structure['data'] = $atom_data; 1421 1716 break; … … 1441 1736 // terminated by a 32-bit integer set to 0. If you are writing a program 1442 1737 // to read user data atoms, you should allow for the terminating 0. 1738 if (strlen($atom_data) > 12) { 1739 $subatomoffset += 4; 1740 continue; 1741 } 1443 1742 return $atom_structure; 1444 1743 } … … 1754 2053 if (empty($QuicktimeIODSaudioProfileNameLookup)) { 1755 2054 $QuicktimeIODSaudioProfileNameLookup = array( 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 2055 0x00 => 'ISO Reserved (0x00)', 2056 0x01 => 'Main Audio Profile @ Level 1', 2057 0x02 => 'Main Audio Profile @ Level 2', 2058 0x03 => 'Main Audio Profile @ Level 3', 2059 0x04 => 'Main Audio Profile @ Level 4', 2060 0x05 => 'Scalable Audio Profile @ Level 1', 2061 0x06 => 'Scalable Audio Profile @ Level 2', 2062 0x07 => 'Scalable Audio Profile @ Level 3', 2063 0x08 => 'Scalable Audio Profile @ Level 4', 2064 0x09 => 'Speech Audio Profile @ Level 1', 2065 0x0A => 'Speech Audio Profile @ Level 2', 2066 0x0B => 'Synthetic Audio Profile @ Level 1', 2067 0x0C => 'Synthetic Audio Profile @ Level 2', 2068 0x0D => 'Synthetic Audio Profile @ Level 3', 2069 0x0E => 'High Quality Audio Profile @ Level 1', 2070 0x0F => 'High Quality Audio Profile @ Level 2', 2071 0x10 => 'High Quality Audio Profile @ Level 3', 2072 0x11 => 'High Quality Audio Profile @ Level 4', 2073 0x12 => 'High Quality Audio Profile @ Level 5', 2074 0x13 => 'High Quality Audio Profile @ Level 6', 2075 0x14 => 'High Quality Audio Profile @ Level 7', 2076 0x15 => 'High Quality Audio Profile @ Level 8', 2077 0x16 => 'Low Delay Audio Profile @ Level 1', 2078 0x17 => 'Low Delay Audio Profile @ Level 2', 2079 0x18 => 'Low Delay Audio Profile @ Level 3', 2080 0x19 => 'Low Delay Audio Profile @ Level 4', 2081 0x1A => 'Low Delay Audio Profile @ Level 5', 2082 0x1B => 'Low Delay Audio Profile @ Level 6', 2083 0x1C => 'Low Delay Audio Profile @ Level 7', 2084 0x1D => 'Low Delay Audio Profile @ Level 8', 2085 0x1E => 'Natural Audio Profile @ Level 1', 2086 0x1F => 'Natural Audio Profile @ Level 2', 2087 0x20 => 'Natural Audio Profile @ Level 3', 2088 0x21 => 'Natural Audio Profile @ Level 4', 2089 0x22 => 'Mobile Audio Internetworking Profile @ Level 1', 2090 0x23 => 'Mobile Audio Internetworking Profile @ Level 2', 2091 0x24 => 'Mobile Audio Internetworking Profile @ Level 3', 2092 0x25 => 'Mobile Audio Internetworking Profile @ Level 4', 2093 0x26 => 'Mobile Audio Internetworking Profile @ Level 5', 2094 0x27 => 'Mobile Audio Internetworking Profile @ Level 6', 2095 0x28 => 'AAC Profile @ Level 1', 2096 0x29 => 'AAC Profile @ Level 2', 2097 0x2A => 'AAC Profile @ Level 4', 2098 0x2B => 'AAC Profile @ Level 5', 2099 0x2C => 'High Efficiency AAC Profile @ Level 2', 2100 0x2D => 'High Efficiency AAC Profile @ Level 3', 2101 0x2E => 'High Efficiency AAC Profile @ Level 4', 2102 0x2F => 'High Efficiency AAC Profile @ Level 5', 2103 0xFE => 'Not part of MPEG-4 audio profiles', 2104 0xFF => 'No audio capability required', 1806 2105 ); 1807 2106 } … … 2112 2411 static $handyatomtranslatorarray = array(); 2113 2412 if (empty($handyatomtranslatorarray)) { 2413 // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt 2414 // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt 2415 // http://atomicparsley.sourceforge.net/mpeg-4files.html 2416 // https://code.google.com/p/mp4v2/wiki/iTunesMetadata 2417 $handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.0 2418 $handyatomtranslatorarray["\xA9".'ART'] = 'artist'; 2419 $handyatomtranslatorarray["\xA9".'art'] = 'artist'; // iTunes 4.0 2420 $handyatomtranslatorarray["\xA9".'aut'] = 'author'; 2421 $handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.0 2422 $handyatomtranslatorarray["\xA9".'com'] = 'comment'; 2114 2423 $handyatomtranslatorarray["\xA9".'cpy'] = 'copyright'; 2115 $handyatomtranslatorarray["\xA9".'day'] = 'creation_date'; // iTunes 4.02424 $handyatomtranslatorarray["\xA9".'day'] = 'creation_date'; // iTunes 4.0 2116 2425 $handyatomtranslatorarray["\xA9".'dir'] = 'director'; 2117 2426 $handyatomtranslatorarray["\xA9".'ed1'] = 'edit1'; … … 2124 2433 $handyatomtranslatorarray["\xA9".'ed8'] = 'edit8'; 2125 2434 $handyatomtranslatorarray["\xA9".'ed9'] = 'edit9'; 2435 $handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by'; 2126 2436 $handyatomtranslatorarray["\xA9".'fmt'] = 'format'; 2437 $handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.0 2438 $handyatomtranslatorarray["\xA9".'grp'] = 'grouping'; // iTunes 4.2 2439 $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer'; 2127 2440 $handyatomtranslatorarray["\xA9".'inf'] = 'information'; 2441 $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics'; // iTunes 5.0 2442 $handyatomtranslatorarray["\xA9".'mak'] = 'make'; 2443 $handyatomtranslatorarray["\xA9".'mod'] = 'model'; 2444 $handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.0 2445 $handyatomtranslatorarray["\xA9".'ope'] = 'composer'; 2128 2446 $handyatomtranslatorarray["\xA9".'prd'] = 'producer'; 2447 $handyatomtranslatorarray["\xA9".'PRD'] = 'product'; 2129 2448 $handyatomtranslatorarray["\xA9".'prf'] = 'performers'; 2130 2449 $handyatomtranslatorarray["\xA9".'req'] = 'system_requirements'; 2131 2450 $handyatomtranslatorarray["\xA9".'src'] = 'source_credit'; 2132 $handyatomtranslatorarray["\xA9".'wrt'] = 'writer'; 2133 2134 // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt 2135 $handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.0 2136 $handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.0 2451 $handyatomtranslatorarray["\xA9".'swr'] = 'software'; 2452 $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool'; // iTunes 4.0 2453 $handyatomtranslatorarray["\xA9".'trk'] = 'track'; 2454 $handyatomtranslatorarray["\xA9".'url'] = 'url'; 2137 2455 $handyatomtranslatorarray["\xA9".'wrn'] = 'warning'; 2138 $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer'; 2139 $handyatomtranslatorarray["\xA9".'mak'] = 'make'; 2140 $handyatomtranslatorarray["\xA9".'mod'] = 'model'; 2141 $handyatomtranslatorarray["\xA9".'PRD'] = 'product'; 2142 $handyatomtranslatorarray["\xA9".'swr'] = 'software'; 2143 $handyatomtranslatorarray["\xA9".'aut'] = 'author'; 2144 $handyatomtranslatorarray["\xA9".'ART'] = 'artist'; 2145 $handyatomtranslatorarray["\xA9".'trk'] = 'track'; 2146 $handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.0 2147 $handyatomtranslatorarray["\xA9".'com'] = 'comment'; 2148 $handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.0 2149 $handyatomtranslatorarray["\xA9".'ope'] = 'composer'; 2150 $handyatomtranslatorarray["\xA9".'url'] = 'url'; 2151 $handyatomtranslatorarray["\xA9".'enc'] = 'encoder'; 2152 2153 // http://atomicparsley.sourceforge.net/mpeg-4files.html 2154 $handyatomtranslatorarray["\xA9".'art'] = 'artist'; // iTunes 4.0 2456 $handyatomtranslatorarray["\xA9".'wrt'] = 'composer'; 2155 2457 $handyatomtranslatorarray['aART'] = 'album_artist'; 2156 $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0 2157 $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0 2158 $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0 2159 $handyatomtranslatorarray["\xA9".'too'] = 'encoder'; // iTunes 4.0 2160 $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0 2161 $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0? 2162 $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0 2163 $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0 2164 $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0 2165 $handyatomtranslatorarray["\xA9".'grp'] = 'grouping'; // iTunes 4.2 2166 $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9 2167 $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9 2168 $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9 2169 $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9 2170 $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9 2171 $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9 2172 $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0 2173 $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics'; // iTunes 5.0 2174 $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0 2175 $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0 2176 $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0 2177 $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0 2178 $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2 2179 $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0 2180 2181 // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt 2182 2183 2458 $handyatomtranslatorarray['apID'] = 'purchase_account'; 2459 $handyatomtranslatorarray['catg'] = 'category'; // iTunes 4.9 2460 $handyatomtranslatorarray['covr'] = 'picture'; // iTunes 4.0 2461 $handyatomtranslatorarray['cpil'] = 'compilation'; // iTunes 4.0 2462 $handyatomtranslatorarray['cprt'] = 'copyright'; // iTunes 4.0? 2463 $handyatomtranslatorarray['desc'] = 'description'; // iTunes 5.0 2464 $handyatomtranslatorarray['disk'] = 'disc_number'; // iTunes 4.0 2465 $handyatomtranslatorarray['egid'] = 'episode_guid'; // iTunes 4.9 2466 $handyatomtranslatorarray['gnre'] = 'genre'; // iTunes 4.0 2467 $handyatomtranslatorarray['hdvd'] = 'hd_video'; // iTunes 4.0 2468 $handyatomtranslatorarray['ldes'] = 'description_long'; // 2469 $handyatomtranslatorarray['keyw'] = 'keyword'; // iTunes 4.9 2470 $handyatomtranslatorarray['pcst'] = 'podcast'; // iTunes 4.9 2471 $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0 2472 $handyatomtranslatorarray['purd'] = 'purchase_date'; // iTunes 6.0.2 2473 $handyatomtranslatorarray['purl'] = 'podcast_url'; // iTunes 4.9 2474 $handyatomtranslatorarray['rtng'] = 'rating'; // iTunes 4.0 2475 $handyatomtranslatorarray['soaa'] = 'sort_album_artist'; // 2476 $handyatomtranslatorarray['soal'] = 'sort_album'; // 2477 $handyatomtranslatorarray['soar'] = 'sort_artist'; // 2478 $handyatomtranslatorarray['soco'] = 'sort_composer'; // 2479 $handyatomtranslatorarray['sonm'] = 'sort_title'; // 2480 $handyatomtranslatorarray['sosn'] = 'sort_show'; // 2481 $handyatomtranslatorarray['stik'] = 'stik'; // iTunes 4.9 2482 $handyatomtranslatorarray['tmpo'] = 'bpm'; // iTunes 4.0 2483 $handyatomtranslatorarray['trkn'] = 'track_number'; // iTunes 4.0 2484 $handyatomtranslatorarray['tven'] = 'tv_episode_id'; // 2485 $handyatomtranslatorarray['tves'] = 'tv_episode'; // iTunes 6.0 2486 $handyatomtranslatorarray['tvnn'] = 'tv_network_name'; // iTunes 6.0 2487 $handyatomtranslatorarray['tvsh'] = 'tv_show_name'; // iTunes 6.0 2488 $handyatomtranslatorarray['tvsn'] = 'tv_season'; // iTunes 6.0 2184 2489 2185 2490 // boxnames: … … 2226 2531 } 2227 2532 } 2228 $info['quicktime']['comments'][$comment_key][] = $data; 2533 $gooddata = array($data); 2534 if ($comment_key == 'genre') { 2535 // some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal" 2536 $gooddata = explode(';', $data); 2537 } 2538 foreach ($gooddata as $data) { 2539 $info['quicktime']['comments'][$comment_key][] = $data; 2540 } 2229 2541 } 2230 2542 return true; 2231 2543 } 2544 2545 public function LociString($lstring, &$count) { 2546 // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM 2547 // Also need to return the number of bytes the string occupied so additional fields can be extracted 2548 $len = strlen($lstring); 2549 if ($len == 0) { 2550 $count = 0; 2551 return ''; 2552 } 2553 if ($lstring[0] == "\x00") { 2554 $count = 1; 2555 return ''; 2556 } 2557 //check for BOM 2558 if ($len > 2 && (($lstring[0] == "\xFE" && $lstring[1] == "\xFF") || ($lstring[0] == "\xFF" && $lstring[1] == "\xFE"))) { 2559 //UTF-16 2560 if (preg_match('/(.*)\x00/', $lstring, $lmatches)){ 2561 $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000 2562 return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]); 2563 } else { 2564 return ''; 2565 } 2566 } else { 2567 //UTF-8 2568 if (preg_match('/(.*)\x00/', $lstring, $lmatches)){ 2569 $count = strlen($lmatches[1]) + 1; //account for trailing \x00 2570 return $lmatches[1]; 2571 }else { 2572 return ''; 2573 } 2574 2575 } 2576 } 2232 2577 2233 2578 public function NoNullString($nullterminatedstring) { … … 2244 2589 } 2245 2590 2591 2592 /* 2593 // helper functions for m4b audiobook chapters 2594 // code by Steffen Hartmann 2015-Nov-08 2595 */ 2596 public function search_tag_by_key($info, $tag, $history, &$result) { 2597 foreach ($info as $key => $value) { 2598 $key_history = $history.'/'.$key; 2599 if ($key === $tag) { 2600 $result[] = array($key_history, $info); 2601 } else { 2602 if (is_array($value)) { 2603 $this->search_tag_by_key($value, $tag, $key_history, $result); 2604 } 2605 } 2606 } 2607 } 2608 2609 public function search_tag_by_pair($info, $k, $v, $history, &$result) { 2610 foreach ($info as $key => $value) { 2611 $key_history = $history.'/'.$key; 2612 if (($key === $k) && ($value === $v)) { 2613 $result[] = array($key_history, $info); 2614 } else { 2615 if (is_array($value)) { 2616 $this->search_tag_by_pair($value, $k, $v, $key_history, $result); 2617 } 2618 } 2619 } 2620 } 2621 2622 public function quicktime_time_to_sample_table($info) { 2623 $res = array(); 2624 $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res); 2625 foreach ($res as $value) { 2626 $stbl_res = array(); 2627 $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res); 2628 if (count($stbl_res) > 0) { 2629 $stts_res = array(); 2630 $this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res); 2631 if (count($stts_res) > 0) { 2632 return $stts_res[0][1]['time_to_sample_table']; 2633 } 2634 } 2635 } 2636 return array(); 2637 } 2638 2639 function quicktime_bookmark_time_scale($info) { 2640 $time_scale = ''; 2641 $ts_prefix_len = 0; 2642 $res = array(); 2643 $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res); 2644 foreach ($res as $value) { 2645 $stbl_res = array(); 2646 $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res); 2647 if (count($stbl_res) > 0) { 2648 $ts_res = array(); 2649 $this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res); 2650 foreach ($ts_res as $value) { 2651 $prefix = substr($value[0], 0, -12); 2652 if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) { 2653 $time_scale = $value[1]['time_scale']; 2654 $ts_prefix_len = strlen($prefix); 2655 } 2656 } 2657 } 2658 } 2659 return $time_scale; 2660 } 2661 /* 2662 // END helper functions for m4b audiobook chapters 2663 */ 2664 2665 2246 2666 } -
trunk/src/wp-includes/ID3/module.audio-video.riff.php
r29734 r41196 191 191 $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag']; 192 192 if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) { 193 $ info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';193 $this->error('Corrupt RIFF file: bitrate_audio == zero'); 194 194 return false; 195 195 } … … 200 200 $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); 201 201 if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { 202 $ info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];202 $this->warning('Audio codec = '.$thisfile_audio['codec']); 203 203 } 204 204 $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; … … 303 303 $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']); 304 304 } else { 305 $ info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';305 $this->warning('RIFF.WAVE.BEXT.origin_time is invalid'); 306 306 } 307 307 } else { 308 $ info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';308 $this->warning('RIFF.WAVE.BEXT.origin_date is invalid'); 309 309 } 310 310 $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author']; … … 386 386 387 387 if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) { 388 $ 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).')';388 $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).')'); 389 389 break; 390 390 } elseif ($SNDM_thisTagSize <= 0) { 391 $ info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';391 $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'); 392 392 break; 393 393 } … … 398 398 $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText; 399 399 } else { 400 $ info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';400 $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')'); 401 401 } 402 402 } … … 429 429 if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) { 430 430 $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0')); 431 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']; 431 $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 432 $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate; 432 433 $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] / 3600); 433 434 $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600)) / 60); … … 436 437 $thisfile_riff_WAVE['iXML'][0]['timecode_string'] = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s, $f); 437 438 $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d', $h, $m, $s, round($f)); 439 unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f); 438 440 } 439 441 unset($parsedXML); … … 571 573 } else { 572 574 // Short by more than one byte, throw warning 573 $ 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)';575 $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)'); 574 576 $info['avdataend'] = $info['filesize']; 575 577 } … … 580 582 // output file appears to be incorrectly *not* padded to nearest WORD boundary 581 583 // Output less severe warning 582 $ 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)';584 $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)'); 583 585 $info['avdataend'] = $info['filesize']; 584 586 } else { 585 587 // Short by more than one byte, throw warning 586 $ 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)';588 $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)'); 587 589 $info['avdataend'] = $info['filesize']; 588 590 } … … 593 595 if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) { 594 596 $info['avdataend']--; 595 $ info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';597 $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'); 596 598 } 597 599 } … … 620 622 } 621 623 if ($info['avdataend'] > $info['filesize']) { 622 $ 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)';624 $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)'); 623 625 $info['avdataend'] = $info['filesize']; 624 626 } … … 661 663 $thisfile_riff_raw_avih['dwMicroSecPerFrame'] = $this->EitherEndian2Int(substr($avihData, 0, 4)); // frame display rate (or 0L) 662 664 if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) { 663 $ info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';665 $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero'); 664 666 return false; 665 667 } … … 859 861 860 862 default: 861 $ info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';863 $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"'); 862 864 break; 863 865 … … 964 966 // forget to pad end of file to make this actually work 965 967 } else { 966 $ info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';968 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 967 969 } 968 970 $info['avdataend'] = $info['filesize']; … … 1021 1023 $thisfile_audio['sample_rate'] = $thisfile_riff_audio['sample_rate']; 1022 1024 if ($thisfile_audio['sample_rate'] == 0) { 1023 $ info['error'][] = 'Corrupted AIFF file: sample_rate == zero';1025 $this->error('Corrupted AIFF file: sample_rate == zero'); 1024 1026 return false; 1025 1027 } … … 1081 1083 $info['avdataend'] = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size']; 1082 1084 if ($info['avdataend'] > $info['filesize']) { 1083 $ info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';1085 $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found'); 1084 1086 } 1085 1087 } … … 1113 1115 1114 1116 default: 1115 $ info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';1117 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"'); 1116 1118 break; 1117 1119 } … … 1131 1133 1132 1134 default: 1133 $ info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';1135 $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"'); 1134 1136 break; 1135 1137 } … … 1171 1173 break; 1172 1174 1175 case 'WEBP': 1176 // https://developers.google.com/speed/webp/docs/riff_container 1177 // https://tools.ietf.org/html/rfc6386 1178 // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt 1179 $info['fileformat'] = 'webp'; 1180 $info['mime_type'] = 'image/webp'; 1181 1182 if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) { 1183 $old_offset = $this->ftell(); 1184 $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size 1185 $WEBP_VP8_header = $this->fread(10); 1186 $this->fseek($old_offset); 1187 if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") { 1188 $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000); 1189 $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20; 1190 $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000); 1191 $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0; 1192 1193 $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14; 1194 $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF); 1195 $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14; 1196 $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF); 1197 1198 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width']; 1199 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height']; 1200 } else { 1201 $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)).'"'); 1202 } 1203 1204 } 1205 if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) { 1206 $old_offset = $this->ftell(); 1207 $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size 1208 $WEBP_VP8L_header = $this->fread(10); 1209 $this->fseek($old_offset); 1210 if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") { 1211 $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4)); 1212 $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1; 1213 $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1; 1214 $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1)); 1215 $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3)); 1216 1217 $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width']; 1218 $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height']; 1219 } else { 1220 $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"'); 1221 } 1222 1223 } 1224 break; 1173 1225 1174 1226 default: 1175 $ info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';1227 $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead'); 1176 1228 //unset($info['fileformat']); 1177 1229 } … … 1186 1238 if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) { 1187 1239 $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]; 1188 $ info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';1240 $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"'); 1189 1241 } 1190 1242 } … … 1510 1562 if (!empty($getid3_temp->info['warning'])) { 1511 1563 foreach ($getid3_temp->info['warning'] as $key => $value) { 1512 $ info['warning'][] = $value;1564 $this->warning($value); 1513 1565 } 1514 1566 } -
trunk/src/wp-includes/ID3/module.audio.ac3.php
r32979 r41196 21 21 private $BSIoffset = 0; 22 22 23 const syncword = "\x0B\x77";23 const syncword = 0x0B77; 24 24 25 25 public function Analyze() { … … 56 56 57 57 $this->fseek($info['avdataoffset']); 58 $this->AC3header['syncinfo'] = $this->fread(5); 59 60 if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) { 61 $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword; 62 $offset = 2; 63 } else { 58 $tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...? 59 $this->AC3header['syncinfo'] = getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2)); 60 $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin(substr($tempAC3header, 2)); 61 $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 62 unset($tempAC3header); 63 64 if ($this->AC3header['syncinfo'] !== self::syncword) { 64 65 if (!$this->isDependencyFor('matroska')) { 65 66 unset($info['fileformat'], $info['ac3']); 66 return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"'); 67 } 68 $offset = 0; 69 $this->fseek(-2, SEEK_CUR); 67 return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"'); 68 } 70 69 } 71 70 … … 74 73 $info['audio']['lossless'] = false; 75 74 76 $thisfile_ac3_raw['synchinfo']['crc1'] = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2)); 77 $ac3_synchinfo_fscod_frmsizecod = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1)); 78 $thisfile_ac3_raw['synchinfo']['fscod'] = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6; 79 $thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F); 80 81 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']); 82 if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) { 83 $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate']; 84 } 85 86 $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']); 87 $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']); 88 $info['audio']['bitrate'] = $thisfile_ac3['bitrate']; 89 90 $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15)); 91 $ac3_bsi_offset = 0; 92 93 $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5); 94 if ($thisfile_ac3_raw_bsi['bsid'] > 8) { 95 // Decoders which can decode version 8 will thus be able to decode version numbers less than 8. 96 // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used. 97 // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8. 98 $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8'); 75 if ($thisfile_ac3_raw_bsi['bsid'] <= 8) { 76 77 $thisfile_ac3_raw_bsi['crc1'] = getid3_lib::Bin2Dec($this->readHeaderBSI(16)); 78 $thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); // 5.4.1.3 79 $thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); // 5.4.1.4 80 if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits) 81 $this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly'); 82 } 83 84 $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 85 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3); 86 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3); 87 88 if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) { 89 // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream. 90 $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2); 91 $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']); 92 } 93 94 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { 95 // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream. 96 $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2); 97 $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']); 98 } 99 100 if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) { 101 // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround. 102 $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2); 103 $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']); 104 } 105 106 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1); 107 108 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. 109 // 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. 110 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits 111 112 $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit 113 if ($thisfile_ac3_raw_bsi['flags']['compr']) { 114 $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); // 5.4.2.10 compr: Compression Gain Word, 8 Bits 115 $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']); 116 } 117 118 $thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1); // 5.4.2.11 langcode: Language Code Exists, 1 Bit 119 if ($thisfile_ac3_raw_bsi['flags']['langcod']) { 120 $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8); // 5.4.2.12 langcod: Language Code, 8 Bits 121 } 122 123 $thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1); // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit 124 if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) { 125 $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); // 5.4.2.14 mixlevel: Mixing Level, 5 Bits 126 $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); // 5.4.2.15 roomtyp: Room Type, 2 Bits 127 128 $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB'; 129 $thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']); 130 } 131 132 133 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits 134 $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. 135 136 $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit 137 if ($thisfile_ac3_raw_bsi['flags']['compr2']) { 138 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits 139 $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']); 140 } 141 142 $thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit 143 if ($thisfile_ac3_raw_bsi['flags']['langcod2']) { 144 $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8); // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits 145 } 146 147 $thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit 148 if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) { 149 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits 150 $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits 151 152 $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB'; 153 $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']); 154 } 155 156 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit 157 158 $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit 159 160 $thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2); // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits 161 if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) { 162 $thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits 163 $thisfile_ac3['timecode1'] = 0; 164 $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 165 $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 166 $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) 167 } 168 if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) { 169 $thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits 170 $thisfile_ac3['timecode2'] = 0; 171 $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) 172 $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) 173 $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 174 } 175 176 $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1); 177 if ($thisfile_ac3_raw_bsi['flags']['addbsi']) { 178 $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. 179 180 $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length'])); 181 182 $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8); 183 $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8; 184 } 185 186 187 } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3 188 189 190 $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.'); 191 $info['audio']['dataformat'] = 'eac3'; 192 193 $thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2); 194 $thisfile_ac3_raw_bsi['substreamid'] = $this->readHeaderBSI(3); 195 $thisfile_ac3_raw_bsi['frmsiz'] = $this->readHeaderBSI(11); 196 $thisfile_ac3_raw_bsi['fscod'] = $this->readHeaderBSI(2); 197 if ($thisfile_ac3_raw_bsi['fscod'] == 3) { 198 $thisfile_ac3_raw_bsi['fscod2'] = $this->readHeaderBSI(2); 199 $thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe 200 } else { 201 $thisfile_ac3_raw_bsi['numblkscod'] = $this->readHeaderBSI(2); 202 } 203 $thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']); 204 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3); 205 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1); 206 $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 207 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); 208 $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1); 209 if ($thisfile_ac3_raw_bsi['flags']['compr']) { 210 $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8); 211 } 212 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value) 213 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5); 214 $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1); 215 if ($thisfile_ac3_raw_bsi['flags']['compr2']) { 216 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8); 217 } 218 } 219 if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream 220 $thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1); 221 if ($thisfile_ac3_raw_bsi['flags']['chanmap']) { 222 $thisfile_ac3_raw_bsi['chanmap'] = $this->readHeaderBSI(8); 223 } 224 } 225 $thisfile_ac3_raw_bsi['flags']['mixmdat'] = (bool) $this->readHeaderBSI(1); 226 if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata 227 if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels 228 $thisfile_ac3_raw_bsi['dmixmod'] = $this->readHeaderBSI(2); 229 } 230 if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist 231 $thisfile_ac3_raw_bsi['ltrtcmixlev'] = $this->readHeaderBSI(3); 232 $thisfile_ac3_raw_bsi['lorocmixlev'] = $this->readHeaderBSI(3); 233 } 234 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists 235 $thisfile_ac3_raw_bsi['ltrtsurmixlev'] = $this->readHeaderBSI(3); 236 $thisfile_ac3_raw_bsi['lorosurmixlev'] = $this->readHeaderBSI(3); 237 } 238 if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists 239 $thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1); 240 if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) { 241 $thisfile_ac3_raw_bsi['lfemixlevcod'] = $this->readHeaderBSI(5); 242 } 243 } 244 if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream 245 $thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1); 246 if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) { 247 $thisfile_ac3_raw_bsi['pgmscl'] = $this->readHeaderBSI(6); 248 } 249 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value) 250 $thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1); 251 if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) { 252 $thisfile_ac3_raw_bsi['pgmscl2'] = $this->readHeaderBSI(6); 253 } 254 } 255 $thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1); 256 if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) { 257 $thisfile_ac3_raw_bsi['extpgmscl'] = $this->readHeaderBSI(6); 258 } 259 $thisfile_ac3_raw_bsi['mixdef'] = $this->readHeaderBSI(2); 260 if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2 261 $thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); 262 $thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); 263 $thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); 264 } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3 265 $thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI(12); 266 } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4 267 $mixdefbitsread = 0; 268 $thisfile_ac3_raw_bsi['mixdeflen'] = $this->readHeaderBSI(5); $mixdefbitsread += 5; 269 $thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 270 if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) { 271 $thisfile_ac3_raw_bsi['premixcmpsel'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 272 $thisfile_ac3_raw_bsi['drcsrc'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 273 $thisfile_ac3_raw_bsi['premixcmpscl'] = $this->readHeaderBSI(3); $mixdefbitsread += 3; 274 $thisfile_ac3_raw_bsi['flags']['extpgmlscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 275 if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) { 276 $thisfile_ac3_raw_bsi['extpgmlscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 277 } 278 $thisfile_ac3_raw_bsi['flags']['extpgmcscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 279 if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) { 280 $thisfile_ac3_raw_bsi['extpgmcscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 281 } 282 $thisfile_ac3_raw_bsi['flags']['extpgmrscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 283 if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) { 284 $thisfile_ac3_raw_bsi['extpgmrscl'] = $this->readHeaderBSI(4); 285 } 286 $thisfile_ac3_raw_bsi['flags']['extpgmlsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 287 if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) { 288 $thisfile_ac3_raw_bsi['extpgmlsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 289 } 290 $thisfile_ac3_raw_bsi['flags']['extpgmrsscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 291 if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) { 292 $thisfile_ac3_raw_bsi['extpgmrsscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 293 } 294 $thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 295 if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) { 296 $thisfile_ac3_raw_bsi['extpgmlfescl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 297 } 298 $thisfile_ac3_raw_bsi['flags']['dmixscl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 299 if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) { 300 $thisfile_ac3_raw_bsi['dmixscl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 301 } 302 $thisfile_ac3_raw_bsi['flags']['addch'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 303 if ($thisfile_ac3_raw_bsi['flags']['addch']) { 304 $thisfile_ac3_raw_bsi['flags']['extpgmaux1scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 305 if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) { 306 $thisfile_ac3_raw_bsi['extpgmaux1scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 307 } 308 $thisfile_ac3_raw_bsi['flags']['extpgmaux2scl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 309 if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) { 310 $thisfile_ac3_raw_bsi['extpgmaux2scl'] = $this->readHeaderBSI(4); $mixdefbitsread += 4; 311 } 312 } 313 } 314 $thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 315 if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) { 316 $thisfile_ac3_raw_bsi['spchdat'] = $this->readHeaderBSI(5); $mixdefbitsread += 5; 317 $thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 318 if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) { 319 $thisfile_ac3_raw_bsi['spchdat1'] = $this->readHeaderBSI(5); $mixdefbitsread += 5; 320 $thisfile_ac3_raw_bsi['spchan1att'] = $this->readHeaderBSI(2); $mixdefbitsread += 2; 321 $thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1; 322 if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) { 323 $thisfile_ac3_raw_bsi['spchdat2'] = $this->readHeaderBSI(5); $mixdefbitsread += 5; 324 $thisfile_ac3_raw_bsi['spchan2att'] = $this->readHeaderBSI(3); $mixdefbitsread += 3; 325 } 326 } 327 } 328 $mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread; 329 $mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0); 330 $thisfile_ac3_raw_bsi['mixdata'] = $this->readHeaderBSI($mixdata_bits); 331 $thisfile_ac3_raw_bsi['mixdatafill'] = $this->readHeaderBSI($mixdata_fill); 332 unset($mixdefbitsread, $mixdata_bits, $mixdata_fill); 333 } 334 if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source 335 $thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1); 336 if ($thisfile_ac3_raw_bsi['flags']['paninfo']) { 337 $thisfile_ac3_raw_bsi['panmean'] = $this->readHeaderBSI(8); 338 $thisfile_ac3_raw_bsi['paninfo'] = $this->readHeaderBSI(6); 339 } 340 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value) 341 $thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1); 342 if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) { 343 $thisfile_ac3_raw_bsi['panmean2'] = $this->readHeaderBSI(8); 344 $thisfile_ac3_raw_bsi['paninfo2'] = $this->readHeaderBSI(6); 345 } 346 } 347 } 348 $thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1); 349 if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information 350 if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) { 351 $thisfile_ac3_raw_bsi['blkmixcfginfo'][0] = $this->readHeaderBSI(5); 352 } else { 353 for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) { 354 $thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1); 355 if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information 356 $thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk] = $this->readHeaderBSI(5); 357 } 358 } 359 } 360 } 361 } 362 } 363 $thisfile_ac3_raw_bsi['flags']['infomdat'] = (bool) $this->readHeaderBSI(1); 364 if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata 365 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3); 366 $thisfile_ac3_raw_bsi['flags']['copyrightb'] = (bool) $this->readHeaderBSI(1); 367 $thisfile_ac3_raw_bsi['flags']['origbs'] = (bool) $this->readHeaderBSI(1); 368 if ($thisfile_ac3_raw_bsi['acmod'] == 2) { // if in 2/0 mode 369 $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2); 370 $thisfile_ac3_raw_bsi['dheadphonmod'] = $this->readHeaderBSI(2); 371 } 372 if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { // if both surround channels exist 373 $thisfile_ac3_raw_bsi['dsurexmod'] = $this->readHeaderBSI(2); 374 } 375 $thisfile_ac3_raw_bsi['flags']['audprodi'] = (bool) $this->readHeaderBSI(1); 376 if ($thisfile_ac3_raw_bsi['flags']['audprodi']) { 377 $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5); 378 $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2); 379 $thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1); 380 } 381 if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value) 382 $thisfile_ac3_raw_bsi['flags']['audprodi2'] = (bool) $this->readHeaderBSI(1); 383 if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) { 384 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5); 385 $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2); 386 $thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1); 387 } 388 } 389 if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate 390 $thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1); 391 } 392 } 393 if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { // if both surround channels exist 394 $thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1); 395 } 396 if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { // if bit stream converted from AC-3 397 if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe 398 $thisfile_ac3_raw_bsi['flags']['blkid'] = 1; 399 } else { 400 $thisfile_ac3_raw_bsi['flags']['blkid'] = (bool) $this->readHeaderBSI(1); 401 } 402 if ($thisfile_ac3_raw_bsi['flags']['blkid']) { 403 $thisfile_ac3_raw_bsi['frmsizecod'] = $this->readHeaderBSI(6); 404 } 405 } 406 $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1); 407 if ($thisfile_ac3_raw_bsi['flags']['addbsi']) { 408 $thisfile_ac3_raw_bsi['addbsil'] = $this->readHeaderBSI(6); 409 $thisfile_ac3_raw_bsi['addbsi'] = $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8); 410 } 411 412 } else { 413 414 $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.'); 99 415 unset($info['ac3']); 100 416 return false; 101 } 102 103 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3); 104 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3); 417 418 } 419 420 if (isset($thisfile_ac3_raw_bsi['fscod2'])) { 421 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']); 422 } else { 423 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']); 424 } 425 if ($thisfile_ac3_raw_bsi['fscod'] <= 3) { 426 $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate']; 427 } else { 428 $this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']); 429 } 430 if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) { 431 $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']); 432 $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']); 433 } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) { 434 // this isn't right, but it's (usually) close, roughly 5% less than it should be. 435 // but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know! 436 $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. 437 // kludge-fix to make it approximately the expected value, still not "right": 438 $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000; 439 } 440 $info['audio']['bitrate'] = $thisfile_ac3['bitrate']; 105 441 106 442 $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); … … 124 460 $info['audio']['channels'] = $thisfile_ac3['num_channels']; 125 461 126 if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) { 127 // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream. 128 $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2); 129 $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']); 130 } 131 132 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { 133 // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream. 134 $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2); 135 $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']); 136 } 137 138 if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) { 139 // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround. 140 $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2); 141 $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']); 142 } 143 144 $thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1); 145 $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon']; 146 if ($thisfile_ac3_raw_bsi['lfeon']) { 147 //$info['audio']['channels']++; 462 $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon']; 463 if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { 148 464 $info['audio']['channels'] .= '.1'; 149 465 } 150 466 151 $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']); 152 153 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. 154 // 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. 155 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5); 467 $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']); 156 468 $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB'; 157 158 $thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);159 if ($thisfile_ac3_raw_bsi['compre_flag']) {160 $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);161 $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);162 }163 164 $thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);165 if ($thisfile_ac3_raw_bsi['langcode_flag']) {166 $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);167 }168 169 $thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);170 if ($thisfile_ac3_raw_bsi['audprodie']) {171 $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);172 $thisfile_ac3_raw_bsi['roomtyp'] = $this->readHeaderBSI(2);173 174 $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';175 $thisfile_ac3['room_type'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);176 }177 178 if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {179 // If acmod is 0, then two completely independent program channels (dual mono)180 // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,181 // a number of additional items are present in BSI or audblk to fully describe Ch2.182 183 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.184 // 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.185 $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);186 $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';187 188 $thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);189 if ($thisfile_ac3_raw_bsi['compre_flag2']) {190 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);191 $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);192 }193 194 $thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);195 if ($thisfile_ac3_raw_bsi['langcode_flag2']) {196 $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);197 }198 199 $thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);200 if ($thisfile_ac3_raw_bsi['audprodie2']) {201 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);202 $thisfile_ac3_raw_bsi['roomtyp2'] = $this->readHeaderBSI(2);203 204 $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';205 $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);206 }207 208 }209 210 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);211 212 $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1);213 214 $thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);215 if ($thisfile_ac3_raw_bsi['timecode1_flag']) {216 $thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);217 }218 219 $thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);220 if ($thisfile_ac3_raw_bsi['timecode2_flag']) {221 $thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);222 }223 224 $thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);225 if ($thisfile_ac3_raw_bsi['addbsi_flag']) {226 $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);227 228 $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));229 230 $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);231 $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;232 }233 469 234 470 return true; … … 250 486 ); 251 487 return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false); 488 } 489 490 public static function sampleRateCodeLookup2($fscod2) { 491 static $sampleRateCodeLookup2 = array( 492 0 => 24000, 493 1 => 22050, 494 2 => 16000, 495 3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute. 496 ); 497 return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false); 252 498 } 253 499 … … 410 656 411 657 public static function frameSizeLookup($frmsizecod, $fscod) { 412 $padding = (bool) ($frmsizecod % 2); 413 $framesizeid = floor($frmsizecod / 2); 658 // LSB is whether padding is used or not 659 $padding = (bool) ($frmsizecod & 0x01); 660 $framesizeid = ($frmsizecod & 0x3E) >> 1; 414 661 415 662 static $frameSizeLookup = array(); 416 663 if (empty($frameSizeLookup)) { 417 664 $frameSizeLookup = array ( 418 0 => array( 128, 138, 192),419 1 => array( 40, 160, 174, 240),420 2 => array( 48, 192, 208, 288),421 3 => array( 56, 224, 242, 336),422 4 => array( 64, 256, 278, 384),423 5 => array( 80, 320, 348, 480),424 6 => array( 96, 384, 416, 576),425 7 => array( 112, 448, 486, 672),426 8 => array( 128, 512, 556, 768),427 9 => array( 160, 640, 696, 960),428 10 => array( 192, 768, 834, 1152),429 11 => array( 224, 896, 974, 1344),430 12 => array( 256, 1024, 1114, 1536),431 13 => array( 320, 1280, 1392, 1920),432 14 => array( 384, 1536, 1670, 2304),433 15 => array( 448, 1792, 1950, 2688),434 16 => array( 512, 2048, 2228, 3072),435 17 => array( 576, 2304, 2506, 3456),436 18 => array( 640, 2560, 2786, 3840)665 0 => array( 128, 138, 192), // 32 kbps 666 1 => array( 160, 174, 240), // 40 kbps 667 2 => array( 192, 208, 288), // 48 kbps 668 3 => array( 224, 242, 336), // 56 kbps 669 4 => array( 256, 278, 384), // 64 kbps 670 5 => array( 320, 348, 480), // 80 kbps 671 6 => array( 384, 416, 576), // 96 kbps 672 7 => array( 448, 486, 672), // 112 kbps 673 8 => array( 512, 556, 768), // 128 kbps 674 9 => array( 640, 696, 960), // 160 kbps 675 10 => array( 768, 834, 1152), // 192 kbps 676 11 => array( 896, 974, 1344), // 224 kbps 677 12 => array(1024, 1114, 1536), // 256 kbps 678 13 => array(1280, 1392, 1920), // 320 kbps 679 14 => array(1536, 1670, 2304), // 384 kbps 680 15 => array(1792, 1950, 2688), // 448 kbps 681 16 => array(2048, 2228, 3072), // 512 kbps 682 17 => array(2304, 2506, 3456), // 576 kbps 683 18 => array(2560, 2786, 3840) // 640 kbps 437 684 ); 438 685 } … … 445 692 446 693 public static function bitrateLookup($frmsizecod) { 447 $framesizeid = floor($frmsizecod / 2); 694 // LSB is whether padding is used or not 695 $padding = (bool) ($frmsizecod & 0x01); 696 $framesizeid = ($frmsizecod & 0x3E) >> 1; 448 697 449 698 static $bitrateLookup = array( 450 0 =>32000,451 1 =>40000,452 2 =>48000,453 3 =>56000,454 4 =>64000,455 5 =>80000,456 6 =>96000,457 7=> 112000,458 8=> 128000,459 9=> 160000,699 0 => 32000, 700 1 => 40000, 701 2 => 48000, 702 3 => 56000, 703 4 => 64000, 704 5 => 80000, 705 6 => 96000, 706 7 => 112000, 707 8 => 128000, 708 9 => 160000, 460 709 10 => 192000, 461 710 11 => 224000, … … 466 715 16 => 512000, 467 716 17 => 576000, 468 18 => 640000 717 18 => 640000, 469 718 ); 470 719 return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false); 471 720 } 472 721 722 public static function blocksPerSyncFrame($numblkscod) { 723 static $blocksPerSyncFrameLookup = array( 724 0 => 1, 725 1 => 2, 726 2 => 3, 727 3 => 6, 728 ); 729 return (isset($blocksPerSyncFrameLookup[$numblkscod]) ? $blocksPerSyncFrameLookup[$numblkscod] : false); 730 } 731 473 732 474 733 } -
trunk/src/wp-includes/ID3/module.audio.mp3.php
r32979 r41196 35 35 if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) { 36 36 if ($this->allow_bruteforce) { 37 $ info['error'][] = 'Rescanning file in BruteForce mode';37 $this->error('Rescanning file in BruteForce mode'); 38 38 $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info); 39 39 } … … 73 73 74 74 } 75 $ info['warning'][] = $synchoffsetwarning;75 $this->warning($synchoffsetwarning); 76 76 77 77 } … … 135 135 136 136 default: 137 $ info['warning'][] = 'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"';137 $this->warning('Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$info['audio']['dataformat'].'"'); 138 138 break; 139 139 } … … 425 425 426 426 if ($this->fseek($offset) != 0) { 427 $ info['error'][] = 'decodeMPEGaudioHeader() failed to seek to next offset at '.$offset;427 $this->error('decodeMPEGaudioHeader() failed to seek to next offset at '.$offset); 428 428 return false; 429 429 } … … 438 438 439 439 $head4 = substr($headerstring, 0, 4); 440 440 $head4_key = getid3_lib::PrintHexBytes($head4, true, false, false); 441 441 static $MPEGaudioHeaderDecodeCache = array(); 442 if (isset($MPEGaudioHeaderDecodeCache[$head4 ])) {443 $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4 ];442 if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) { 443 $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key]; 444 444 } else { 445 445 $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4); 446 $MPEGaudioHeaderDecodeCache[$head4 ] = $MPEGheaderRawArray;446 $MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray; 447 447 } 448 448 449 449 static $MPEGaudioHeaderValidCache = array(); 450 if (!isset($MPEGaudioHeaderValidCache[$head4 ])) { // Not in cache451 //$MPEGaudioHeaderValidCache[$head4 ] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1)452 $MPEGaudioHeaderValidCache[$head4 ] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false);450 if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache 451 //$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1) 452 $MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false); 453 453 } 454 454 … … 460 460 461 461 462 if ($MPEGaudioHeaderValidCache[$head4 ]) {462 if ($MPEGaudioHeaderValidCache[$head4_key]) { 463 463 $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; 464 464 } else { 465 $ info['error'][] = 'Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset;465 $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); 466 466 return false; 467 467 } … … 491 491 if ($thisfile_mpeg_audio['raw']['bitrate'] == 15) { 492 492 // http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0 493 $ info['warning'][] = 'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';493 $this->warning('Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1'); 494 494 $thisfile_mpeg_audio['raw']['bitrate'] = 0; 495 495 } … … 513 513 // these are ok 514 514 } else { 515 $ info['error'][] = $thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';515 $this->error($thisfile_mpeg_audio['bitrate'].'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.'); 516 516 return false; 517 517 } … … 524 524 // these are ok 525 525 } else { 526 $ info['error'][] = intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.';526 $this->error(intval(round($thisfile_mpeg_audio['bitrate'] / 1000)).'kbps not allowed in Layer 2, '.$thisfile_mpeg_audio['channelmode'].'.'); 527 527 return false; 528 528 } … … 546 546 $nextframetestoffset = $offset + $thisfile_mpeg_audio['framelength']; 547 547 } else { 548 $ info['error'][] = 'Frame at offset('.$offset.') is has an invalid frame length.';548 $this->error('Frame at offset('.$offset.') is has an invalid frame length.'); 549 549 return false; 550 550 } … … 649 649 650 650 //if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) { 651 if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) { 652 653 $framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']; 651 //if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) { 652 if (!empty($thisfile_mpeg_audio['VBR_frames'])) { 653 $used_filesize = 0; 654 if (!empty($thisfile_mpeg_audio['VBR_bytes'])) { 655 $used_filesize = $thisfile_mpeg_audio['VBR_bytes']; 656 } elseif (!empty($info['filesize'])) { 657 $used_filesize = $info['filesize']; 658 $used_filesize -= intval(@$info['id3v2']['headerlength']); 659 $used_filesize -= (isset($info['id3v1']) ? 128 : 0); 660 $used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0); 661 $this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes'); 662 } 663 664 $framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames']; 654 665 655 666 if ($thisfile_mpeg_audio['layer'] == '1') { … … 838 849 $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); 839 850 if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { 840 $ info['warning'][] = 'Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org';851 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); 841 852 } 842 853 if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { … … 882 893 } 883 894 if ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') { 884 $ info['warning'][] = 'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';895 $this->warning('VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.'); 885 896 } 886 897 } … … 909 920 // if ($PossibleNullByte === "\x00") { 910 921 $info['avdataend']--; 911 // $ info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';922 // $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'); 912 923 // } else { 913 // $ 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)';924 // $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)'); 914 925 // } 915 926 } else { 916 $ 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)';927 $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)'); 917 928 } 918 929 } … … 932 943 } 933 944 } else { 934 $ info['error'][] = 'Error calculating frame length of free-format MP3 without Xing/LAME header';945 $this->error('Error calculating frame length of free-format MP3 without Xing/LAME header'); 935 946 } 936 947 } … … 949 960 $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); 950 961 if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) { 951 $info['audio']['bitrate'] 962 $info['audio']['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; 952 963 $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion 953 964 } … … 1075 1086 public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) { 1076 1087 $info = &$this->getid3->info; 1077 $firstframetestarray = array('error' =>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);1088 $firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']); 1078 1089 $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false); 1079 1090 … … 1085 1096 } 1086 1097 1087 $nextframetestarray = array('error' =>'', 'warning'=>'', 'avdataend'=>$info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);1098 $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); 1088 1099 if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { 1089 1100 if ($ScanAsCBR) { … … 1099 1110 $nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength']; 1100 1111 } else { 1101 $ info['error'][] = 'Frame at offset ('.$offset.') is has an invalid frame length.';1112 $this->error('Frame at offset ('.$offset.') is has an invalid frame length.'); 1102 1113 return false; 1103 1114 } … … 1111 1122 1112 1123 // next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence 1113 $ info['warning'][] = 'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';1124 $this->warning('Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.'); 1114 1125 1115 1126 return false; … … 1154 1165 } 1155 1166 if (!$framelength) { 1156 $ info['error'][] = 'Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset;1167 $this->error('Cannot find next free-format synch pattern ('.getid3_lib::PrintHexBytes($SyncPattern1).' or '.getid3_lib::PrintHexBytes($SyncPattern2).') after offset '.$offset); 1157 1168 return false; 1158 1169 } else { 1159 $ info['warning'][] = 'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';1170 $this->warning('ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)'); 1160 1171 $info['audio']['codec'] = 'LAME'; 1161 1172 $info['audio']['encoder'] = 'LAME3.88'; … … 1184 1195 $nextoffset++; 1185 1196 } else { 1186 $ info['error'][] = 'Did not find expected free-format sync pattern at offset '.$nextoffset;1197 $this->error('Did not find expected free-format sync pattern at offset '.$nextoffset); 1187 1198 return false; 1188 1199 } … … 1282 1293 if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) { 1283 1294 $pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']); 1284 $ 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.';1295 $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.'); 1285 1296 foreach ($Distribution as $key1 => $value1) { 1286 1297 foreach ($value1 as $key2 => $value2) { … … 1309 1320 $info['mpeg']['audio']['padding_distribution'] = $Distribution['padding']; 1310 1321 if (count($Distribution['version']) > 1) { 1311 $ info['error'][] = 'Corrupt file - more than one MPEG version detected';1322 $this->error('Corrupt file - more than one MPEG version detected'); 1312 1323 } 1313 1324 if (count($Distribution['layer']) > 1) { 1314 $ info['error'][] = 'Corrupt file - more than one MPEG layer detected';1325 $this->error('Corrupt file - more than one MPEG layer detected'); 1315 1326 } 1316 1327 if (count($Distribution['frequency']) > 1) { 1317 $ info['error'][] = 'Corrupt file - more than one MPEG sample rate detected';1328 $this->error('Corrupt file - more than one MPEG sample rate detected'); 1318 1329 } 1319 1330 … … 1327 1338 $info['mpeg']['audio']['frame_count'] = array_sum($Distribution['bitrate']); 1328 1339 if ($info['mpeg']['audio']['frame_count'] == 0) { 1329 $ info['error'][] = 'no MPEG audio frames found';1340 $this->error('no MPEG audio frames found'); 1330 1341 return false; 1331 1342 } … … 1362 1373 $sync_seek_buffer_size = min(128 * 1024, $info['avdataend'] - $avdataoffset); 1363 1374 if ($sync_seek_buffer_size <= 0) { 1364 $ info['error'][] = 'Invalid $sync_seek_buffer_size at offset '.$avdataoffset;1375 $this->error('Invalid $sync_seek_buffer_size at offset '.$avdataoffset); 1365 1376 return false; 1366 1377 } … … 1373 1384 if ($SynchSeekOffset > $sync_seek_buffer_size) { 1374 1385 // if a synch's not found within the first 128k bytes, then give up 1375 $ info['error'][] = 'Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB';1386 $this->error('Could not find valid MPEG audio synch within the first '.round($sync_seek_buffer_size / 1024).'kB'); 1376 1387 if (isset($info['audio']['bitrate'])) { 1377 1388 unset($info['audio']['bitrate']); … … 1387 1398 } elseif (feof($this->getid3->fp)) { 1388 1399 1389 $ info['error'][] = 'Could not find valid MPEG audio synch before end of file';1400 $this->error('Could not find valid MPEG audio synch before end of file'); 1390 1401 if (isset($info['audio']['bitrate'])) { 1391 1402 unset($info['audio']['bitrate']); … … 1402 1413 1403 1414 if (($SynchSeekOffset + 1) >= strlen($header)) { 1404 $ info['error'][] = 'Could not find valid MPEG synch before end of file';1415 $this->error('Could not find valid MPEG synch before end of file'); 1405 1416 return false; 1406 1417 } … … 1445 1456 $info = $dummy; 1446 1457 $info['avdataoffset'] = $GarbageOffsetEnd; 1447 $ 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;1458 $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); 1448 1459 } else { 1449 $ 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.')';1460 $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.')'); 1450 1461 } 1451 1462 } … … 1540 1551 } 1541 1552 if ($pct_data_scanned > 0) { 1542 $ 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.';1553 $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.'); 1543 1554 foreach ($info['mpeg']['audio'] as $key1 => $value1) { 1544 1555 if (!preg_match('#_distribution$#i', $key1)) { … … 1552 1563 1553 1564 if ($SynchErrorsFound > 0) { 1554 $ info['warning'][] = 'Found '.$SynchErrorsFound.' synch errors in histogram analysis';1565 $this->warning('Found '.$SynchErrorsFound.' synch errors in histogram analysis'); 1555 1566 //return false; 1556 1567 } … … 1565 1576 } 1566 1577 if ($framecounter == 0) { 1567 $ info['error'][] = 'Corrupt MP3 file: framecounter == zero';1578 $this->error('Corrupt MP3 file: framecounter == zero'); 1568 1579 return false; 1569 1580 } … … 1600 1611 if (empty($info['mpeg']['audio'])) { 1601 1612 1602 $ info['error'][] = 'could not find valid MPEG synch before end of file';1613 $this->error('could not find valid MPEG synch before end of file'); 1603 1614 if (isset($info['audio']['bitrate'])) { 1604 1615 unset($info['audio']['bitrate']); -
trunk/src/wp-includes/ID3/module.audio.ogg.php
r32979 r41196 27 27 // Warn about illegal tags - only vorbiscomments are allowed 28 28 if (isset($info['id3v2'])) { 29 $ info['warning'][] = 'Illegal ID3v2 tag present.';29 $this->warning('Illegal ID3v2 tag present.'); 30 30 } 31 31 if (isset($info['id3v1'])) { 32 $ info['warning'][] = 'Illegal ID3v1 tag present.';32 $this->warning('Illegal ID3v1 tag present.'); 33 33 } 34 34 if (isset($info['ape'])) { 35 $ info['warning'][] = 'Illegal APE tag present.';35 $this->warning('Illegal APE tag present.'); 36 36 } 37 37 … … 45 45 46 46 if ($this->ftell() >= $this->getid3->fread_buffer_size()) { 47 $ 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?)';47 $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?)'); 48 48 unset($info['fileformat']); 49 49 unset($info['ogg']); … … 180 180 $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; 181 181 } 182 $ 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';182 $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'); 183 183 184 184 … … 241 241 242 242 $info['video']['dataformat'] = 'theora1'; 243 $ info['error'][] = 'Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']';243 $this->error('Ogg Theora (v1) not correctly handled in this version of getID3 ['.$this->getid3->version().']'); 244 244 //break; 245 245 … … 249 249 250 250 } else { 251 $ info['error'][] = 'unexpected';251 $this->error('unexpected'); 252 252 //break; 253 253 } … … 257 257 $this->fseek($oggpageinfo['page_start_offset']); 258 258 259 $ info['error'][] = 'Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']';259 $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']'); 260 260 //return false; 261 261 262 262 } else { 263 263 264 $ info['error'][] = 'Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"';264 $this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"'); 265 265 unset($info['ogg']); 266 266 unset($info['mime_type']); … … 285 285 $flac = new getid3_flac($this->getid3); 286 286 if (!$flac->parseMETAdata()) { 287 $ info['error'][] = 'Failed to parse FLAC headers';287 $this->error('Failed to parse FLAC headers'); 288 288 return false; 289 289 } … … 300 300 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags' 301 301 if(substr($filedata, 0, 8) != 'OpusTags') { 302 $ info['error'][] = 'Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"';302 $this->error('Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"'); 303 303 return false; 304 304 } … … 312 312 if (!getid3_lib::intValueSupported($info['avdataend'])) { 313 313 314 $ info['warning'][] = 'Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)';314 $this->warning('Unable to parse Ogg end chunk file (PHP does not support file operations beyond '.round(PHP_INT_MAX / 1073741824).'GB)'); 315 315 316 316 } else { … … 324 324 $info['ogg']['samples'] = $info['ogg']['pageheader']['eos']['pcm_abs_position']; 325 325 if ($info['ogg']['samples'] == 0) { 326 $ info['error'][] = 'Corrupt Ogg file: eos.number of samples == zero';326 $this->error('Corrupt Ogg file: eos.number of samples == zero'); 327 327 return false; 328 328 } … … 343 343 if (isset($info['audio']['bitrate']) && !isset($info['playtime_seconds'])) { 344 344 if ($info['audio']['bitrate'] == 0) { 345 $ info['error'][] = 'Corrupt Ogg file: bitrate_audio == zero';345 $this->error('Corrupt Ogg file: bitrate_audio == zero'); 346 346 return false; 347 347 } … … 396 396 $filedataoffset += 4; 397 397 if ($info['ogg']['samplerate'] == 0) { 398 $ info['error'][] = 'Corrupt Ogg file: sample rate == zero';398 $this->error('Corrupt Ogg file: sample rate == zero'); 399 399 return false; 400 400 } … … 444 444 445 445 if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) { 446 $ info['error'][] = 'Unknown opus version number (only accepting 1-15)';446 $this->error('Unknown opus version number (only accepting 1-15)'); 447 447 return false; 448 448 } … … 452 452 453 453 if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) { 454 $ info['error'][] = 'Invalid channel count in opus header (must not be zero)';454 $this->error('Invalid channel count in opus header (must not be zero)'); 455 455 return false; 456 456 } … … 563 563 default: 564 564 return false; 565 break; 565 566 } 566 567 … … 581 582 if ($i >= 10000) { 582 583 // https://github.com/owncloud/music/issues/212#issuecomment-43082336 583 $ info['warning'][] = 'Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments';584 $this->warning('Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments'); 584 585 break; 585 586 } … … 619 620 while ((strlen($commentdata) - $commentdataoffset) < $ThisFileInfo_ogg_comments_raw[$i]['size']) { 620 621 if (($ThisFileInfo_ogg_comments_raw[$i]['size'] > $info['avdataend']) || ($ThisFileInfo_ogg_comments_raw[$i]['size'] < 0)) { 621 $ info['warning'][] = 'Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments';622 $this->warning('Invalid Ogg comment size (comment #'.$i.', claims to be '.number_format($ThisFileInfo_ogg_comments_raw[$i]['size']).' bytes) - aborting reading comments'); 622 623 break 2; 623 624 } … … 643 644 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); 644 645 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { 645 $ info['warning'][] = 'undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();646 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 646 647 break; 647 648 } 648 649 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); 649 650 if ($readlength <= 0) { 650 $ info['warning'][] = 'invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell();651 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 651 652 break; 652 653 } … … 662 663 663 664 // no comment? 664 $ info['warning'][] = 'Blank Ogg comment ['.$i.']';665 $this->warning('Blank Ogg comment ['.$i.']'); 665 666 666 667 } elseif (strstr($commentstring, '=')) { … … 712 713 } else { 713 714 714 $ info['warning'][] = '[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring;715 $this->warning('[known problem with CDex >= v1.40, < v1.50b7] Invalid Ogg comment name/value pair ['.$i.']: '.$commentstring); 715 716 716 717 } -
trunk/src/wp-includes/ID3/module.tag.apetag.php
r32979 r41196 24 24 25 25 if (!getid3_lib::intValueSupported($info['filesize'])) { 26 $ info['warning'][] = 'Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB';26 $this->warning('Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'); 27 27 return false; 28 28 } … … 73 73 $APEfooterData = $this->fread(32); 74 74 if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) { 75 $ info['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end'];75 $this->error('Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']); 76 76 return false; 77 77 } … … 89 89 90 90 if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) { 91 $ info['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data';91 $this->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data'); 92 92 unset($info['id3v1']); 93 93 foreach ($info['warning'] as $key => $value) { … … 105 105 $offset += $apetagheadersize; 106 106 } else { 107 $ info['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start'];107 $this->error('Error parsing APE header at offset '.$thisfile_ape['tag_offset_start']); 108 108 return false; 109 109 } … … 120 120 $offset += 4; 121 121 if (strstr(substr($APEtagData, $offset), "\x00") === false) { 122 $ 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);122 $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)); 123 123 return false; 124 124 } … … 155 155 $thisfile_replaygain['track']['originator'] = 'unspecified'; 156 156 } else { 157 $ info['warning'][] = 'MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';157 $this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 158 158 } 159 159 break; … … 164 164 $thisfile_replaygain['track']['originator'] = 'unspecified'; 165 165 if ($thisfile_replaygain['track']['peak'] <= 0) { 166 $ info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';167 } 168 } else { 169 $ info['warning'][] = 'MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';166 $this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")'); 167 } 168 } else { 169 $this->warning('MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 170 170 } 171 171 break; … … 176 176 $thisfile_replaygain['album']['originator'] = 'unspecified'; 177 177 } else { 178 $ info['warning'][] = 'MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';178 $this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 179 179 } 180 180 break; … … 185 185 $thisfile_replaygain['album']['originator'] = 'unspecified'; 186 186 if ($thisfile_replaygain['album']['peak'] <= 0) { 187 $ info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';188 } 189 } else { 190 $ info['warning'][] = 'MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';187 $this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")'); 188 } 189 } else { 190 $this->warning('MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 191 191 } 192 192 break; … … 199 199 $thisfile_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false); 200 200 } else { 201 $ info['warning'][] = 'MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';201 $this->warning('MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 202 202 } 203 203 break; … … 209 209 $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max); 210 210 } else { 211 $ info['warning'][] = 'MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';211 $this->warning('MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"'); 212 212 } 213 213 break; … … 219 219 $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max); 220 22