Ticket #41496: 41496.diff
File 41496.diff, 269.2 KB (added by , 7 years ago) |
---|
-
src/wp-includes/ID3/getid3.lib.php
diff --git a/src/wp-includes/ID3/getid3.lib.php b/src/wp-includes/ID3/getid3.lib.php index 76e2854..1931bb3 100644
a b class getid3_lib 293 293 return self::BigEndian2Int(strrev($byteword), false, $signed); 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) { 298 301 $binvalue = ''; … … class getid3_lib 414 417 return $newarray; 415 418 } 416 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); 432 } 433 417 434 418 435 public static function ksort_recursive(&$theArray) { 419 436 ksort($theArray); … … class getid3_lib 946 963 return $string; 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) { 953 982 case 'ISO-8859-1': … … class getid3_lib 963 992 } 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)) { 969 998 $ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8'; … … class getid3_lib 985 1014 $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)]; 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 991 1020 public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') { … … class getid3_lib 1006 1035 $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string 1007 1036 $HTMLstring = ''; 1008 1037 1009 switch ( $charset) {1038 switch (strtolower($charset)) { 1010 1039 case '1251': 1011 1040 case '1252': 1012 1041 case '866': 1013 1042 case '932': 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++) { 1043 1072 $char_ord_val = ord($string{$i}); … … class getid3_lib 1065 1094 } 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)); 1071 1100 if (($charval >= 32) && ($charval <= 127)) { … … class getid3_lib 1076 1105 } 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)); 1082 1111 if (($charval >= 32) && ($charval <= 127)) { … … class getid3_lib 1153 1182 public static function GetDataImageSize($imgData, &$imageinfo=array()) { 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; 1163 1200 if ($tempfilename = tempnam($tempdir, 'gI3')) { … … class getid3_lib 1165 1202 fwrite($tmp, $imgData); 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]; 1170 1210 } … … class getid3_lib 1237 1277 } 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 } … … class getid3_lib 1248 1292 } 1249 1293 } 1250 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]); 1304 } 1305 } 1306 1251 1307 // Copy to ['comments_html'] 1252 1308 if (!empty($ThisFileInfo['comments'])) { 1253 1309 foreach ($ThisFileInfo['comments'] as $field => $values) { -
src/wp-includes/ID3/getid3.php
diff --git a/src/wp-includes/ID3/getid3.php b/src/wp-includes/ID3/getid3.php index 714fb02..7732c19 100644
a b if (!defined('GETID3_INCLUDEPATH')) { 22 22 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { 23 23 define('IMG_JPG', IMAGETYPE_JPEG); 24 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)); 27 } 25 28 26 29 // attempt to define temp dir as something flexible but reliable 27 30 $temp_dir = ini_get('upload_tmp_dir'); … … class getID3 109 112 protected $startup_error = ''; 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 115 118 const ATTACHMENTS_NONE = false; … … class getID3 120 123 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; 129 132 } 130 133 if ($this->memory_limit <= 0) { 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 138 141 // Check safe_mode off … … class getID3 140 143 $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.'); 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 147 153 // Check for magic_quotes_runtime 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 } 153 159 154 160 // Check for magic_quotes_gpc 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 } 160 166 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 166 172 if ($this->option_max_2gb_check === null) { … … class getID3 179 185 $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path 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)); 185 191 $path_so_far = array(); … … class getID3 199 205 } 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 } 205 211 $path_so_far[] = $value; … … class getID3 209 215 define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR); 210 216 } 211 217 218 if (!empty($this->startup_error)) { 219 echo $this->startup_error; 220 throw new getid3_exception($this->startup_error); 221 } 222 212 223 return true; 213 224 } 214 225 … … class getID3 236 247 } 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)) { 242 253 throw new getid3_exception($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 248 261 // init result array and set parameters … … class getID3 252 265 $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false); 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 263 276 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 … … class getID3 280 293 throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')'); 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 286 299 $filename = str_replace('\\', '/', $filename); … … class getID3 288 301 $this->info['filename'] = getid3_lib::mb_basename($filename); 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 293 317 if ($this->option_max_2gb_check) { … … class getID3 314 338 } 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 331 343 } catch (Exception $e) { … … class getID3 335 347 } 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 } 343 355 … … class getID3 382 394 $formattest = fread($this->fp, 32774); 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 388 400 if (!$determined_format) { … … class getID3 419 431 return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.'); 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); 432 444 } … … class getID3 561 573 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', 567 579 'mime_type' => 'audio/ac3', … … class getID3 579 591 /* 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', 585 597 'mime_type' => 'audio/audible', … … class getID3 587 599 */ 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', 593 605 'mime_type' => 'application/octet-stream', … … class getID3 597 609 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', 603 615 'mime_type' => 'audio/basic', … … class getID3 605 617 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', 611 623 'mime_type' => 'audio/amr', … … class getID3 621 633 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', 627 639 'mime_type' => 'audio/xmms-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', 635 655 'mime_type' => 'application/octet-stream', … … class getID3 637 657 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', 643 663 'mime_type' => 'audio/dts', … … class getID3 722 742 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', 728 748 'mime_type' => 'audio/x-musepack', … … class getID3 730 750 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', 736 756 'mime_type' => 'audio/mpeg', … … class getID3 738 758 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', 744 764 'mime_type' => 'application/octet-stream', … … class getID3 764 784 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', 770 790 'mime_type' => 'application/octet-stream', … … class getID3 799 819 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', 805 825 'mime_type' => 'video/x-ms-asf', … … class getID3 816 836 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', 822 842 'mime_type' => 'video/x-flv', … … class getID3 824 844 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', 830 850 'mime_type' => 'video/x-matroska', // may also be audio/x-matroska … … class getID3 832 852 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', 838 858 'mime_type' => 'video/mpeg', … … class getID3 869 889 'pattern' => '^(RIFF|SDSS|FORM)', 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 ), 875 895 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', 881 901 'mime_type' => 'audio/x-realaudio', … … class getID3 891 911 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', 897 917 'mime_type' => 'video/MP2T', … … class getID3 922 942 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', 928 948 'mime_type' => 'image/jpeg', … … class getID3 932 952 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', 938 958 'mime_type' => 'image/x-photo-cd', … … class getID3 943 963 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', 949 969 'mime_type' => 'image/png', … … class getID3 954 974 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', 960 980 'mime_type' => 'image/svg+xml', … … class getID3 965 985 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', 971 991 'mime_type' => 'image/tiff', … … class getID3 976 996 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', 982 1002 'mime_type' => 'image/efax', … … class getID3 1000 1020 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', 1006 1026 'mime_type' => 'application/octet-stream', … … class getID3 1010 1030 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', 1016 1036 'mime_type' => 'application/octet-stream', … … class getID3 1020 1040 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', 1026 1046 'mime_type' => 'application/x-tar', … … class getID3 1030 1050 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', 1036 1056 'mime_type' => 'application/x-gzip', … … class getID3 1040 1060 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', 1046 1066 'mime_type' => 'application/zip', … … class getID3 1053 1073 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', 1059 1079 'mime_type' => 'application/octet-stream', … … class getID3 1063 1083 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', 1069 1089 'mime_type' => 'application/pdf', … … class getID3 1073 1093 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', 1079 1099 'mime_type' => 'application/octet-stream', … … class getID3 1114 1134 } 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 1120 1140 $GetFileFormatArray = $this->GetFileFormatArray(); 1121 1141 $info = $GetFileFormatArray['mp3']; 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 1127 1147 // and verify there's at least one instance of "TRACK xx AUDIO" in the file … … class getID3 1222 1242 continue; 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 1234 1255 } … … class getID3 1352 1373 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 { 1359 1380 … … class getID3 1582 1603 return true; 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 1587 1619 … … abstract class getid3_handler { 1661 1693 if (!getid3_lib::intValueSupported($pos)) { 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 1667 1715 protected function fseek($bytes, $whence=SEEK_SET) { … … abstract class getid3_handler { 1741 1789 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 } 1747 1795 $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : ''); -
src/wp-includes/ID3/module.audio-video.asf.php
diff --git a/src/wp-includes/ID3/module.audio-video.asf.php b/src/wp-includes/ID3/module.audio-video.asf.php index ee61d7d..23d3a0e 100644
a b class getid3_asf extends getid3_handler { 266 266 $offset += 16; 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; 272 272 } 273 273 $thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); 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; 279 279 } … … class getid3_asf extends getid3_handler { 316 316 $offset += 16; 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; 322 322 } … … class getid3_asf extends getid3_handler { 349 349 if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec 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 355 355 list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description'])); … … class getid3_asf extends getid3_handler { 412 412 break; 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 } 418 418 … … class getid3_asf extends getid3_handler { 458 458 $offset += 16; 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; 464 464 } … … class getid3_asf extends getid3_handler { 517 517 $offset += 16; 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 } 523 523 $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); … … class getid3_asf extends getid3_handler { 525 525 $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); 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 } 531 531 $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); … … class getid3_asf extends getid3_handler { 576 576 $thisfile_asf_bitratemutualexclusionobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']); 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; 582 582 } … … class getid3_asf extends getid3_handler { 637 637 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; 643 643 } … … class getid3_asf extends getid3_handler { 761 761 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; 767 767 } … … class getid3_asf extends getid3_handler { 962 962 default: 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); 970 970 break; … … class getid3_asf extends getid3_handler { 1183 1183 $thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2)); 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; 1189 1189 } … … class getid3_asf extends getid3_handler { 1319 1319 default: 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); 1327 1327 break; … … class getid3_asf extends getid3_handler { 1405 1405 break; 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 1411 1411 } … … class getid3_asf extends getid3_handler { 1917 1917 default: 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; 1925 1925 } -
src/wp-includes/ID3/module.audio-video.flv.php
diff --git a/src/wp-includes/ID3/module.audio-video.flv.php b/src/wp-includes/ID3/module.audio-video.flv.php index c5fbd4b..661c77c 100644
a b class getid3_flv extends getid3_handler { 93 93 $TypeFlags = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1)); 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; 99 99 } … … class AMFReader { 541 541 // Long string 542 542 default: 543 543 $value = '(unknown or unsupported data type)'; 544 break;544 break; 545 545 } 546 546 547 547 return $value; -
src/wp-includes/ID3/module.audio-video.matroska.php
diff --git a/src/wp-includes/ID3/module.audio-video.matroska.php b/src/wp-includes/ID3/module.audio-video.matroska.php index f2cc5ac..825a22e 100644
a b class getid3_matroska extends getid3_handler 234 234 try { 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 240 240 // calculate playtime … … class getid3_matroska extends getid3_handler 330 330 break; 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']])) { 340 342 $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set'); … … class getid3_matroska extends getid3_handler 352 354 } 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__); 358 360 if ($track_info['dataformat'] == 'flac') { … … class getid3_matroska extends getid3_handler 457 459 458 460 default: 459 461 $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"'); 462 break; 460 463 } 461 464 462 465 $info['audio']['streams'][] = $track_info; … … class getid3_matroska extends getid3_handler 524 527 525 528 default: 526 529 $this->unhandledElement('header', __LINE__, $element_data); 530 break; 527 531 } 528 532 529 533 unset($element_data['offset'], $element_data['end']); … … class getid3_matroska extends getid3_handler 562 566 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 } 570 578 break; 571 579 572 580 default: 573 581 $this->unhandledElement('seekhead', __LINE__, $seek_entry); 582 break; 574 583 } 575 584 } 576 585 break; … … class getid3_matroska extends getid3_handler 653 662 654 663 default: 655 664 $this->unhandledElement('track.video', __LINE__, $sub_subelement); 665 break; 656 666 } 657 667 } 658 668 break; … … class getid3_matroska extends getid3_handler 678 688 679 689 default: 680 690 $this->unhandledElement('track.audio', __LINE__, $sub_subelement); 691 break; 681 692 } 682 693 } 683 694 break; … … class getid3_matroska extends getid3_handler 713 724 714 725 default: 715 726 $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); 727 break; 716 728 } 717 729 } 718 730 break; … … class getid3_matroska extends getid3_handler 736 748 737 749 default: 738 750 $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement); 751 break; 739 752 } 740 753 } 741 754 break; 742 755 743 756 default: 744 757 $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement); 758 break; 745 759 } 746 760 } 747 761 break; 748 762 749 763 default: 750 764 $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement); 765 break; 751 766 } 752 767 } 753 768 break; 754 769 755 770 default: 756 771 $this->unhandledElement('track', __LINE__, $subelement); 772 break; 757 773 } 758 774 } 759 775 … … class getid3_matroska extends getid3_handler 762 778 763 779 default: 764 780 $this->unhandledElement('tracks', __LINE__, $track_entry); 781 break; 765 782 } 766 783 } 767 784 break; … … class getid3_matroska extends getid3_handler 825 842 826 843 default: 827 844 $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement); 845 break; 828 846 } 829 847 } 830 848 $info_entry[$subelement['id_name']] = $chaptertranslate_entry; … … class getid3_matroska extends getid3_handler 832 850 833 851 default: 834 852 $this->unhandledElement('info', __LINE__, $subelement); 853 break; 835 854 } 836 855 } 837 856 $info['matroska']['info'][] = $info_entry; … … class getid3_matroska extends getid3_handler 868 887 869 888 default: 870 889 $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement); 890 break; 871 891 } 872 892 } 873 893 $cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry; … … class getid3_matroska extends getid3_handler 879 899 880 900 default: 881 901 $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement); 902 break; 882 903 } 883 904 } 884 905 $cues_entry[] = $cuepoint_entry; … … class getid3_matroska extends getid3_handler 886 907 887 908 default: 888 909 $this->unhandledElement('cues', __LINE__, $subelement); 910 break; 889 911 } 890 912 } 891 913 $info['matroska']['cues'] = $cues_entry; … … class getid3_matroska extends getid3_handler 927 949 928 950 default: 929 951 $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement); 952 break; 930 953 } 931 954 } 932 955 $tag_entry[$sub_subelement['id_name']] = $targets_entry; … … class getid3_matroska extends getid3_handler 938 961 939 962 default: 940 963 $this->unhandledElement('tags.tag', __LINE__, $sub_subelement); 964 break; 941 965 } 942 966 } 943 967 $tags_entry[] = $tag_entry; … … class getid3_matroska extends getid3_handler 945 969 946 970 default: 947 971 $this->unhandledElement('tags', __LINE__, $subelement); 972 break; 948 973 } 949 974 } 950 975 $info['matroska']['tags'] = $tags_entry; … … class getid3_matroska extends getid3_handler 985 1010 986 1011 default: 987 1012 $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement); 1013 break; 988 1014 } 989 1015 } 990 1016 $info['matroska']['attachments'][] = $attachedfile_entry; … … class getid3_matroska extends getid3_handler 992 1018 993 1019 default: 994 1020 $this->unhandledElement('attachments', __LINE__, $subelement); 1021 break; 995 1022 } 996 1023 } 997 1024 break; … … class getid3_matroska extends getid3_handler 1051 1078 1052 1079 default: 1053 1080 $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement); 1081 break; 1054 1082 } 1055 1083 } 1056 1084 $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry; … … class getid3_matroska extends getid3_handler 1070 1098 1071 1099 default: 1072 1100 $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement); 1101 break; 1073 1102 } 1074 1103 } 1075 1104 $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry; … … class getid3_matroska extends getid3_handler 1077 1106 1078 1107 default: 1079 1108 $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement); 1109 break; 1080 1110 } 1081 1111 } 1082 1112 $editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry; … … class getid3_matroska extends getid3_handler 1084 1114 1085 1115 default: 1086 1116 $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement); 1117 break; 1087 1118 } 1088 1119 } 1089 1120 $info['matroska']['chapters'][] = $editionentry_entry; … … class getid3_matroska extends getid3_handler 1091 1122 1092 1123 default: 1093 1124 $this->unhandledElement('chapters', __LINE__, $subelement); 1125 break; 1094 1126 } 1095 1127 } 1096 1128 break; … … class getid3_matroska extends getid3_handler 1119 1151 1120 1152 default: 1121 1153 $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement); 1154 break; 1122 1155 } 1123 1156 } 1124 1157 $cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks; … … class getid3_matroska extends getid3_handler 1149 1182 1150 1183 default: 1151 1184 $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement); 1185 break; 1152 1186 } 1153 1187 } 1154 1188 $cluster_entry[$subelement['id_name']][] = $cluster_block_group; … … class getid3_matroska extends getid3_handler 1160 1194 1161 1195 default: 1162 1196 $this->unhandledElement('cluster', __LINE__, $subelement); 1197 break; 1163 1198 } 1164 1199 $this->current_offset = $subelement['end']; 1165 1200 } … … class getid3_matroska extends getid3_handler 1181 1216 1182 1217 default: 1183 1218 $this->unhandledElement('segment', __LINE__, $element_data); 1219 break; 1184 1220 } 1185 1221 } 1186 1222 break; 1187 1223 1188 1224 default: 1189 1225 $this->unhandledElement('root', __LINE__, $top_element); 1226 break; 1190 1227 } 1191 1228 } 1192 1229 } … … class getid3_matroska extends getid3_handler 1339 1376 1340 1377 default: 1341 1378 $this->unhandledElement('tag.simpletag', __LINE__, $element); 1379 break; 1342 1380 } 1343 1381 } 1344 1382 … … class getid3_matroska extends getid3_handler 1490 1528 $CodecIDlist['A_AAC'] = 'aac'; 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'; 1495 1534 $CodecIDlist['A_MPEG/L1'] = 'mp1'; -
src/wp-includes/ID3/module.audio-video.quicktime.php
diff --git a/src/wp-includes/ID3/module.audio-video.quicktime.php b/src/wp-includes/ID3/module.audio-video.quicktime.php index 482c091..6f29ca4 100644
a b class getid3_quicktime extends getid3_handler 35 35 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 } 44 44 $this->fseek($offset); … … class getid3_quicktime extends getid3_handler 57 57 $info['quicktime'][$atomname]['offset'] = $offset; 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 } 63 63 … … class getid3_quicktime extends getid3_handler 81 81 unset($info['avdataend_tmp']); 82 82 } 83 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 } 157 } 158 84 159 if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { 85 160 $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 86 161 } … … class getid3_quicktime extends getid3_handler 98 173 } 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 107 186 if (!$this->ReturnAtomData) { … … class getid3_quicktime extends getid3_handler 120 199 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; 125 205 … … class getid3_quicktime extends getid3_handler 222 302 break; 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 229 354 case 'cprt': // CoPyRighT 230 355 case 'desc': // DESCription 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 302 389 $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); … … class getid3_quicktime extends getid3_handler 318 405 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); 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); 324 411 break; … … class getid3_quicktime extends getid3_handler 328 415 $atom_structure['data'] = $boxsmalldata; 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; 334 421 } … … class getid3_quicktime extends getid3_handler 340 427 $boxtype = substr($atom_data, $atomoffset + 4, 4); 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); 346 433 break; … … class getid3_quicktime extends getid3_handler 361 448 case 21: // tmpo/cpil flag 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; 372 462 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)); 377 468 $atom_structure['data'] = empty($num) ? '' : $num; … … class getid3_quicktime extends getid3_handler 379 470 break; 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); 384 476 break; 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]); 389 482 break; 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]); 394 488 break; 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]); 399 494 break; … … class getid3_quicktime extends getid3_handler 403 498 $atom_structure['data'] = substr($boxdata, 8); 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 } 409 527 break; … … class getid3_quicktime extends getid3_handler 414 532 $atom_structure['data'] = substr($boxdata, 8); 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'])) { 422 540 $atom_structure['image_mime'] = 'image/gif'; … … class getid3_quicktime extends getid3_handler 428 546 break; 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 434 552 } … … class getid3_quicktime extends getid3_handler 476 594 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { 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; 482 600 … … class getid3_quicktime extends getid3_handler 595 713 if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { 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; 601 719 … … class getid3_quicktime extends getid3_handler 604 722 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 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++) { 609 741 $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 801 933 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++) { 807 939 $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 928 1060 for ($i = 0; $i < $atom_structure['number_entries']; $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)); 934 1066 $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 940 1072 $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001); … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1001 1133 $atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2)); 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']); 1010 1142 $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1019 1151 case 'pnot': // Preview atom 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 1025 1157 $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']); … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1029 1161 case 'crgn': // Clipping ReGioN atom 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 1035 1167 … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1115 1247 $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4)); 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']; 1126 1258 break; … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1240 1372 } 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 } 1382 @$info['quicktime']['comments']['chapters'][] = $chapter_string; 1250 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 1253 1391 if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1265 1403 $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); 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 } 1271 1409 if (!empty($getid3_temp->info['mpeg'])) { … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1368 1506 $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude); 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; 1374 1512 … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1397 1535 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); 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 } 1416 1567 break; 1417 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; 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; 1422 1717 } … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1440 1735 // Furthermore, for historical reasons the list of atoms is optionally 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 } 1445 1744 … … if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 1753 2052 static $QuicktimeIODSaudioProfileNameLookup = array(); 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 } 1808 2107 return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private'); … … echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 2111 2410 public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') { 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'; 2118 2427 $handyatomtranslatorarray["\xA9".'ed2'] = 'edit2'; … … echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 2123 2432 $handyatomtranslatorarray["\xA9".'ed7'] = 'edit7'; 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.txt2135 $handyatomtranslatorarray["\xA9".'nam'] = 'title'; // iTunes 4.02136 $handyatomtranslatorarray["\xA9".'cmt'] = 'comment'; // iTunes 4.02137 $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 2451 $handyatomtranslatorarray["\xA9".'swr'] = 'software'; 2143 $handyatomtranslatorarray["\xA9".'aut'] = 'author'; 2144 $handyatomtranslatorarray["\xA9".'ART'] = 'artist'; 2452 $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool'; // iTunes 4.0 2145 2453 $handyatomtranslatorarray["\xA9".'trk'] = 'track'; 2146 $handyatomtranslatorarray["\xA9".'alb'] = 'album'; // iTunes 4.02147 $handyatomtranslatorarray["\xA9".'com'] = 'comment';2148 $handyatomtranslatorarray["\xA9".'gen'] = 'genre'; // iTunes 4.02149 $handyatomtranslatorarray["\xA9".'ope'] = 'composer';2150 2454 $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 2455 $handyatomtranslatorarray["\xA9".'wrn'] = 'warning'; 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: 2186 2491 /* … … echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 2225 2530 $data = array('data'=>$data, 'image_mime'=>$image_mime); 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 } 2232 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 } 2577 2233 2578 public function NoNullString($nullterminatedstring) { 2234 2579 // remove the single null terminator on null terminated strings 2235 2580 if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") { … … echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 2243 2588 return substr($pascalstring, 1); 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 } -
src/wp-includes/ID3/module.audio-video.riff.php
diff --git a/src/wp-includes/ID3/module.audio-video.riff.php b/src/wp-includes/ID3/module.audio-video.riff.php index e8ba944..53f9350 100644
a b class getid3_riff extends getid3_handler { 190 190 $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']); 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 } 196 196 $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw']; … … class getid3_riff extends getid3_handler { 199 199 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']; 205 205 … … class getid3_riff extends getid3_handler { 302 302 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; 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']; 311 311 $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_bext_0['title']; … … class getid3_riff extends getid3_handler { 385 385 $SNDM_thisTagOffset += $SNDM_thisTagDataSize; 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 } 394 394 $SNDM_startoffset += $SNDM_thisTagSize; … … class getid3_riff extends getid3_handler { 397 397 if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) { 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 } 403 403 … … class getid3_riff extends getid3_handler { 428 428 } 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); 434 435 $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60)); 435 436 $f = ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate']; 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); 440 442 } … … class getid3_riff extends getid3_handler { 570 572 // byte, in which case - skip warning 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 } 576 578 break; … … class getid3_riff extends getid3_handler { 579 581 if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) { 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 } 589 591 break; … … class getid3_riff extends getid3_handler { 592 594 if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) { 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 } 598 600 if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) { … … class getid3_riff extends getid3_handler { 619 621 $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size']; 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 } 625 627 } … … class getid3_riff extends getid3_handler { 660 662 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 } 666 668 … … class getid3_riff extends getid3_handler { 858 860 break; 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 864 866 } … … class getid3_riff extends getid3_handler { 963 965 // structures rounded to 2-byte boundary, but dumb encoders 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']; 969 971 } … … class getid3_riff extends getid3_handler { 1020 1022 } 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 } 1026 1028 $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate']; … … class getid3_riff extends getid3_handler { 1080 1082 $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; 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 } 1086 1088 … … class getid3_riff extends getid3_handler { 1112 1114 break; 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 } 1118 1120 } … … class getid3_riff extends getid3_handler { 1130 1132 break; 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 } 1136 1138 … … class getid3_riff extends getid3_handler { 1170 1172 } 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 } 1178 1230 … … class getid3_riff extends getid3_handler { 1185 1237 foreach ($ID3v2_keys_bad as $ID3v2_key_bad) { 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 } 1191 1243 … … class getid3_riff extends getid3_handler { 1509 1561 $info['ac3'] = $getid3_temp->info['ac3']; 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 } 1515 1567 } … … class getid3_riff extends getid3_handler { 2583 2635 return getid3_lib::BigEndian2Int($byteword, false, $signed); 2584 2636 } 2585 2637 2586 } 2587 No newline at end of file 2638 } -
src/wp-includes/ID3/module.audio.ac3.php
diff --git a/src/wp-includes/ID3/module.audio.ac3.php b/src/wp-includes/ID3/module.audio.ac3.php index 2dc52f4..27c328d 100644
a b class getid3_ac3 extends getid3_handler 20 20 private $AC3header = array(); 21 21 private $BSIoffset = 0; 22 22 23 const syncword = "\x0B\x77";23 const syncword = 0x0B77; 24 24 25 25 public function Analyze() { 26 26 $info = &$this->getid3->info; … … class getid3_ac3 extends getid3_handler 55 55 // } /* end of syncinfo */ 56 56 57 57 $this->fseek($info['avdataoffset']); 58 $this->AC3header['syncinfo'] = $this->fread(5); 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); 59 63 60 if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) { 61 $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword; 62 $offset = 2; 63 } else { 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 return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"'); 67 68 } 68 $offset = 0;69 $this->fseek(-2, SEEK_CUR);70 69 } 71 70 72 71 $info['audio']['dataformat'] = 'ac3'; 73 72 $info['audio']['bitrate_mode'] = 'cbr'; 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); 75 if ($thisfile_ac3_raw_bsi['bsid'] <= 8) { 80 76 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 } 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 } 85 83 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'];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); 89 87 90 $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15)); 91 $ac3_bsi_offset = 0; 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 } 92 93 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'); 99 unset($info['ac3']); 100 return false; 101 } 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 } 102 99 103 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3); 104 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3); 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 105 106 $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); 107 $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']); 108 foreach($ac3_coding_mode as $key => $value) { 109 $thisfile_ac3[$key] = $value; 110 } 111 switch ($thisfile_ac3_raw_bsi['acmod']) { 112 case 0: 113 case 1: 114 $info['audio']['channelmode'] = 'mono'; 115 break; 116 case 3: 117 case 4: 118 $info['audio']['channelmode'] = 'stereo'; 119 break; 120 default: 121 $info['audio']['channelmode'] = 'surround'; 122 break; 123 } 124 $info['audio']['channels'] = $thisfile_ac3['num_channels']; 106 $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1); 125 107 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 } 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 131 111 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 }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 } 137 117 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 } 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 } 143 122 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']++; 148 $info['audio']['channels'] .= '.1'; 149 } 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 150 127 151 $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']); 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 } 152 131 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);156 $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';157 132 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 } 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. 163 135 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 } 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 } 168 141 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);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 } 173 146 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 } 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 } 177 155 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. 156 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1); // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit 182 157 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'; 158 $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1); // 5.4.2.25 origbs: Original Bit Stream, 1 Bit 187 159 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']); 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) 192 167 } 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); 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 197 174 } 198 175 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); 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. 203 179 204 $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB'; 205 $thisfile_ac3['room_type2'] = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']); 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; 206 184 } 207 185 208 }209 186 210 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);187 } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3 211 188 212 $thisfile_ac3_raw_bsi['original'] = (bool) $this->readHeaderBSI(1);213 189 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 } 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 &n