External Libraries: Update getID3() to 1.9.19.

Changelog: https://github.com/JamesHeinrich/getID3/compare/v1.9.18...v1.9.19

Props ayeshrajans, schlessera.
See #49945.

git-svn-id: https://develop.svn.wordpress.org/trunk@47601 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Sergey Biryukov 2020-04-20 11:11:48 +00:00
parent 5d5e3439e4
commit 02e17123f9
12 changed files with 244 additions and 112 deletions

View File

@ -18,7 +18,7 @@ class getid3_lib
* @param string $string * @param string $string
* @param bool $hex * @param bool $hex
* @param bool $spaces * @param bool $spaces
* @param string $htmlencoding * @param string|bool $htmlencoding
* *
* @return string * @return string
*/ */
@ -216,7 +216,6 @@ class getid3_lib
default: default:
return false; return false;
break;
} }
if ($floatvalue >= 0) { if ($floatvalue >= 0) {
$signbit = '0'; $signbit = '0';
@ -284,11 +283,9 @@ class getid3_lib
$floatvalue *= -1; $floatvalue *= -1;
} }
return $floatvalue; return $floatvalue;
break;
default: default:
return false; return false;
break;
} }
$exponentstring = substr($bitword, 1, $exponentbits); $exponentstring = substr($bitword, 1, $exponentbits);
$fractionstring = substr($bitword, $exponentbits + 1, $fractionbits); $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
@ -500,8 +497,8 @@ class getid3_lib
} }
/** /**
* @param array $array1 * @param mixed $array1
* @param array $array2 * @param mixed $array2
* *
* @return array|false * @return array|false
*/ */
@ -523,8 +520,8 @@ class getid3_lib
} }
/** /**
* @param array $array1 * @param mixed $array1
* @param array $array2 * @param mixed $array2
* *
* @return array|false * @return array|false
*/ */
@ -544,8 +541,8 @@ class getid3_lib
} }
/** /**
* @param array $array1 * @param mixed $array1
* @param array $array2 * @param mixed $array2
* *
* @return array|false|null * @return array|false|null
*/ */
@ -735,9 +732,9 @@ class getid3_lib
} }
/** /**
* @param SimpleXMLElement|array $XMLobject * @param SimpleXMLElement|array|mixed $XMLobject
* *
* @return array * @return mixed
*/ */
public static function SimpleXMLelement2array($XMLobject) { public static function SimpleXMLelement2array($XMLobject) {
if (!is_object($XMLobject) && !is_array($XMLobject)) { if (!is_object($XMLobject) && !is_array($XMLobject)) {
@ -1479,6 +1476,15 @@ class getid3_lib
* @return array|false * @return array|false
*/ */
public static function GetDataImageSize($imgData, &$imageinfo=array()) { public static function GetDataImageSize($imgData, &$imageinfo=array()) {
if (PHP_VERSION_ID >= 50400) {
$GetDataImageSize = @getimagesizefromstring($imgData, $imageinfo);
if ($GetDataImageSize === false || !isset($GetDataImageSize[0], $GetDataImageSize[1])) {
return false;
}
$GetDataImageSize['height'] = $GetDataImageSize[0];
$GetDataImageSize['width'] = $GetDataImageSize[1];
return $GetDataImageSize;
}
static $tempdir = ''; static $tempdir = '';
if (empty($tempdir)) { if (empty($tempdir)) {
if (function_exists('sys_get_temp_dir')) { if (function_exists('sys_get_temp_dir')) {
@ -1487,14 +1493,13 @@ class getid3_lib
// yes this is ugly, feel free to suggest a better way // yes this is ugly, feel free to suggest a better way
if (include_once(dirname(__FILE__).'/getid3.php')) { if (include_once(dirname(__FILE__).'/getid3.php')) {
if ($getid3_temp = new getID3()) { $getid3_temp = new getID3();
if ($getid3_temp_tempdir = $getid3_temp->tempdir) { if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
$tempdir = $getid3_temp_tempdir; $tempdir = $getid3_temp_tempdir;
} }
unset($getid3_temp, $getid3_temp_tempdir); unset($getid3_temp, $getid3_temp_tempdir);
} }
} }
}
$GetDataImageSize = false; $GetDataImageSize = false;
if ($tempfilename = tempnam($tempdir, 'gI3')) { if ($tempfilename = tempnam($tempdir, 'gI3')) {
if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) { if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) {
@ -1568,7 +1573,7 @@ class getid3_lib
if (!is_int($key) && !ctype_digit($key)) { if (!is_int($key) && !ctype_digit($key)) {
$ThisFileInfo['comments'][$tagname][$key] = $value; $ThisFileInfo['comments'][$tagname][$key] = $value;
} else { } else {
if (isset($ThisFileInfo['comments'][$tagname])) { if (!isset($ThisFileInfo['comments'][$tagname])) {
$ThisFileInfo['comments'][$tagname] = array($value); $ThisFileInfo['comments'][$tagname] = array($value);
} else { } else {
$ThisFileInfo['comments'][$tagname][] = $value; $ThisFileInfo['comments'][$tagname][] = $value;

View File

@ -250,7 +250,7 @@ class getID3
*/ */
protected $startup_warning = ''; protected $startup_warning = '';
const VERSION = '1.9.18-201907240906'; const VERSION = '1.9.19-201912131005';
const FREAD_BUFFER_SIZE = 32768; const FREAD_BUFFER_SIZE = 32768;
const ATTACHMENTS_NONE = false; const ATTACHMENTS_NONE = false;
@ -266,14 +266,16 @@ class getID3
} }
// Check memory // Check memory
$this->memory_limit = ini_get('memory_limit'); $memoryLimit = ini_get('memory_limit');
if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) { if (preg_match('#([0-9]+) ?M#i', $memoryLimit, $matches)) {
// could be stored as "16M" rather than 16777216 for example // could be stored as "16M" rather than 16777216 for example
$this->memory_limit = $matches[1] * 1048576; $memoryLimit = $matches[1] * 1048576;
} elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0 } elseif (preg_match('#([0-9]+) ?G#i', $memoryLimit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
// could be stored as "2G" rather than 2147483648 for example // could be stored as "2G" rather than 2147483648 for example
$this->memory_limit = $matches[1] * 1073741824; $memoryLimit = $matches[1] * 1073741824;
} }
$this->memory_limit = $memoryLimit;
if ($this->memory_limit <= 0) { if ($this->memory_limit <= 0) {
// memory limits probably disabled // memory limits probably disabled
} elseif ($this->memory_limit <= 4194304) { } elseif ($this->memory_limit <= 4194304) {
@ -287,30 +289,28 @@ class getID3
$this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.'); $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
} }
if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) { if (($mbstring_func_overload = (int) ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
// http://php.net/manual/en/mbstring.overload.php // http://php.net/manual/en/mbstring.overload.php
// "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions" // "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
// getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those. // getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
$this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n"; $this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
} }
// WORDPRESS CHANGE FROM UPSTREAM // check for magic quotes in PHP < 7.4.0 (when these functions became deprecated)
// Comment out deprecated function if (version_compare(PHP_VERSION, '7.4.0', '<')) {
/*
// Check for magic_quotes_runtime // Check for magic_quotes_runtime
if (function_exists('get_magic_quotes_runtime')) { if (function_exists('get_magic_quotes_runtime')) {
if (get_magic_quotes_runtime()) { if (get_magic_quotes_runtime()) {
$this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n"; $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
} }
} }
// Check for magic_quotes_gpc // Check for magic_quotes_gpc
if (function_exists('magic_quotes_gpc')) { if (function_exists('get_magic_quotes_gpc')) {
if (get_magic_quotes_gpc()) { if (get_magic_quotes_gpc()) {
$this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n"; $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
} }
} }
**/ }
// Load support library // Load support library
if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
@ -404,6 +404,7 @@ class getID3
/** /**
* @param string $filename * @param string $filename
* @param int $filesize * @param int $filesize
* @param resource $fp
* *
* @return bool * @return bool
* *
@ -516,6 +517,7 @@ class getID3
* @param string $filename * @param string $filename
* @param int $filesize * @param int $filesize
* @param string $original_filename * @param string $original_filename
* @param resource $fp
* *
* @return array * @return array
*/ */
@ -1106,6 +1108,14 @@ class getID3
'mime_type' => 'video/MP2T', 'mime_type' => 'video/MP2T',
), ),
// WTV - audio/video - Windows Recorded TV Show
'wtv' => array(
'pattern' => '^\\xB7\\xD8\\x00\\x20\\x37\\x49\\xDA\\x11\\xA6\\x4E\\x00\\x07\\xE9\\x5E\\xAD\\x8D',
'group' => 'audio-video',
'module' => 'wtv',
'mime_type' => 'video/x-ms-wtv',
),
// Still-Image formats // Still-Image formats
@ -1528,7 +1538,6 @@ class getID3
default: default:
return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()'); return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
break;
} }
if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) { if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {

View File

@ -363,7 +363,7 @@ class getid3_asf extends getid3_handler
$thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']); $thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']);
if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) { if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
$thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000); $thisfile_audio['bitrate'] = (int) trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000;
} }
//if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) { //if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) {
if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) { if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) {
@ -807,7 +807,7 @@ class getid3_asf extends getid3_handler
case 'wm/track': case 'wm/track':
if (empty($thisfile_asf_comments['track_number'])) { if (empty($thisfile_asf_comments['track_number'])) {
$thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); $thisfile_asf_comments['track_number'] = array(1 + (int) $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
} }
break; break;

View File

@ -597,7 +597,6 @@ class AMFReader
// null // null
case 6: case 6:
return null; return null;
break;
// Mixed array // Mixed array
case 8: case 8:

View File

@ -112,47 +112,44 @@ class getid3_quicktime extends getid3_handler
if (!empty($info['quicktime']['comments']['location.ISO6709'])) { if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
// https://en.wikipedia.org/wiki/ISO_6709 // https://en.wikipedia.org/wiki/ISO_6709
foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) { foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
$latitude = false; $ISO6709parsed = array('latitude'=>false, 'longitude'=>false, 'altitude'=>false);
$longitude = false;
$altitude = false;
if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) { if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
@list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches; @list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
if (strlen($lat_deg) == 2) { // [+-]DD.D if (strlen($lat_deg) == 2) { // [+-]DD.D
$latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec); $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim($lat_deg, '0').$lat_deg_dec);
} elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M } elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60); $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
} elseif (strlen($lat_deg) == 6) { // [+-]DDMMSS.S } elseif (strlen($lat_deg) == 6) { // [+-]DDMMSS.S
$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600); $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
} }
if (strlen($lon_deg) == 3) { // [+-]DDD.D if (strlen($lon_deg) == 3) { // [+-]DDD.D
$longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec); $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim($lon_deg, '0').$lon_deg_dec);
} elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M } elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60); $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
} elseif (strlen($lon_deg) == 7) { // [+-]DDDMMSS.S } elseif (strlen($lon_deg) == 7) { // [+-]DDDMMSS.S
$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600); $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
} }
if (strlen($alt_deg) == 3) { // [+-]DDD.D if (strlen($alt_deg) == 3) { // [+-]DDD.D
$altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec); $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim($alt_deg, '0').$alt_deg_dec);
} elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M } elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60); $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
} elseif (strlen($alt_deg) == 7) { // [+-]DDDMMSS.S } elseif (strlen($alt_deg) == 7) { // [+-]DDDMMSS.S
$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600); $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
} }
if ($latitude !== false) { foreach (array('latitude', 'longitude', 'altitude') as $key) {
$info['quicktime']['comments']['gps_latitude'][] = (($lat_sign == '-') ? -1 : 1) * floatval($latitude); if ($ISO6709parsed[$key] !== false) {
} $value = (($lat_sign == '-') ? -1 : 1) * floatval($ISO6709parsed[$key]);
if ($longitude !== false) { if (!in_array($value, $info['quicktime']['comments']['gps_'.$key])) {
$info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude); $info['quicktime']['comments']['gps_'.$key][] = (($lat_sign == '-') ? -1 : 1) * floatval($ISO6709parsed[$key]);
}
if ($altitude !== false) {
$info['quicktime']['comments']['gps_altitude'][] = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
} }
} }
if ($latitude === false) { }
}
if ($ISO6709parsed['latitude'] === false) {
$this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug'); $this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
} }
break; break;
@ -224,6 +221,7 @@ class getid3_quicktime extends getid3_handler
$atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717 $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717
array_push($atomHierarchy, $atomname); array_push($atomHierarchy, $atomname);
$atom_structure = array();
$atom_structure['hierarchy'] = implode(' ', $atomHierarchy); $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
$atom_structure['name'] = $atomname; $atom_structure['name'] = $atomname;
$atom_structure['size'] = $atomsize; $atom_structure['size'] = $atomsize;
@ -244,6 +242,7 @@ class getid3_quicktime extends getid3_handler
case 'mdia': // MeDIA container atom case 'mdia': // MeDIA container atom
case 'minf': // Media INFormation container atom case 'minf': // Media INFormation container atom
case 'dinf': // Data INFormation container atom case 'dinf': // Data INFormation container atom
case 'nmhd': // Null Media HeaDer container atom
case 'udta': // User DaTA container atom case 'udta': // User DaTA container atom
case 'cmov': // Compressed MOVie container atom case 'cmov': // Compressed MOVie container atom
case 'rmra': // Reference Movie Record Atom case 'rmra': // Reference Movie Record Atom
@ -1044,6 +1043,7 @@ class getid3_quicktime extends getid3_handler
case 'stco': // Sample Table Chunk Offset atom case 'stco': // Sample Table Chunk Offset atom
// if (true) {
if ($ParseAllPossibleAtoms) { if ($ParseAllPossibleAtoms) {
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000
@ -1639,6 +1639,124 @@ class getid3_quicktime extends getid3_handler
} }
break; break;
case 'uuid': // Atom holding 360fly spatial data??
/* code in this block by Paul Lewis 2019-Oct-31 */
/* Sensor Timestamps need to be calculated using the recordings base time at ['quicktime']['moov']['subatoms'][0]['creation_time_unix']. */
$atom_structure['title'] = '360Fly Sensor Data';
//Get the UUID ID in first 16 bytes
$uuid_bytes_read = unpack('H8time_low/H4time_mid/H4time_hi/H4clock_seq_hi/H12clock_seq_low', substr($atom_data, 0, 16));
$atom_structure['uuid_field_id'] = print_r(implode('-', $uuid_bytes_read), true);
//Get the UUID HEADER data
$uuid_bytes_read = unpack('Sheader_size/Sheader_version/Stimescale/Shardware_version/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/', substr($atom_data, 16, 32));
$atom_structure['uuid_header'] = json_encode($uuid_bytes_read, true);
$start_byte = 48;
$atom_SENSOR_data = substr($atom_data, $start_byte);
$atom_structure['sensor_data']['data_type'] = array(
'fusion_count' => 0, // ID 250
'fusion_data' => array(),
'accel_count' => 0, // ID 1
'accel_data' => array(),
'gyro_count' => 0, // ID 2
'gyro_data' => array(),
'magno_count' => 0, // ID 3
'magno_data' => array(),
'gps_count' => 0, // ID 5
'gps_data' => array(),
'rotation_count' => 0, // ID 6
'rotation_data' => array(),
'unknown_count' => 0, // ID ??
'unknown_data' => array(),
'debug_list' => '', // Used to debug variables stored as comma delimited strings
);
$debug_structure['debug_items'] = array();
// Can start loop here to decode all sensor data in 32 Byte chunks:
foreach (str_split($atom_SENSOR_data, 32) as $sensor_key => $sensor_data) {
// This gets me a data_type code to work out what data is in the next 31 bytes.
$sensor_data_type = substr($sensor_data, 0, 1);
$sensor_data_content = substr($sensor_data, 1);
$uuid_bytes_read = unpack('C*', $sensor_data_type);
$sensor_data_array = array();
switch ($uuid_bytes_read[1]) {
case 250:
$atom_structure['sensor_data']['data_type']['fusion_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['yaw'] = $uuid_bytes_read['yaw'];
$sensor_data_array['pitch'] = $uuid_bytes_read['pitch'];
$sensor_data_array['roll'] = $uuid_bytes_read['roll'];
array_push($atom_structure['sensor_data']['data_type']['fusion_data'], $sensor_data_array);
break;
case 1:
$atom_structure['sensor_data']['data_type']['accel_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['yaw'] = $uuid_bytes_read['yaw'];
$sensor_data_array['pitch'] = $uuid_bytes_read['pitch'];
$sensor_data_array['roll'] = $uuid_bytes_read['roll'];
array_push($atom_structure['sensor_data']['data_type']['accel_data'], $sensor_data_array);
break;
case 2:
$atom_structure['sensor_data']['data_type']['gyro_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['yaw'] = $uuid_bytes_read['yaw'];
$sensor_data_array['pitch'] = $uuid_bytes_read['pitch'];
$sensor_data_array['roll'] = $uuid_bytes_read['roll'];
array_push($atom_structure['sensor_data']['data_type']['gyro_data'], $sensor_data_array);
break;
case 3:
$atom_structure['sensor_data']['data_type']['magno_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Gmagx/Gmagy/Gmagz/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['magx'] = $uuid_bytes_read['magx'];
$sensor_data_array['magy'] = $uuid_bytes_read['magy'];
$sensor_data_array['magz'] = $uuid_bytes_read['magz'];
array_push($atom_structure['sensor_data']['data_type']['magno_data'], $sensor_data_array);
break;
case 5:
$atom_structure['sensor_data']['data_type']['gps_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Glat/Glon/Galt/Gspeed/nbearing/nacc/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['lat'] = $uuid_bytes_read['lat'];
$sensor_data_array['lon'] = $uuid_bytes_read['lon'];
$sensor_data_array['alt'] = $uuid_bytes_read['alt'];
$sensor_data_array['speed'] = $uuid_bytes_read['speed'];
$sensor_data_array['bearing'] = $uuid_bytes_read['bearing'];
$sensor_data_array['acc'] = $uuid_bytes_read['acc'];
//$sensor_data_array = print_r($uuid_bytes_read, true);
array_push($atom_structure['sensor_data']['data_type']['gps_data'], $sensor_data_array);
//array_push($debug_structure['debug_items'], $uuid_bytes_read['timestamp']);
break;
case 6:
$atom_structure['sensor_data']['data_type']['rotation_count']++;
$uuid_bytes_read = unpack('cmode/Jtimestamp/Grotx/Groty/Grotz/x*', $sensor_data_content);
$sensor_data_array['mode'] = $uuid_bytes_read['mode'];
$sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
$sensor_data_array['rotx'] = $uuid_bytes_read['rotx'];
$sensor_data_array['roty'] = $uuid_bytes_read['roty'];
$sensor_data_array['rotz'] = $uuid_bytes_read['rotz'];
array_push($atom_structure['sensor_data']['data_type']['rotation_data'], $sensor_data_array);
break;
default:
$atom_structure['sensor_data']['data_type']['unknown_count']++;
break;
}
}
// if (isset($debug_structure['debug_items']) && count($debug_structure['debug_items']) > 0) {
// $atom_structure['sensor_data']['data_type']['debug_list'] = implode(',', $debug_structure['debug_items']);
// } else {
$atom_structure['sensor_data']['data_type']['debug_list'] = 'No debug items in list!';
// }
break;
case 'gps ': case 'gps ':
// https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730 // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
// The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data. // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
@ -1683,22 +1801,24 @@ class getid3_quicktime extends getid3_handler
// $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) { if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
$GPS_this_GPRMC = array(); $GPS_this_GPRMC = array();
$GPS_this_GPRMC_raw = array();
list( list(
$GPS_this_GPRMC['raw']['gprmc'], $GPS_this_GPRMC_raw['gprmc'],
$GPS_this_GPRMC['raw']['timestamp'], $GPS_this_GPRMC_raw['timestamp'],
$GPS_this_GPRMC['raw']['status'], $GPS_this_GPRMC_raw['status'],
$GPS_this_GPRMC['raw']['latitude'], $GPS_this_GPRMC_raw['latitude'],
$GPS_this_GPRMC['raw']['latitude_direction'], $GPS_this_GPRMC_raw['latitude_direction'],
$GPS_this_GPRMC['raw']['longitude'], $GPS_this_GPRMC_raw['longitude'],
$GPS_this_GPRMC['raw']['longitude_direction'], $GPS_this_GPRMC_raw['longitude_direction'],
$GPS_this_GPRMC['raw']['knots'], $GPS_this_GPRMC_raw['knots'],
$GPS_this_GPRMC['raw']['angle'], $GPS_this_GPRMC_raw['angle'],
$GPS_this_GPRMC['raw']['datestamp'], $GPS_this_GPRMC_raw['datestamp'],
$GPS_this_GPRMC['raw']['variation'], $GPS_this_GPRMC_raw['variation'],
$GPS_this_GPRMC['raw']['variation_direction'], $GPS_this_GPRMC_raw['variation_direction'],
$dummy, $dummy,
$GPS_this_GPRMC['raw']['checksum'], $GPS_this_GPRMC_raw['checksum'],
) = $matches; ) = $matches;
$GPS_this_GPRMC['raw'] = $GPS_this_GPRMC_raw;
$hour = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2); $hour = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
$minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2); $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
@ -1706,7 +1826,7 @@ class getid3_quicktime extends getid3_handler
$ms = substr($GPS_this_GPRMC['raw']['timestamp'], 6); // may contain decimal seconds $ms = substr($GPS_this_GPRMC['raw']['timestamp'], 6); // may contain decimal seconds
$day = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2); $day = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
$month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2); $month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
$year = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2); $year = (int) substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
$year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
$GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms; $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
@ -2740,6 +2860,10 @@ class getid3_quicktime extends getid3_handler
$gooddata = explode(';', $data); $gooddata = explode(';', $data);
} }
foreach ($gooddata as $data) { foreach ($gooddata as $data) {
if (is_array($data) || (!empty($info['quicktime']['comments'][$comment_key]) && in_array($data, $info['quicktime']['comments'][$comment_key]))) {
// avoid duplicate copies of identical data
continue;
}
$info['quicktime']['comments'][$comment_key][] = $data; $info['quicktime']['comments'][$comment_key][] = $data;
} }
} }

