Changeset 51901
- Timestamp:
- 10/10/2021 01:15:16 AM (3 years ago)
- Location:
- trunk/src/wp-includes/ID3
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/getid3.lib.php
r51900 r51901 243 243 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic 244 244 * 245 * @link http s://web.archive.org/web/20120325162206/http://www.psc.edu/general/software/packages/ieee/ieee.php245 * @link http://www.psc.edu/general/software/packages/ieee/ieee.html 246 246 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html 247 247 * … … 295 295 if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) { 296 296 // Not a Number 297 $floatvalue = NAN;297 $floatvalue = false; 298 298 } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) { 299 299 if ($signbit == '1') { 300 $floatvalue = -INF;300 $floatvalue = '-infinity'; 301 301 } else { 302 $floatvalue = INF;302 $floatvalue = '+infinity'; 303 303 } 304 304 } elseif (($exponent == 0) && ($fraction == 0)) { … … 428 428 */ 429 429 public static function Dec2Bin($number) { 430 if (!is_numeric($number)) {431 // https://github.com/JamesHeinrich/getID3/issues/299432 trigger_error('TypeError: Dec2Bin(): Argument #1 ($number) must be numeric, '.gettype($number).' given', E_USER_WARNING);433 return '';434 }435 $bytes = array();436 430 while ($number >= 256) { 437 $bytes[] = ( int) (($number / 256) - (floor($number / 256))) * 256;431 $bytes[] = (($number / 256) - (floor($number / 256))) * 256; 438 432 $number = floor($number / 256); 439 433 } 440 $bytes[] = (int)$number;434 $bytes[] = $number; 441 435 $binstring = ''; 442 for each ($bytes as $i => $byte) {443 $binstring = (($i == count($bytes) - 1) ? decbin($byte ) : str_pad(decbin($byte), 8, '0', STR_PAD_LEFT)).$binstring;436 for ($i = 0; $i < count($bytes); $i++) { 437 $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring; 444 438 } 445 439 return $binstring; … … 672 666 // $foo['path']['to']['my'] = 'file.txt'; 673 667 $ArrayPath = ltrim($ArrayPath, $Separator); 674 $ReturnedArray = array();675 668 if (($pos = strpos($ArrayPath, $Separator)) !== false) { 676 669 $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value); … … 1546 1539 // Copy all entries from ['tags'] into common ['comments'] 1547 1540 if (!empty($ThisFileInfo['tags'])) { 1548 1549 // Some tag types can only support limited character sets and may contain data in non-standard encoding (usually ID3v1) 1550 // and/or poorly-transliterated tag values that are also in tag formats that do support full-range character sets 1551 // To make the output more user-friendly, process the potentially-problematic tag formats last to enhance the chance that 1552 // the first entries in [comments] are the most correct and the "bad" ones (if any) come later. 1553 // https://github.com/JamesHeinrich/getID3/issues/338 1554 $processLastTagTypes = array('id3v1','riff'); 1555 foreach ($processLastTagTypes as $processLastTagType) { 1556 if (isset($ThisFileInfo['tags'][$processLastTagType])) { 1557 // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings 1558 $temp = $ThisFileInfo['tags'][$processLastTagType]; 1559 unset($ThisFileInfo['tags'][$processLastTagType]); 1560 $ThisFileInfo['tags'][$processLastTagType] = $temp; 1561 unset($temp); 1562 } 1541 if (isset($ThisFileInfo['tags']['id3v1'])) { 1542 // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings 1543 $ID3v1 = $ThisFileInfo['tags']['id3v1']; 1544 unset($ThisFileInfo['tags']['id3v1']); 1545 $ThisFileInfo['tags']['id3v1'] = $ID3v1; 1546 unset($ID3v1); 1563 1547 } 1564 1548 foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) { … … 1579 1563 break 2; 1580 1564 } 1581 1582 if (function_exists('mb_convert_encoding')) { 1583 if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { 1584 // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. 1585 // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character 1586 break 2; 1587 } 1565 } 1566 if (function_exists('mb_convert_encoding')) { 1567 if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { 1568 // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. 1569 // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character 1570 break 2; 1588 1571 } 1589 1572 } … … 1591 1574 } elseif (!is_array($value)) { 1592 1575 1593 $newvaluelength = strlen(trim($value)); 1594 $newvaluelengthMB = mb_strlen(trim($value)); 1576 $newvaluelength = strlen(trim($value)); 1595 1577 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { 1596 $oldvaluelength = strlen(trim($existingvalue)); 1597 $oldvaluelengthMB = mb_strlen(trim($existingvalue)); 1598 if (($newvaluelengthMB == $oldvaluelengthMB) && ($existingvalue == getid3_lib::iconv_fallback('UTF-8', 'ASCII', $value))) { 1599 // https://github.com/JamesHeinrich/getID3/issues/338 1600 // check for tags containing extended characters that may have been forced into limited-character storage (e.g. UTF8 values into ASCII) 1601 // which will usually display unrepresentable characters as "?" 1602 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); 1603 break; 1604 } 1578 $oldvaluelength = strlen(trim($existingvalue)); 1605 1579 if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { 1606 1580 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); … … 1628 1602 1629 1603 // attempt to standardize spelling of returned keys 1630 if (!empty($ThisFileInfo['comments'])) { 1631 $StandardizeFieldNames = array( 1632 'tracknumber' => 'track_number', 1633 'track' => 'track_number', 1634 ); 1635 foreach ($StandardizeFieldNames as $badkey => $goodkey) { 1636 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { 1637 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; 1638 unset($ThisFileInfo['comments'][$badkey]); 1639 } 1604 $StandardizeFieldNames = array( 1605 'tracknumber' => 'track_number', 1606 'track' => 'track_number', 1607 ); 1608 foreach ($StandardizeFieldNames as $badkey => $goodkey) { 1609 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { 1610 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; 1611 unset($ThisFileInfo['comments'][$badkey]); 1640 1612 } 1641 1613 } … … 1763 1735 */ 1764 1736 public static function getFileSizeSyscall($path) { 1765 $commandline = null;1766 1737 $filesize = false; 1767 1738 … … 1825 1796 * @return string 1826 1797 */ 1827 public static function mb_basename($path, $suffix = '') {1798 public static function mb_basename($path, $suffix = null) { 1828 1799 $splited = preg_split('#/#', rtrim($path, '/ ')); 1829 1800 return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); -
trunk/src/wp-includes/ID3/getid3.php
r51900 r51901 17 17 if (!defined('GETID3_INCLUDEPATH')) { 18 18 define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); 19 } 20 // Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923) 21 if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { 22 define('IMG_JPG', IMAGETYPE_JPEG); 19 23 } 20 24 if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE … … 54 58 $basedir .= DIRECTORY_SEPARATOR; 55 59 } 56 if ( strpos($temp_dir, $basedir) === 0) {60 if (preg_match('#^'.preg_quote($basedir).'#', $temp_dir)) { 57 61 $found_valid_tempdir = true; 58 62 break; … … 211 215 public $option_fread_buffer_size = 32768; 212 216 213 214 215 // module-specific options 216 217 /** archive.rar 218 * if true use PHP RarArchive extension, if false (non-extension parsing not yet written in getID3) 219 * 220 * @var bool 221 */ 222 public $options_archive_rar_use_php_rar_extension = true; 223 224 /** archive.gzip 225 * Optional file list - disable for speed. 226 * Decode gzipped files, if possible, and parse recursively (.tar.gz for example). 227 * 228 * @var bool 229 */ 230 public $options_archive_gzip_parse_contents = false; 231 232 /** audio.midi 233 * if false only parse most basic information, much faster for some files but may be inaccurate 234 * 235 * @var bool 236 */ 237 public $options_audio_midi_scanwholefile = true; 238 239 /** audio.mp3 240 * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, 241 * unrecommended, but may provide data from otherwise-unusable files. 242 * 243 * @var bool 244 */ 245 public $options_audio_mp3_allow_bruteforce = false; 246 247 /** audio.mp3 248 * number of frames to scan to determine if MPEG-audio sequence is valid 249 * Lower this number to 5-20 for faster scanning 250 * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams 251 * 217 // Public variables 218 219 /** 220 * Filename of file being analysed. 221 * 222 * @var string 223 */ 224 public $filename; 225 226 /** 227 * Filepointer to file being analysed. 228 * 229 * @var resource 230 */ 231 public $fp; 232 233 /** 234 * Result array. 235 * 236 * @var array 237 */ 238 public $info; 239 240 /** 241 * @var string 242 */ 243 public $tempdir = GETID3_TEMP_DIR; 244 245 /** 252 246 * @var int 253 247 */ 254 public $options_audio_mp3_mp3_valid_check_frames = 50; 255 256 /** audio.wavpack 257 * Avoid scanning all frames (break after finding ID_RIFF_HEADER and ID_CONFIG_BLOCK, 258 * significantly faster for very large files but other data may be missed 259 * 260 * @var bool 261 */ 262 public $options_audio_wavpack_quick_parsing = false; 263 264 /** audio-video.flv 265 * Break out of the loop if too many frames have been scanned; only scan this 266 * many if meta frame does not contain useful duration. 267 * 268 * @var int 269 */ 270 public $options_audiovideo_flv_max_frames = 100000; 271 272 /** audio-video.matroska 273 * If true, do not return information about CLUSTER chunks, since there's a lot of them 274 * and they're not usually useful [default: TRUE]. 275 * 276 * @var bool 277 */ 278 public $options_audiovideo_matroska_hide_clusters = true; 279 280 /** audio-video.matroska 281 * True to parse the whole file, not only header [default: FALSE]. 282 * 283 * @var bool 284 */ 285 public $options_audiovideo_matroska_parse_whole_file = false; 286 287 /** audio-video.quicktime 288 * return all parsed data from all atoms if true, otherwise just returned parsed metadata 289 * 290 * @var bool 291 */ 292 public $options_audiovideo_quicktime_ReturnAtomData = false; 293 294 /** audio-video.quicktime 295 * return all parsed data from all atoms if true, otherwise just returned parsed metadata 296 * 297 * @var bool 298 */ 299 public $options_audiovideo_quicktime_ParseAllPossibleAtoms = false; 300 301 /** audio-video.swf 302 * return all parsed tags if true, otherwise do not return tags not parsed by getID3 303 * 304 * @var bool 305 */ 306 public $options_audiovideo_swf_ReturnAllTagData = false; 307 308 /** graphic.bmp 309 * return BMP palette 310 * 311 * @var bool 312 */ 313 public $options_graphic_bmp_ExtractPalette = false; 314 315 /** graphic.bmp 316 * return image data 317 * 318 * @var bool 319 */ 320 public $options_graphic_bmp_ExtractData = false; 321 322 /** graphic.png 323 * If data chunk is larger than this do not read it completely (getID3 only needs the first 324 * few dozen bytes for parsing). 325 * 326 * @var int 327 */ 328 public $options_graphic_png_max_data_bytes = 10000000; 329 330 /** misc.pdf 331 * return full details of PDF Cross-Reference Table (XREF) 332 * 333 * @var bool 334 */ 335 public $options_misc_pdf_returnXREF = false; 336 337 /** misc.torrent 338 * Assume all .torrent files are less than 1MB and just read entire thing into memory for easy processing. 339 * Override this value if you need to process files larger than 1MB 340 * 341 * @var int 342 */ 343 public $options_misc_torrent_max_torrent_filesize = 1048576; 344 345 346 347 // Public variables 348 349 /** 350 * Filename of file being analysed. 351 * 248 public $memory_limit = 0; 249 250 /** 352 251 * @var string 353 252 */ 354 public $filename; 355 356 /** 357 * Filepointer to file being analysed. 358 * 359 * @var resource 360 */ 361 public $fp; 362 363 /** 364 * Result array. 365 * 366 * @var array 367 */ 368 public $info; 253 protected $startup_error = ''; 369 254 370 255 /** 371 256 * @var string 372 257 */ 373 public $tempdir = GETID3_TEMP_DIR;374 375 /**376 * @var int377 */378 public $memory_limit = 0;379 380 /**381 * @var string382 */383 protected $startup_error = '';384 385 /**386 * @var string387 */388 258 protected $startup_warning = ''; 389 259 390 const VERSION = '1.9.2 1-202109171300';260 const VERSION = '1.9.20-202006061653'; 391 261 const FREAD_BUFFER_SIZE = 32768; 392 262 … … 768 638 } 769 639 $class = new $class_name($this); 770 771 // set module-specific options772 foreach (get_object_vars($this) as $getid3_object_vars_key => $getid3_object_vars_value) {773 if (preg_match('#^options_([^_]+)_([^_]+)_(.+)$#i', $getid3_object_vars_key, $matches)) {774 list($dummy, $GOVgroup, $GOVmodule, $GOVsetting) = $matches;775 $GOVgroup = (($GOVgroup == 'audiovideo') ? 'audio-video' : $GOVgroup); // variable names can only contain 0-9a-z_ so standardize here776 if (($GOVgroup == $determined_format['group']) && ($GOVmodule == $determined_format['module'])) {777 $class->$GOVsetting = $getid3_object_vars_value;778 }779 }780 }781 782 640 $class->Analyze(); 783 641 unset($class); … … 1494 1352 'module' => 'msoffice', 1495 1353 'mime_type' => 'application/octet-stream', 1496 'fail_id3' => 'ERROR',1497 'fail_ape' => 'ERROR',1498 ),1499 1500 // TORRENT - .torrent1501 'torrent' => array(1502 'pattern' => '^(d8\\:announce|d7\\:comment)',1503 'group' => 'misc',1504 'module' => 'torrent',1505 'mime_type' => 'application/x-bittorrent',1506 1354 'fail_id3' => 'ERROR', 1507 1355 'fail_ape' => 'ERROR', … … 1642 1490 $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed! 1643 1491 } 1644 if ( isset($value) && $value !== "") {1492 if ($value) { 1645 1493 if (!is_numeric($key)) { 1646 1494 $this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value; … … 2249 2097 break; 2250 2098 } 2251 return 0; // fseek returns 0 on success 2252 } 2253 2254 $pos = $bytes; 2255 if ($whence == SEEK_CUR) { 2256 $pos = $this->ftell() + $bytes; 2257 } elseif ($whence == SEEK_END) { 2258 $pos = $this->getid3->info['filesize'] + $bytes; 2259 } 2260 if (!getid3_lib::intValueSupported($pos)) { 2261 throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); 2262 } 2263 2264 // https://github.com/JamesHeinrich/getID3/issues/327 2265 $result = fseek($this->getid3->fp, $bytes, $whence); 2266 if ($result !== 0) { // fseek returns 0 on success 2267 throw new getid3_exception('cannot fseek('.$pos.'). resource/stream does not appear to support seeking', 10); 2268 } 2269 return $result; 2099 return 0; 2100 } else { 2101 $pos = $bytes; 2102 if ($whence == SEEK_CUR) { 2103 $pos = $this->ftell() + $bytes; 2104 } elseif ($whence == SEEK_END) { 2105 $pos = $this->getid3->info['filesize'] + $bytes; 2106 } 2107 if (!getid3_lib::intValueSupported($pos)) { 2108 throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); 2109 } 2110 } 2111 return fseek($this->getid3->fp, $bytes, $whence); 2270 2112 } 2271 2113 … … 2383 2225 */ 2384 2226 public function saveAttachment($name, $offset, $length, $image_mime=null) { 2385 $fp_dest = null;2386 $dest = null;2387 2227 try { 2388 2228 -
trunk/src/wp-includes/ID3/module.audio-video.asf.php
r51900 r51901 94 94 $thisfile_asf_streambitratepropertiesobject = array(); 95 95 $thisfile_asf_codeclistobject = array(); 96 $StreamPropertiesObjectData = array();97 96 98 97 for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { … … 285 284 $offset += 2; 286 285 if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) { 287 $this->warning('header_extension_object.reserved_2 ('. $thisfile_asf_headerextensionobject['reserved_2'].') does not match expected value of "6"');286 $this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"'); 288 287 //return false; 289 288 break; … … 537 536 $offset += 2; 538 537 if ($thisfile_asf_markerobject['reserved_2'] != 0) { 539 $this->warning('marker_object.reserved_2 ('. $thisfile_asf_markerobject['reserved_2'].') does not match expected value of "0"');538 $this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"'); 540 539 break; 541 540 } … … 1195 1194 $offset += 2; 1196 1195 if ($thisfile_asf_dataobject['reserved'] != 0x0101) { 1197 $this->warning('data_object.reserved ( 0x'.sprintf('%04X',$thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');1196 $this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'); 1198 1197 //return false; 1199 1198 break; -
trunk/src/wp-includes/ID3/module.audio-video.flv.php
r51900 r51901 162 162 163 163 $FLVvideoHeader = $this->fread(11); 164 $PictureSizeEnc = array();165 164 166 165 if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) { -
trunk/src/wp-includes/ID3/module.audio-video.matroska.php
r51900 r51901 225 225 * @var bool 226 226 */ 227 public $hide_clusters = true;227 public static $hide_clusters = true; 228 228 229 229 /** … … 232 232 * @var bool 233 233 */ 234 public $parse_whole_file = false;234 public static $parse_whole_file = false; 235 235 236 236 /* … … 587 587 588 588 while ($this->getEBMLelement($element_data, $top_element['end'])) { 589 if ($element_data['id'] != EBML_ID_CLUSTER || ! $this->hide_clusters) { // collect clusters only if required589 if ($element_data['id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required 590 590 $info['matroska']['segments'][] = $element_data; 591 591 } … … 619 619 break; 620 620 } 621 if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || ! $this->hide_clusters) { // collect clusters only if required621 if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required 622 622 $info['matroska']['seek'][] = $seek_entry; 623 623 } … … 906 906 907 907 case EBML_ID_CUES: // A top-level element to speed seeking access. All entries are local to the segment. Should be mandatory for non "live" streams. 908 if ( $this->hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway908 if (self::$hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway 909 909 $this->current_offset = $element_data['end']; 910 910 break; … … 1247 1247 $this->current_offset = $subelement['end']; 1248 1248 } 1249 if (! $this->hide_clusters) {1249 if (!self::$hide_clusters) { 1250 1250 $info['matroska']['cluster'][] = $cluster_entry; 1251 1251 } 1252 1252 1253 1253 // check to see if all the data we need exists already, if so, break out of the loop 1254 if (! $this->parse_whole_file) {1254 if (!self::$parse_whole_file) { 1255 1255 if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) { 1256 1256 if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) { -
trunk/src/wp-includes/ID3/module.audio-video.quicktime.php
r51900 r51901 25 25 { 26 26 27 /** audio-video.quicktime 28 * return all parsed data from all atoms if true, otherwise just returned parsed metadata 29 * 30 * @var bool 31 */ 32 public $ReturnAtomData = false; 33 34 /** audio-video.quicktime 35 * return all parsed data from all atoms if true, otherwise just returned parsed metadata 36 * 37 * @var bool 38 */ 27 public $ReturnAtomData = true; 39 28 public $ParseAllPossibleAtoms = false; 40 29 … … 182 171 } 183 172 184 if (!isset($info['bitrate']) && !empty($info['playtime_seconds'])) {173 if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { 185 174 $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; 186 175 } … … 572 561 $atom_structure['data'] = substr($boxdata, 8); 573 562 if ($atomname == 'covr') { 574 if (!empty($atom_structure['data'])) { 575 $atom_structure['image_mime'] = 'image/unknown'; // provide default MIME type to ensure array keys exist 576 if (function_exists('getimagesizefromstring') && ($getimagesize = getimagesizefromstring($atom_structure['data'])) && !empty($getimagesize['mime'])) { 577 $atom_structure['image_mime'] = $getimagesize['mime']; 578 } else { 579 // if getimagesizefromstring is not available, or fails for some reason, fall back to simple detection of common image formats 580 $ImageFormatSignatures = array( 581 'image/jpeg' => "\xFF\xD8\xFF", 582 'image/png' => "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 583 'image/gif' => 'GIF', 584 ); 585 foreach ($ImageFormatSignatures as $mime => $image_format_signature) { 586 if (substr($atom_structure['data'], 0, strlen($image_format_signature)) == $image_format_signature) { 587 $atom_structure['image_mime'] = $mime; 588 break; 589 } 590 } 591 } 592 $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover'); 593 } else { 594 $this->warning('Unknown empty "covr" image at offset '.$baseoffset); 563 // not a foolproof check, but better than nothing 564 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { 565 $atom_structure['image_mime'] = 'image/jpeg'; 566 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { 567 $atom_structure['image_mime'] = 'image/png'; 568 } elseif (preg_match('#^GIF#', $atom_structure['data'])) { 569 $atom_structure['image_mime'] = 'image/gif'; 595 570 } 571 $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover'); 596 572 } 597 573 break; … … 753 729 $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; 754 730 755 $ptv_lookup = array( 756 0 => 'normal', 757 1 => 'double', 758 2 => 'half', 759 3 => 'full', 760 4 => 'current' 761 ); 731 $ptv_lookup[0] = 'normal'; 732 $ptv_lookup[1] = 'double'; 733 $ptv_lookup[2] = 'half'; 734 $ptv_lookup[3] = 'full'; 735 $ptv_lookup[4] = 'current'; 762 736 if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { 763 737 $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; … … 935 909 $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); 936 910 937 $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (( (int)$atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');911 $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); 938 912 $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); 939 913 … … 941 915 $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; 942 916 $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); 943 $info['quicktime']['video']['codec'] = (( (int)$atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);917 $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); 944 918 $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; 945 919 $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; … … 1625 1599 1626 1600 case 'NCDT': 1627 // http s://exiftool.org/TagNames/Nikon.html1601 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html 1628 1602 // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 1629 1603 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); … … 1631 1605 case 'NCTH': // Nikon Camera THumbnail image 1632 1606 case 'NCVW': // Nikon Camera preVieW image 1633 case 'NCM1': // Nikon Camera preview iMage 1 1634 case 'NCM2': // Nikon Camera preview iMage 2 1635 // https://exiftool.org/TagNames/Nikon.html 1607 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html 1636 1608 if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) { 1637 $descriptions = array(1638 'NCTH' => 'Nikon Camera Thumbnail Image',1639 'NCVW' => 'Nikon Camera Preview Image',1640 'NCM1' => 'Nikon Camera Preview Image 1',1641 'NCM2' => 'Nikon Camera Preview Image 2',1642 );1643 1609 $atom_structure['data'] = $atom_data; 1644 1610 $atom_structure['image_mime'] = 'image/jpeg'; 1645 $atom_structure['description'] = isset($descriptions[$atomname]) ? $descriptions[$atomname] : 'Nikon preview image'; 1646 $info['quicktime']['comments']['picture'][] = array( 1647 'image_mime' => $atom_structure['image_mime'], 1648 'data' => $atom_data, 1649 'description' => $atom_structure['description'] 1650 ); 1651 } 1652 break; 1653 case 'NCTG': // Nikon - https://exiftool.org/TagNames/Nikon.html#NCTG 1654 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.nikon-nctg.php', __FILE__, true); 1655 $nikonNCTG = new getid3_tag_nikon_nctg($this->getid3); 1656 1657 $atom_structure['data'] = $nikonNCTG->parse($atom_data); 1658 break; 1659 case 'NCHD': // Nikon:MakerNoteVersion - https://exiftool.org/TagNames/Nikon.html 1660 $makerNoteVersion = ''; 1661 for ($i = 0, $iMax = strlen($atom_data); $i < $iMax; ++$i) { 1662 if (ord($atom_data[$i]) >= 0x00 && ord($atom_data[$i]) <= 0x1F) { 1663 $makerNoteVersion .= ' '.ord($atom_data[$i]); 1664 } else { 1665 $makerNoteVersion .= $atom_data[$i]; 1666 } 1667 } 1668 $makerNoteVersion = rtrim($makerNoteVersion, "\x00"); 1669 $atom_structure['data'] = array( 1670 'MakerNoteVersion' => $makerNoteVersion 1671 ); 1672 break; 1673 case 'NCDB': // Nikon - https://exiftool.org/TagNames/Nikon.html 1674 case 'CNCV': // Canon:CompressorVersion - https://exiftool.org/TagNames/Canon.html 1611 $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); 1612 $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); 1613 } 1614 break; 1615 case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG 1616 $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); 1617 break; 1618 case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html 1619 case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html 1620 case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html 1675 1621 $atom_structure['data'] = $atom_data; 1676 1622 break; … … 1679 1625 // some kind of metacontainer, may contain a big data dump such as: 1680 1626 // 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 1681 // http s://xhelmboyx.tripod.com/formats/qti-layout.txt1627 // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt 1682 1628 1683 1629 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); … … 1776 1722 'debug_list' => '', // Used to debug variables stored as comma delimited strings 1777 1723 ); 1778 $debug_structure = array();1779 1724 $debug_structure['debug_items'] = array(); 1780 1725 // Can start loop here to decode all sensor data in 32 Byte chunks: … … 2095 2040 */ 2096 2041 public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { 2097 $atom_structure = array();2042 $atom_structure = false; 2098 2043 $subatomoffset = 0; 2099 2044 $subatomcounter = 0; … … 2113 2058 continue; 2114 2059 } 2115 break;2060 return $atom_structure; 2116 2061 } 2117 2062 if (strlen($subatomdata) < ($subatomsize - 8)) { … … 2119 2064 // this may be because we are refusing to parse large subatoms, or it may be because this atom had its size set too large 2120 2065 // so we passed in the start of a following atom incorrectly? 2121 break;2066 return $atom_structure; 2122 2067 } 2123 2068 $atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms); 2124 2069 $subatomoffset += $subatomsize; 2125 2070 } 2126 2127 if (empty($atom_structure)) {2128 return false;2129 }2130 2131 2071 return $atom_structure; 2132 2072 } … … 2613 2553 if (empty($QuicktimeContentRatingLookup)) { 2614 2554 $QuicktimeContentRatingLookup[0] = 'None'; 2615 $QuicktimeContentRatingLookup[1] = 'Explicit';2616 2555 $QuicktimeContentRatingLookup[2] = 'Clean'; 2617 $QuicktimeContentRatingLookup[4] = 'Explicit (old)';2556 $QuicktimeContentRatingLookup[4] = 'Explicit'; 2618 2557 } 2619 2558 return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid'); … … 2666 2605 } 2667 2606 return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid'); 2607 } 2608 2609 /** 2610 * @param string $atom_data 2611 * 2612 * @return array 2613 */ 2614 public function QuicktimeParseNikonNCTG($atom_data) { 2615 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG 2616 // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 2617 // Data is stored as records of: 2618 // * 4 bytes record type 2619 // * 2 bytes size of data field type: 2620 // 0x0001 = flag (size field *= 1-byte) 2621 // 0x0002 = char (size field *= 1-byte) 2622 // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB 2623 // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD 2624 // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together 2625 // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? 2626 // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? 2627 // * 2 bytes data size field 2628 // * ? bytes data (string data may be null-padded; datestamp fields are in the format "2011:05:25 20:24:15") 2629 // all integers are stored BigEndian 2630 2631 $NCTGtagName = array( 2632 0x00000001 => 'Make', 2633 0x00000002 => 'Model', 2634 0x00000003 => 'Software', 2635 0x00000011 => 'CreateDate', 2636 0x00000012 => 'DateTimeOriginal', 2637 0x00000013 => 'FrameCount', 2638 0x00000016 => 'FrameRate', 2639 0x00000022 => 'FrameWidth', 2640 0x00000023 => 'FrameHeight', 2641 0x00000032 => 'AudioChannels', 2642 0x00000033 => 'AudioBitsPerSample', 2643 0x00000034 => 'AudioSampleRate', 2644 0x02000001 => 'MakerNoteVersion', 2645 0x02000005 => 'WhiteBalance', 2646 0x0200000b => 'WhiteBalanceFineTune', 2647 0x0200001e => 'ColorSpace', 2648 0x02000023 => 'PictureControlData', 2649 0x02000024 => 'WorldTime', 2650 0x02000032 => 'UnknownInfo', 2651 0x02000083 => 'LensType', 2652 0x02000084 => 'Lens', 2653 ); 2654 2655 $offset = 0; 2656 $data = null; 2657 $datalength = strlen($atom_data); 2658 $parsed = array(); 2659 while ($offset < $datalength) { 2660 $record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4; 2661 $data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; 2662 $data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; 2663 switch ($data_size_type) { 2664 case 0x0001: // 0x0001 = flag (size field *= 1-byte) 2665 $data = getid3_lib::BigEndian2Int(substr($atom_data, $offset, $data_size * 1)); 2666 $offset += ($data_size * 1); 2667 break; 2668 case 0x0002: // 0x0002 = char (size field *= 1-byte) 2669 $data = substr($atom_data, $offset, $data_size * 1); 2670 $offset += ($data_size * 1); 2671 $data = rtrim($data, "\x00"); 2672 break; 2673 case 0x0003: // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB 2674 $data = ''; 2675 for ($i = $data_size - 1; $i >= 0; $i--) { 2676 $data .= substr($atom_data, $offset + ($i * 2), 2); 2677 } 2678 $data = getid3_lib::BigEndian2Int($data); 2679 $offset += ($data_size * 2); 2680 break; 2681 case 0x0004: // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD 2682 $data = ''; 2683 for ($i = $data_size - 1; $i >= 0; $i--) { 2684 $data .= substr($atom_data, $offset + ($i * 4), 4); 2685 } 2686 $data = getid3_lib::BigEndian2Int($data); 2687 $offset += ($data_size * 4); 2688 break; 2689 case 0x0005: // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together 2690 $data = array(); 2691 for ($i = 0; $i < $data_size; $i++) { 2692 $numerator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 0, 4)); 2693 $denomninator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 4, 4)); 2694 if ($denomninator == 0) { 2695 $data[$i] = false; 2696 } else { 2697 $data[$i] = (double) $numerator / $denomninator; 2698 } 2699 } 2700 $offset += (8 * $data_size); 2701 if (count($data) == 1) { 2702 $data = $data[0]; 2703 } 2704 break; 2705 case 0x0007: // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? 2706 $data = substr($atom_data, $offset, $data_size * 1); 2707 $offset += ($data_size * 1); 2708 break; 2709 case 0x0008: // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? 2710 $data = substr($atom_data, $offset, $data_size * 2); 2711 $offset += ($data_size * 2); 2712 break; 2713 default: 2714 echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>'; 2715 break 2; 2716 } 2717 2718 switch ($record_type) { 2719 case 0x00000011: // CreateDate 2720 case 0x00000012: // DateTimeOriginal 2721 $data = strtotime($data); 2722 break; 2723 case 0x0200001e: // ColorSpace 2724 switch ($data) { 2725 case 1: 2726 $data = 'sRGB'; 2727 break; 2728 case 2: 2729 $data = 'Adobe RGB'; 2730 break; 2731 } 2732 break; 2733 case 0x02000023: // PictureControlData 2734 $PictureControlAdjust = array(0=>'default', 1=>'quick', 2=>'full'); 2735 $FilterEffect = array(0x80=>'off', 0x81=>'yellow', 0x82=>'orange', 0x83=>'red', 0x84=>'green', 0xff=>'n/a'); 2736 $ToningEffect = array(0x80=>'b&w', 0x81=>'sepia', 0x82=>'cyanotype', 0x83=>'red', 0x84=>'yellow', 0x85=>'green', 0x86=>'blue-green', 0x87=>'blue', 0x88=>'purple-blue', 0x89=>'red-purple', 0xff=>'n/a'); 2737 $data = array( 2738 'PictureControlVersion' => substr($data, 0, 4), 2739 'PictureControlName' => rtrim(substr($data, 4, 20), "\x00"), 2740 'PictureControlBase' => rtrim(substr($data, 24, 20), "\x00"), 2741 //'?' => substr($data, 44, 4), 2742 'PictureControlAdjust' => $PictureControlAdjust[ord(substr($data, 48, 1))], 2743 'PictureControlQuickAdjust' => ord(substr($data, 49, 1)), 2744 'Sharpness' => ord(substr($data, 50, 1)), 2745 'Contrast' => ord(substr($data, 51, 1)), 2746 'Brightness' => ord(substr($data, 52, 1)), 2747 'Saturation' => ord(substr($data, 53, 1)), 2748 'HueAdjustment' => ord(substr($data, 54, 1)), 2749 'FilterEffect' => $FilterEffect[ord(substr($data, 55, 1))], 2750 'ToningEffect' => $ToningEffect[ord(substr($data, 56, 1))], 2751 'ToningSaturation' => ord(substr($data, 57, 1)), 2752 ); 2753 break; 2754 case 0x02000024: // WorldTime 2755 // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#WorldTime 2756 // timezone is stored as offset from GMT in minutes 2757 $timezone = getid3_lib::BigEndian2Int(substr($data, 0, 2)); 2758 if ($timezone & 0x8000) { 2759 $timezone = 0 - (0x10000 - $timezone); 2760 } 2761 $timezone /= 60; 2762 2763 $dst = (bool) getid3_lib::BigEndian2Int(substr($data, 2, 1)); 2764 switch (getid3_lib::BigEndian2Int(substr($data, 3, 1))) { 2765 case 2: 2766 $datedisplayformat = 'D/M/Y'; break; 2767 case 1: 2768 $datedisplayformat = 'M/D/Y'; break; 2769 case 0: 2770 default: 2771 $datedisplayformat = 'Y/M/D'; break; 2772 } 2773 2774 $data = array('timezone'=>floatval($timezone), 'dst'=>$dst, 'display'=>$datedisplayformat); 2775 break; 2776 case 0x02000083: // LensType 2777 $data = array( 2778 //'_' => $data, 2779 'mf' => (bool) ($data & 0x01), 2780 'd' => (bool) ($data & 0x02), 2781 'g' => (bool) ($data & 0x04), 2782 'vr' => (bool) ($data & 0x08), 2783 ); 2784 break; 2785 } 2786 $tag_name = (isset($NCTGtagName[$record_type]) ? $NCTGtagName[$record_type] : '0x'.str_pad(dechex($record_type), 8, '0', STR_PAD_LEFT)); 2787 $parsed[$tag_name] = $data; 2788 } 2789 return $parsed; 2668 2790 } 2669 2791 -
trunk/src/wp-includes/ID3/module.audio-video.riff.php
r51900 r51901 57 57 $thisfile_riff_WAVE = array(); 58 58 59 $Original = array();60 59 $Original['avdataoffset'] = $info['avdataoffset']; 61 60 $Original['avdataend'] = $info['avdataend']; … … 298 297 $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0]; 299 298 300 $thisfile_riff_WAVE_bext_0['title'] = substr($thisfile_riff_WAVE_bext_0['data'], 0, 256); 301 $thisfile_riff_WAVE_bext_0['author'] = substr($thisfile_riff_WAVE_bext_0['data'], 256, 32); 302 $thisfile_riff_WAVE_bext_0['reference'] = substr($thisfile_riff_WAVE_bext_0['data'], 288, 32); 303 foreach (array('title','author','reference') as $bext_key) { 304 // Some software (notably Logic Pro) may not blank existing data before writing a null-terminated string to the offsets 305 // assigned for text fields, resulting in a null-terminated string (or possibly just a single null) followed by garbage 306 // Keep only string as far as first null byte, discard rest of fixed-width data 307 // https://github.com/JamesHeinrich/getID3/issues/263 308 $null_terminator_offset = strpos($thisfile_riff_WAVE_bext_0[$bext_key], "\x00"); 309 $thisfile_riff_WAVE_bext_0[$bext_key] = substr($thisfile_riff_WAVE_bext_0[$bext_key], 0, $null_terminator_offset); 310 } 311 299 $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256)); 300 $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32)); 301 $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32)); 312 302 $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10); 313 303 $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8); … … 318 308 if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) { 319 309 if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) { 320 $bext_timestamp = array();321 310 list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date; 322 311 list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; … … 463 452 } 464 453 465 if (isset($thisfile_riff_WAVE['guan'][0]['data'])) { 466 // shortcut 467 $thisfile_riff_WAVE_guan_0 = &$thisfile_riff_WAVE['guan'][0]; 468 if (!empty($thisfile_riff_WAVE_guan_0['data']) && (substr($thisfile_riff_WAVE_guan_0['data'], 0, 14) == 'GUANO|Version:')) { 469 $thisfile_riff['guano'] = array(); 470 foreach (explode("\n", $thisfile_riff_WAVE_guan_0['data']) as $line) { 471 if ($line) { 472 @list($key, $value) = explode(':', $line, 2); 473 if (substr($value, 0, 3) == '[{"') { 474 if ($decoded = @json_decode($value, true)) { 475 if (!empty($decoded) && (count($decoded) == 1)) { 476 $value = $decoded[0]; 477 } else { 478 $value = $decoded; 479 } 480 } 481 } 482 $thisfile_riff['guano'] = array_merge_recursive($thisfile_riff['guano'], getid3_lib::CreateDeepArray($key, '|', $value)); 483 } 484 } 485 486 // https://www.wildlifeacoustics.com/SCHEMA/GUANO.html 487 foreach ($thisfile_riff['guano'] as $key => $value) { 488 switch ($key) { 489 case 'Loc Position': 490 if (preg_match('#^([\\+\\-]?[0-9]+\\.[0-9]+) ([\\+\\-]?[0-9]+\\.[0-9]+)$#', $value, $matches)) { 491 list($dummy, $latitude, $longitude) = $matches; 492 $thisfile_riff['comments']['gps_latitude'][0] = floatval($latitude); 493 $thisfile_riff['comments']['gps_longitude'][0] = floatval($longitude); 494 $thisfile_riff['guano'][$key] = floatval($latitude).' '.floatval($longitude); 495 } 496 break; 497 case 'Loc Elevation': // Elevation/altitude above mean sea level in meters 498 $thisfile_riff['comments']['gps_altitude'][0] = floatval($value); 499 $thisfile_riff['guano'][$key] = (float) $value; 500 break; 501 case 'Filter HP': // High-pass filter frequency in kHz 502 case 'Filter LP': // Low-pass filter frequency in kHz 503 case 'Humidity': // Relative humidity as a percentage 504 case 'Length': // Recording length in seconds 505 case 'Loc Accuracy': // Estimated Position Error in meters 506 case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing 507 case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing 508 $thisfile_riff['guano'][$key] = (float) $value; 509 break; 510 case 'Samplerate': // Recording sample rate, Hz 511 case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed. 512 $thisfile_riff['guano'][$key] = (int) $value; 513 break; 514 } 515 } 516 517 } else { 518 $this->warning('RIFF.guan data not in expected format'); 519 } 520 } 454 521 455 522 456 if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { … … 800 734 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) { 801 735 if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) { 802 $thisfile_riff_raw_strf_strhfccType_streamindex = null;803 736 for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) { 804 737 if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { … … 1137 1070 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); 1138 1071 $getid3_temp = new getID3(); 1139 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1072 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1140 1073 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1141 1074 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; … … 1240 1173 1241 1174 $getid3_temp = new getID3(); 1242 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1175 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1243 1176 $getid3_mpeg = new getid3_mpeg($getid3_temp); 1244 1177 $getid3_mpeg->Analyze(); … … 1326 1259 1327 1260 $getid3_temp = new getID3(); 1328 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1261 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1329 1262 $getid3_id3v2 = new getid3_id3v2($getid3_temp); 1330 1263 $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; … … 1582 1515 $RIFFchunk = false; 1583 1516 $FoundAllChunksWeNeed = false; 1584 $LISTchunkParent = null;1585 $LISTchunkMaxOffset = null;1586 $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77"1587 1517 1588 1518 try { … … 1628 1558 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { 1629 1559 $getid3_temp = new getID3(); 1630 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1560 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1631 1561 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1632 1562 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; … … 1646 1576 } 1647 1577 1648 } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) { 1578 } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) { 1579 1649 1580 // AC3 1650 1581 $getid3_temp = new getID3(); 1651 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1582 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1652 1583 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; 1653 1584 $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; … … 1710 1641 if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { 1711 1642 $getid3_temp = new getID3(); 1712 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1643 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1713 1644 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1714 1645 $getid3_temp->info['avdataend'] = $info['avdataend']; … … 1722 1653 } 1723 1654 1724 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) {1655 } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) { 1725 1656 1726 1657 // This is probably AC-3 data 1727 1658 $getid3_temp = new getID3(); 1728 1659 if ($isRegularAC3) { 1729 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1660 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1730 1661 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1731 1662 $getid3_temp->info['avdataend'] = $info['avdataend']; … … 1743 1674 $ac3_data .= substr($testData, 8 + $i + 0, 1); 1744 1675 } 1745 $getid3_ac3->getid3->info['avdataoffset'] = 0;1746 $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data);1747 1676 $getid3_ac3->AnalyzeString($ac3_data); 1748 1677 } … … 1763 1692 // This is probably DTS data 1764 1693 $getid3_temp = new getID3(); 1765 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);1694 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); 1766 1695 $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; 1767 1696 $getid3_dts = new getid3_dts($getid3_temp); … … 1804 1733 case 'MEXT': 1805 1734 case 'DISP': 1806 case 'wamd':1807 case 'guan':1808 1735 // always read data in 1809 1736 case 'JUNK': … … 2150 2077 public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { 2151 2078 2152 $parsed = array();2153 2079 $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure 2154 2080 $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels -
trunk/src/wp-includes/ID3/module.audio.flac.php
r51900 r51901 403 403 $info = &$this->getid3->info; 404 404 405 $picture = array();406 405 $picture['typeid'] = getid3_lib::BigEndian2Int($this->fread(4)); 407 406 $picture['picturetype'] = self::pictureTypeLookup($picture['typeid']); -
trunk/src/wp-includes/ID3/module.audio.mp3.php
r51900 r51901 19 19 } 20 20 21 // number of frames to scan to determine if MPEG-audio sequence is valid 22 // Lower this number to 5-20 for faster scanning 23 // Increase this number to 50+ for most accurate detection of valid VBR/CBR 24 // mpeg-audio streams 25 define('GETID3_MP3_VALID_CHECK_FRAMES', 35); 26 21 27 22 28 class getid3_mp3 extends getid3_handler … … 31 37 32 38 /** 33 * number of frames to scan to determine if MPEG-audio sequence is valid34 * Lower this number to 5-20 for faster scanning35 * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams36 *37 * @var int38 */39 public $mp3_valid_check_frames = 50;40 41 /**42 39 * @return bool 43 40 */ … … 59 56 } 60 57 61 $CurrentDataLAMEversionString = null;62 58 if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) { 63 59 … … 126 122 $PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)" 127 123 if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) { 128 if (!empty($info['audio']['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version']) && ($info['audio']['encoder'] == $info['mpeg']['audio']['LAME']['short_version'])) {129 if (preg_match('#^LAME[0-9\\.]+#', $PossiblyLongerLAMEversion_NewString, $matches)) {130 // "LAME3.100" -> "LAME3.100.1", but avoid including "(alpha)" and similar131 $info['mpeg']['audio']['LAME']['short_version'] = $matches[0];132 }133 }134 124 $info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString; 135 125 } … … 306 296 307 297 if ($info['audio']['bitrate_mode'] == 'cbr') { 308 $encoder_options = strtoupper($info['audio']['bitrate_mode']). round($info['audio']['bitrate'] / 1000);298 $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000); 309 299 } else { 310 300 $encoder_options = strtoupper($info['audio']['bitrate_mode']); … … 499 489 $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; 500 490 } else { 501 $this-> warning('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset);491 $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); 502 492 return false; 503 493 } … … 733 723 $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20); 734 724 $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9); 735 736 //$thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); 737 $thisfile_mpeg_audio_lame['numeric_version'] = ''; 738 if (preg_match('#^LAME([0-9\\.a-z]*)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { 725 $thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); 726 if (preg_match('#^LAME([0-9\\.a-z]+)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { 739 727 $thisfile_mpeg_audio_lame['short_version'] = $matches[0]; 740 728 $thisfile_mpeg_audio_lame['numeric_version'] = $matches[1]; 741 729 } 742 if (strlen($thisfile_mpeg_audio_lame['numeric_version']) > 0) { 743 foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { 744 $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); 730 foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { 731 $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); 732 } 733 734 //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { 735 if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 736 737 // extra 11 chars are not part of version string when LAMEtag present 738 unset($thisfile_mpeg_audio_lame['long_version']); 739 740 // It the LAME tag was only introduced in LAME v3.90 741 // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 742 743 // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html 744 // are assuming a 'Xing' identifier offset of 0x24, which is the case for 745 // MPEG-1 non-mono, but not for other combinations 746 $LAMEtagOffsetContant = $VBRidOffset - 0x24; 747 748 // shortcuts 749 $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); 750 $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; 751 $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; 752 $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; 753 $thisfile_mpeg_audio_lame['raw'] = array(); 754 $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; 755 756 // byte $9B VBR Quality 757 // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. 758 // Actually overwrites original Xing bytes 759 unset($thisfile_mpeg_audio['VBR_scale']); 760 $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); 761 762 // bytes $9C-$A4 Encoder short VersionString 763 $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); 764 765 // byte $A5 Info Tag revision + VBR method 766 $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); 767 768 $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; 769 $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; 770 $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); 771 $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' 772 773 // byte $A6 Lowpass filter value 774 $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; 775 776 // bytes $A7-$AE Replay Gain 777 // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html 778 // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" 779 if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { 780 // LAME 3.94a16 and later - 9.23 fixed point 781 // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 782 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); 783 } else { 784 // LAME 3.94a15 and earlier - 32-bit floating point 785 // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 786 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); 745 787 } 746 //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { 747 if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 748 749 // extra 11 chars are not part of version string when LAMEtag present 750 unset($thisfile_mpeg_audio_lame['long_version']); 751 752 // It the LAME tag was only introduced in LAME v3.90 753 // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 754 755 // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html 756 // are assuming a 'Xing' identifier offset of 0x24, which is the case for 757 // MPEG-1 non-mono, but not for other combinations 758 $LAMEtagOffsetContant = $VBRidOffset - 0x24; 759 760 // shortcuts 761 $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); 762 $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; 763 $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; 764 $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; 765 $thisfile_mpeg_audio_lame['raw'] = array(); 766 $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; 767 768 // byte $9B VBR Quality 769 // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. 770 // Actually overwrites original Xing bytes 771 unset($thisfile_mpeg_audio['VBR_scale']); 772 $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); 773 774 // bytes $9C-$A4 Encoder short VersionString 775 $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); 776 777 // byte $A5 Info Tag revision + VBR method 778 $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); 779 780 $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; 781 $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; 782 $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); 783 $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' 784 785 // byte $A6 Lowpass filter value 786 $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; 787 788 // bytes $A7-$AE Replay Gain 789 // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html 790 // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" 791 if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { 792 // LAME 3.94a16 and later - 9.23 fixed point 793 // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 794 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); 795 } else { 796 // LAME 3.94a15 and earlier - 32-bit floating point 797 // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 798 $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); 788 if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { 789 unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 790 } else { 791 $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 792 } 793 794 $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); 795 $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); 796 797 798 if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { 799 800 $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; 801 $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; 802 $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; 803 $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; 804 $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); 805 $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); 806 $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); 807 808 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 809 $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 799 810 } 800 if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { 801 unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 802 } else { 803 $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); 811 $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; 812 $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; 813 } else { 814 unset($thisfile_mpeg_audio_lame_RGAD['track']); 815 } 816 if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { 817 818 $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; 819 $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; 820 $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; 821 $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; 822 $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); 823 $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); 824 $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); 825 826 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 827 $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 804 828 } 805 806 $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); 807 $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); 808 809 810 if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { 811 812 $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; 813 $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; 814 $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; 815 $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; 816 $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); 817 $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); 818 $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); 819 820 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 821 $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 822 } 823 $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; 824 $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; 825 } else { 826 unset($thisfile_mpeg_audio_lame_RGAD['track']); 827 } 828 if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { 829 830 $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; 831 $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; 832 $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; 833 $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; 834 $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); 835 $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); 836 $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); 837 838 if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { 839 $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; 840 } 841 $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; 842 $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; 843 } else { 844 unset($thisfile_mpeg_audio_lame_RGAD['album']); 845 } 846 if (empty($thisfile_mpeg_audio_lame_RGAD)) { 847 unset($thisfile_mpeg_audio_lame['RGAD']); 848 } 849 850 851 // byte $AF Encoding flags + ATH Type 852 $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); 853 $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); 854 $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); 855 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); 856 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); 857 $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; 858 859 // byte $B0 if ABR {specified bitrate} else {minimal bitrate} 860 $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); 861 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) 862 $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 863 } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) 864 // ignore 865 } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate 866 $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 867 } 868 869 // bytes $B1-$B3 Encoder delays 870 $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); 871 $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; 872 $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; 873 874 // byte $B4 Misc 875 $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); 876 $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); 877 $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; 878 $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; 879 $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; 880 $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; 881 $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); 882 $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; 883 $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); 884 885 // byte $B5 MP3 Gain 886 $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); 887 $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; 888 $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); 889 890 // bytes $B6-$B7 Preset and surround info 891 $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); 892 // Reserved = ($PresetSurroundBytes & 0xC000); 893 $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); 894 $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); 895 $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); 896 $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); 897 if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { 898 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); 899 } 900 if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { 901 // this may change if 3.90.4 ever comes out 902 $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; 903 } 904 905 // bytes $B8-$BB MusicLength 906 $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); 907 $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); 908 909 // bytes $BC-$BD MusicCRC 910 $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); 911 912 // bytes $BE-$BF CRC-16 of Info Tag 913 $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); 914 915 916 // LAME CBR 917 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { 918 919 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; 920 $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); 921 $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; 922 //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { 923 // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; 924 //} 925 926 } 927 829 $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; 830 $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; 831 } else { 832 unset($thisfile_mpeg_audio_lame_RGAD['album']); 928 833 } 834 if (empty($thisfile_mpeg_audio_lame_RGAD)) { 835 unset($thisfile_mpeg_audio_lame['RGAD']); 836 } 837 838 839 // byte $AF Encoding flags + ATH Type 840 $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); 841 $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); 842 $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); 843 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); 844 $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); 845 $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; 846 847 // byte $B0 if ABR {specified bitrate} else {minimal bitrate} 848 $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); 849 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) 850 $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 851 } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) 852 // ignore 853 } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate 854 $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; 855 } 856 857 // bytes $B1-$B3 Encoder delays 858 $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); 859 $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; 860 $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; 861 862 // byte $B4 Misc 863 $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); 864 $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); 865 $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; 866 $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; 867 $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; 868 $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; 869 $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); 870 $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; 871 $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); 872 873 // byte $B5 MP3 Gain 874 $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); 875 $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; 876 $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); 877 878 // bytes $B6-$B7 Preset and surround info 879 $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); 880 // Reserved = ($PresetSurroundBytes & 0xC000); 881 $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); 882 $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); 883 $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); 884 $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); 885 if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { 886 $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); 887 } 888 if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { 889 // this may change if 3.90.4 ever comes out 890 $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; 891 } 892 893 // bytes $B8-$BB MusicLength 894 $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); 895 $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); 896 897 // bytes $BC-$BD MusicCRC 898 $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); 899 900 // bytes $BE-$BF CRC-16 of Info Tag 901 $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); 902 903 904 // LAME CBR 905 if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { 906 907 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; 908 $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); 909 $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; 910 //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { 911 // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; 912 //} 913 914 } 915 929 916 } 930 917 } … … 1022 1009 if (!$this->RecursiveFrameScanning($offset, $nextframetestoffset, $ScanAsCBR)) { 1023 1010 return false; 1024 }1025 if (!empty($this->getid3->info['mp3_validity_check_bitrates']) && !empty($thisfile_mpeg_audio['bitrate_mode']) && ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') && !empty($thisfile_mpeg_audio['VBR_bitrate'])) {1026 // https://github.com/JamesHeinrich/getID3/issues/2871027 if (count(array_keys($this->getid3->info['mp3_validity_check_bitrates'])) == 1) {1028 list($cbr_bitrate_in_short_scan) = array_keys($this->getid3->info['mp3_validity_check_bitrates']);1029 $deviation_cbr_from_header_bitrate = abs($thisfile_mpeg_audio['VBR_bitrate'] - $cbr_bitrate_in_short_scan) / $cbr_bitrate_in_short_scan;1030 if ($deviation_cbr_from_header_bitrate < 0.01) {1031 // VBR header bitrate may differ slightly from true bitrate of frames, perhaps accounting for overhead of VBR header frame itself?1032 // If measured CBR bitrate is within 1% of specified bitrate in VBR header then assume that file is truly CBR1033 $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';1034 //$this->warning('VBR header ignored, assuming CBR '.round($cbr_bitrate_in_short_scan / 1000).'kbps based on scan of '.$this->mp3_valid_check_frames.' frames');1035 }1036 }1037 }1038 if (isset($this->getid3->info['mp3_validity_check_bitrates'])) {1039 unset($this->getid3->info['mp3_validity_check_bitrates']);1040 1011 } 1041 1012 … … 1160 1131 $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false); 1161 1132 1162 $info['mp3_validity_check_bitrates'] = array(); 1163 for ($i = 0; $i < $this->mp3_valid_check_frames; $i++) { 1164 // check next (default: 50) frames for validity, to make sure we haven't run across a false synch 1133 for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) { 1134 // check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch 1165 1135 if (($nextframetestoffset + 4) >= $info['avdataend']) { 1166 1136 // end of file … … 1170 1140 $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); 1171 1141 if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { 1172 getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]);1173 1142 if ($ScanAsCBR) { 1174 1143 // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header … … 1305 1274 $LongMPEGpaddingLookup = array(); 1306 1275 $LongMPEGfrequencyLookup = array(); 1307 $Distribution = array();1308 1276 $Distribution['bitrate'] = array(); 1309 1277 $Distribution['frequency'] = array(); … … 1466 1434 $sync_seek_buffer_size = strlen($header); 1467 1435 $SynchSeekOffset = 0; 1468 $SyncSeekAttempts = 0;1469 $SyncSeekAttemptsMax = 1000;1470 $FirstFrameThisfileInfo = null;1471 1436 while ($SynchSeekOffset < $sync_seek_buffer_size) { 1472 1437 if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) { … … 1507 1472 } 1508 1473 1509 if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // possible synch detected 1510 if (++$SyncSeekAttempts >= $SyncSeekAttemptsMax) { 1511 // https://github.com/JamesHeinrich/getID3/issues/286 1512 // corrupt files claiming to be MP3, with a large number of 0xFF bytes near the beginning, can cause this loop to take a very long time 1513 // should have escape condition to avoid spending too much time scanning a corrupt file 1514 // if a synch's not found within the first 128k bytes, then give up 1515 $this->error('Could not find valid MPEG audio synch after scanning '.$SyncSeekAttempts.' candidate offsets'); 1516 if (isset($info['audio']['bitrate'])) { 1517 unset($info['audio']['bitrate']); 1518 } 1519 if (isset($info['mpeg']['audio'])) { 1520 unset($info['mpeg']['audio']); 1521 } 1522 if (empty($info['mpeg'])) { 1523 unset($info['mpeg']); 1524 } 1525 return false; 1526 } 1474 if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected 1527 1475 $FirstFrameAVDataOffset = null; 1528 1476 if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) { … … 1564 1512 $info = $dummy; 1565 1513 $info['avdataoffset'] = $GarbageOffsetEnd; 1566 $this->warning('apparently-valid VBR header not used because could not find '. $this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd);1514 $this->warning('apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd); 1567 1515 } else { 1568 $this->warning('using data from VBR header even though could not find '. $this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')');1516 $this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')'); 1569 1517 } 1570 1518 } … … 1611 1559 for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) { 1612 1560 $frames_scanned_this_segment = 0; 1613 $scan_start_offset = array();1614 1561 if ($this->ftell() >= $info['avdataend']) { 1615 1562 break; … … 1941 1888 } 1942 1889 1943 $MPEGrawHeader = array();1944 1890 $MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4; 1945 1891 $MPEGrawHeader['version'] = (ord($Header4Bytes[1]) & 0x18) >> 3; // BB -
trunk/src/wp-includes/ID3/module.audio.ogg.php
r51900 r51901 530 530 public function ParseOggPageHeader() { 531 531 // http://xiph.org/ogg/vorbis/doc/framing.html 532 $oggheader = array();533 532 $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file 534 533 … … 682 681 $VorbisCommentPage++; 683 682 684 if ($oggpageinfo = $this->ParseOggPageHeader()) { 685 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; 686 687 // First, save what we haven't read yet 688 $AsYetUnusedData = substr($commentdata, $commentdataoffset); 689 690 // Then take that data off the end 691 $commentdata = substr($commentdata, 0, $commentdataoffset); 692 693 // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct 694 $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); 695 $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); 696 697 // Finally, stick the unused data back on the end 698 $commentdata .= $AsYetUnusedData; 699 700 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); 701 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { 702 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 703 break; 704 } 705 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); 706 if ($readlength <= 0) { 707 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 708 break; 709 } 710 $commentdata .= $this->fread($readlength); 711 712 //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; 713 } else { 714 $this->warning('failed to ParseOggPageHeader() at offset '.$this->ftell()); 683 $oggpageinfo = $this->ParseOggPageHeader(); 684 $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; 685 686 // First, save what we haven't read yet 687 $AsYetUnusedData = substr($commentdata, $commentdataoffset); 688 689 // Then take that data off the end 690 $commentdata = substr($commentdata, 0, $commentdataoffset); 691 692 // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct 693 $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); 694 $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); 695 696 // Finally, stick the unused data back on the end 697 $commentdata .= $AsYetUnusedData; 698 699 //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); 700 if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { 701 $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 715 702 break; 716 703 } 704 $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); 705 if ($readlength <= 0) { 706 $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); 707 break; 708 } 709 $commentdata .= $this->fread($readlength); 710 711 //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; 717 712 } 718 713 $ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset; -
trunk/src/wp-includes/ID3/module.tag.apetag.php
r51900 r51901 361 361 362 362 // shortcut 363 $headerfooterinfo = array();364 363 $headerfooterinfo['raw'] = array(); 365 364 $headerfooterinfo_raw = &$headerfooterinfo['raw']; … … 391 390 // All are set to zero on creation and ignored on reading." 392 391 // http://wiki.hydrogenaud.io/index.php?title=Ape_Tags_Flags 393 $flags = array();394 392 $flags['header'] = (bool) ($rawflagint & 0x80000000); 395 393 $flags['footer'] = (bool) ($rawflagint & 0x40000000); -
trunk/src/wp-includes/ID3/module.tag.id3v1.php
r51900 r51901 32 32 } 33 33 34 if($info['filesize'] < 256) { 35 $this->fseek(-128, SEEK_END); 36 $preid3v1 = ''; 37 $id3v1tag = $this->fread(128); 38 } else { 39 $this->fseek(-256, SEEK_END); 40 $preid3v1 = $this->fread(128); 41 $id3v1tag = $this->fread(128); 42 } 43 34 $this->fseek(-256, SEEK_END); 35 $preid3v1 = $this->fread(128); 36 $id3v1tag = $this->fread(128); 44 37 45 38 if (substr($id3v1tag, 0, 3) == 'TAG') { … … 47 40 $info['avdataend'] = $info['filesize'] - 128; 48 41 49 $ParsedID3v1 = array();50 42 $ParsedID3v1['title'] = $this->cutfield(substr($id3v1tag, 3, 30)); 51 43 $ParsedID3v1['artist'] = $this->cutfield(substr($id3v1tag, 33, 30)); … … 306 298 146 => 'JPop', 307 299 147 => 'Synthpop', 308 148 => 'Abstract',309 149 => 'Art Rock',310 150 => 'Baroque',311 151 => 'Bhangra',312 152 => 'Big Beat',313 153 => 'Breakbeat',314 154 => 'Chillout',315 155 => 'Downtempo',316 156 => 'Dub',317 157 => 'EBM',318 158 => 'Eclectic',319 159 => 'Electro',320 160 => 'Electroclash',321 161 => 'Emo',322 162 => 'Experimental',323 163 => 'Garage',324 164 => 'Global',325 165 => 'IDM',326 166 => 'Illbient',327 167 => 'Industro-Goth',328 168 => 'Jam Band',329 169 => 'Krautrock',330 170 => 'Leftfield',331 171 => 'Lounge',332 172 => 'Math Rock',333 173 => 'New Romantic',334 174 => 'Nu-Breakz',335 175 => 'Post-Punk',336 176 => 'Post-Rock',337 177 => 'Psytrance',338 178 => 'Shoegaze',339 179 => 'Space Rock',340 180 => 'Trop Rock',341 181 => 'World Music',342 182 => 'Neoclassical',343 183 => 'Audiobook',344 184 => 'Audio Theatre',345 185 => 'Neue Deutsche Welle',346 186 => 'Podcast',347 187 => 'Indie-Rock',348 188 => 'G-Funk',349 189 => 'Dubstep',350 190 => 'Garage Rock',351 191 => 'Psybient',352 300 353 301 255 => 'Unknown', -
trunk/src/wp-includes/ID3/module.tag.id3v2.php
r51900 r51901 346 346 if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) { 347 347 348 $parsedFrame = array();348 unset($parsedFrame); 349 349 $parsedFrame['frame_name'] = $frame_name; 350 350 $parsedFrame['frame_flags_raw'] = $frame_flags; … … 979 979 980 980 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USLT')) || // 4.8 USLT Unsynchronised lyric/text transcription 981 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription981 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription 982 982 // There may be more than one 'Unsynchronised lyrics/text transcription' frame 983 983 // in each tag, but only one with the same language and content descriptor. … … 995 995 $frame_textencoding_terminator = "\x00"; 996 996 } 997 if (strlen($parsedFrame['data']) >= (4 + strlen($frame_textencoding_terminator))) { // shouldn't be an issue but badly-written files have been spotted in the wild with not only no contents but also missing the required language field, see https://github.com/JamesHeinrich/getID3/issues/315 998 $frame_language = substr($parsedFrame['data'], $frame_offset, 3); 999 $frame_offset += 3; 1000 $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset); 1001 if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) { 1002 $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 1003 } 1004 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); 1005 $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']); 1006 $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); 1007 $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator); 1008 1009 $parsedFrame['encodingid'] = $frame_textencoding; 1010 $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); 1011 1012 $parsedFrame['language'] = $frame_language; 1013 $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); 1014 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { 1015 $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); 1016 } 1017 } else { 1018 $this->warning('Invalid data in frame "'.$parsedFrame['frame_name'].'" at offset '.$parsedFrame['dataoffset']); 997 $frame_language = substr($parsedFrame['data'], $frame_offset, 3); 998 $frame_offset += 3; 999 $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset); 1000 if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) { 1001 $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 1002 } 1003 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); 1004 $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']); 1005 $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); 1006 $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator); 1007 1008 $parsedFrame['encodingid'] = $frame_textencoding; 1009 $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); 1010 1011 $parsedFrame['language'] = $frame_language; 1012 $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); 1013 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { 1014 $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); 1019 1015 } 1020 1016 unset($parsedFrame['data']); … … 1375 1371 } 1376 1372 1377 $frame_imagetype = null;1378 $frame_mimetype = null;1379 1373 if ($id3v2_majorversion == 2 && strlen($parsedFrame['data']) > $frame_offset) { 1380 1374 $frame_imagetype = substr($parsedFrame['data'], $frame_offset, 3); … … 1963 1957 $parsedFrame['peakamplitude'] = getid3_lib::BigEndian2Float(substr($parsedFrame['data'], $frame_offset, 4)); 1964 1958 $frame_offset += 4; 1965 foreach (array('track','album') as $rgad_entry_type) { 1966 $rg_adjustment_word = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); 1967 $frame_offset += 2; 1968 $parsedFrame['raw'][$rgad_entry_type]['name'] = ($rg_adjustment_word & 0xE000) >> 13; 1969 $parsedFrame['raw'][$rgad_entry_type]['originator'] = ($rg_adjustment_word & 0x1C00) >> 10; 1970 $parsedFrame['raw'][$rgad_entry_type]['signbit'] = ($rg_adjustment_word & 0x0200) >> 9; 1971 $parsedFrame['raw'][$rgad_entry_type]['adjustment'] = ($rg_adjustment_word & 0x0100); 1972 } 1959 $rg_track_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); 1960 $frame_offset += 2; 1961 $rg_album_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); 1962 $frame_offset += 2; 1963 $parsedFrame['raw']['track']['name'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 0, 3)); 1964 $parsedFrame['raw']['track']['originator'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 3, 3)); 1965 $parsedFrame['raw']['track']['signbit'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 6, 1)); 1966 $parsedFrame['raw']['track']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 7, 9)); 1967 $parsedFrame['raw']['album']['name'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 0, 3)); 1968 $parsedFrame['raw']['album']['originator'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 3, 3)); 1969 $parsedFrame['raw']['album']['signbit'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 6, 1)); 1970 $parsedFrame['raw']['album']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 7, 9)); 1973 1971 $parsedFrame['track']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['track']['name']); 1974 1972 $parsedFrame['track']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['track']['originator']); … … 2447 2445 TND Dinars 2448 2446 TOP Pa'anga 2449 TRL Liras (old) 2450 TRY Liras 2447 TRL Liras 2451 2448 TTD Dollars 2452 2449 TVD Tuvalu Dollars … … 2649 2646 TOP Tonga 2650 2647 TRL Turkey 2651 TRY Turkey2652 2648 TTD Trinidad and Tobago 2653 2649 TVD Tuvalu -
trunk/src/wp-includes/ID3/module.tag.lyrics3.php
r51900 r51901 34 34 35 35 $this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] 36 $lyrics3offset = null;37 $lyrics3version = null;38 $lyrics3size = null;39 36 $lyrics3_id3v1 = $this->fread(128 + 9 + 6); 40 37 $lyrics3lsz = (int) substr($lyrics3_id3v1, 0, 6); // Lyrics3size -
trunk/src/wp-includes/ID3/readme.txt
r51900 r51901 626 626 * http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header 627 627 * http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf 628 * https://fileformats.fandom.com/wiki/Torrent_file
Note: See TracChangeset
for help on using the changeset viewer.