View File

@ -203,7 +203,7 @@ class getid3_riff extends getid3_handler
unset($thisfile_riff_audio[$streamindex]['raw']); unset($thisfile_riff_audio[$streamindex]['raw']);
$thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex]; $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
$thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]); $thisfile_audio = (array) getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') { if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
$this->warning('Audio codec = '.$thisfile_audio['codec']); $this->warning('Audio codec = '.$thisfile_audio['codec']);
} }

View File

@ -485,7 +485,7 @@ class getid3_ac3 extends getid3_handler
/** /**
* @param int $length * @param int $length
* *
* @return float|int * @return int
*/ */
private function readHeaderBSI($length) { private function readHeaderBSI($length) {
$data = substr($this->AC3header['bsi'], $this->BSIoffset, $length); $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);

View File

@ -149,7 +149,7 @@ class getid3_dts extends getid3_handler
* @param string $bin * @param string $bin
* @param int $length * @param int $length
* *
* @return float|int * @return int
*/ */
private function readBinData($bin, $length) { private function readBinData($bin, $length) {
$data = substr($bin, $this->readBinDataOffset, $length); $data = substr($bin, $this->readBinDataOffset, $length);
@ -252,36 +252,28 @@ class getid3_dts extends getid3_handler
switch ($index) { switch ($index) {
case 0: case 0:
return 1; return 1;
break;
case 1: case 1:
case 2: case 2:
case 3: case 3:
case 4: case 4:
return 2; return 2;
break;
case 5: case 5:
case 6: case 6:
return 3; return 3;
break;
case 7: case 7:
case 8: case 8:
return 4; return 4;
break;
case 9: case 9:
return 5; return 5;
break;
case 10: case 10:
case 11: case 11:
case 12: case 12:
return 6; return 6;
break;
case 13: case 13:
return 7; return 7;
break;
case 14: case 14:
case 15: case 15:
return 8; return 8;
break;
} }
return false; return false;
} }
@ -323,10 +315,8 @@ class getid3_dts extends getid3_handler
switch ($version) { switch ($version) {
case 7: case 7:
return 0 - $index; return 0 - $index;
break;
case 6: case 6:
return 0 - 16 - $index; return 0 - 16 - $index;
break;
} }
return false; return false;
} }

View File

@ -719,8 +719,17 @@ class getid3_mp3 extends getid3_handler
$thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20); $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20);
$thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9); $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9);
$thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']);
if (preg_match('#^LAME([0-9\\.a-z]+)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) {
$thisfile_mpeg_audio_lame['short_version'] = $matches[0];
$thisfile_mpeg_audio_lame['numeric_version'] = $matches[1];
}
foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) {
$thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number);
}
if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
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
// extra 11 chars are not part of version string when LAMEtag present // extra 11 chars are not part of version string when LAMEtag present
unset($thisfile_mpeg_audio_lame['long_version']); unset($thisfile_mpeg_audio_lame['long_version']);
@ -1324,12 +1333,12 @@ class getid3_mp3 extends getid3_handler
if ($MPEGaudioHeaderValidCache[$next4]) { if ($MPEGaudioHeaderValidCache[$next4]) {
$this->fseek(-4, SEEK_CUR); $this->fseek(-4, SEEK_CUR);
getid3_lib::safe_inc($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]); $Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]] = isset($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]) ? ++$Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]] : 1;
getid3_lib::safe_inc($Distribution['layer'][$LongMPEGlayerLookup[$head4]]); $Distribution['layer'][$LongMPEGlayerLookup[$head4]] = isset($Distribution['layer'][$LongMPEGlayerLookup[$head4]]) ? ++$Distribution['layer'][$LongMPEGlayerLookup[$head4]] : 1;
getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]); $Distribution['version'][$LongMPEGversionLookup[$head4]] = isset($Distribution['version'][$LongMPEGversionLookup[$head4]]) ? ++$Distribution['version'][$LongMPEGversionLookup[$head4]] : 1;
getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]); $Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1;
getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]); $Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1;
if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) { if (++$frames_scanned >= $max_frames_scan) {
$pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']); $pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
$this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.'); $this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
foreach ($Distribution as $key1 => $value1) { foreach ($Distribution as $key1 => $value1) {

View File

@ -615,7 +615,6 @@ class getid3_ogg extends getid3_handler
default: default:
return false; return false;
break;
} }
$VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4)); $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));

View File

@ -3723,12 +3723,10 @@ class getid3_id3v2 extends getid3_handler
switch ($id3v2majorversion) { switch ($id3v2majorversion) {
case 2: case 2:
return preg_match('#[A-Z][A-Z0-9]{2}#', $framename); return preg_match('#[A-Z][A-Z0-9]{2}#', $framename);
break;
case 3: case 3:
case 4: case 4:
return preg_match('#[A-Z][A-Z0-9]{3}#', $framename); return preg_match('#[A-Z][A-Z0-9]{3}#', $framename);
break;
} }
return false; return false;
} }

View File

@ -32,7 +32,7 @@ class getid3_lyrics3 extends getid3_handler
$this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] $this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size]
$lyrics3_id3v1 = $this->fread(128 + 9 + 6); $lyrics3_id3v1 = $this->fread(128 + 9 + 6);
$lyrics3lsz = substr($lyrics3_id3v1, 0, 6); // Lyrics3size $lyrics3lsz = (int) substr($lyrics3_id3v1, 0, 6); // Lyrics3size
$lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200
$id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1 $id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1
@ -240,7 +240,6 @@ class getid3_lyrics3 extends getid3_handler
default: default:
$this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)'); $this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)');
return false; return false;
break;
} }