External Libraries: Update getID3 to version 1.9.23.

The latest version includes numerous bug fixes, a few new features, as well as various improvements for PHP 8.1 and PHP 8.2 support.

This commit also includes PHPCS adjustments previously made for a passing PHP Compatibility scan.

References:
* [https://github.com/JamesHeinrich/getID3/releases/tag/v1.9.23 getID3 1.9.23 release notes]
* [https://github.com/JamesHeinrich/getID3/compare/v1.9.22...v1.9.23 Full list of changes in getID3 1.9.23]

Follow-up to [47601], [48278], [52254], [54376].

Props jrf.
Fixes #59683.
Built from https://develop.svn.wordpress.org/trunk@56975


git-svn-id: http://core.svn.wordpress.org/trunk@56486 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Sergey Biryukov 2023-10-20 13:29:27 +00:00
parent bbe67a0147
commit 6fae0d706a
15 changed files with 196 additions and 121 deletions

View File

@ -121,12 +121,24 @@ class getid3_lib
} }
} }
// if integers are 64-bit - no other check required // if integers are 64-bit - no other check required
if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) { // phpcs:ignore PHPCompatibility.Constants.NewConstants.php_int_minFound if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
return true; return true;
} }
return false; return false;
} }
/**
* Perform a division, guarding against division by zero
*
* @param float|int $numerator
* @param float|int $denominator
* @param float|int $fallback
* @return float|int
*/
public static function SafeDiv($numerator, $denominator, $fallback = 0) {
return $denominator ? $numerator / $denominator : $fallback;
}
/** /**
* @param string $fraction * @param string $fraction
* *
@ -134,7 +146,7 @@ class getid3_lib
*/ */
public static function DecimalizeFraction($fraction) { public static function DecimalizeFraction($fraction) {
list($numerator, $denominator) = explode('/', $fraction); list($numerator, $denominator) = explode('/', $fraction);
return $numerator / ($denominator ? $denominator : 1); return (int) $numerator / ($denominator ? $denominator : 1);
} }
/** /**
@ -871,10 +883,6 @@ class getid3_lib
* @return string * @return string
*/ */
public static function iconv_fallback_iso88591_utf8($string, $bom=false) { public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
if (function_exists('utf8_encode')) {
return utf8_encode($string);
}
// utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
$newcharstring = ''; $newcharstring = '';
if ($bom) { if ($bom) {
$newcharstring .= "\xEF\xBB\xBF"; $newcharstring .= "\xEF\xBB\xBF";
@ -943,10 +951,6 @@ class getid3_lib
* @return string * @return string
*/ */
public static function iconv_fallback_utf8_iso88591($string) { public static function iconv_fallback_utf8_iso88591($string) {
if (function_exists('utf8_decode')) {
return utf8_decode($string);
}
// utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
$newcharstring = ''; $newcharstring = '';
$offset = 0; $offset = 0;
$stringlength = strlen($string); $stringlength = strlen($string);

View File

@ -387,7 +387,7 @@ class getID3
*/ */
protected $startup_warning = ''; protected $startup_warning = '';
const VERSION = '1.9.22-202207161647'; const VERSION = '1.9.23-202310190849';
const FREAD_BUFFER_SIZE = 32768; const FREAD_BUFFER_SIZE = 32768;
const ATTACHMENTS_NONE = false; const ATTACHMENTS_NONE = false;
@ -438,19 +438,19 @@ class getID3
$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";
} }
// check for magic quotes in PHP < 7.4.0 (when these functions became deprecated) // check for magic quotes in PHP < 5.4.0 (when these options were removed and getters always return false)
if (version_compare(PHP_VERSION, '7.4.0', '<')) { if (version_compare(PHP_VERSION, '5.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')) {
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_runtimeDeprecated // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_runtimeDeprecated
if (get_magic_quotes_runtime()) { if (get_magic_quotes_runtime()) { // @phpstan-ignore-line
$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('get_magic_quotes_gpc')) { if (function_exists('get_magic_quotes_gpc')) {
// phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.get_magic_quotes_gpcDeprecated
if (get_magic_quotes_gpc()) { if (get_magic_quotes_gpc()) { // @phpstan-ignore-line
$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";
} }
} }
@ -1468,6 +1468,16 @@ class getID3
'fail_ape' => 'ERROR', 'fail_ape' => 'ERROR',
), ),
// XZ - data - XZ compressed data
'7zip' => array(
'pattern' => '^7z\\xBC\\xAF\\x27\\x1C',
'group' => 'archive',
'module' => '7zip',
'mime_type' => 'application/x-7z-compressed',
'fail_id3' => 'ERROR',
'fail_ape' => 'ERROR',
),
// Misc other formats // Misc other formats
@ -1982,7 +1992,7 @@ class getID3
} }
$BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate; $BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
$this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed; $this->info['video']['compression_ratio'] = getid3_lib::SafeDiv($BitrateCompressed, $BitrateUncompressed, 1);
return true; return true;
} }
@ -2188,6 +2198,8 @@ abstract class getid3_handler
} }
/** /**
* @phpstan-impure
*
* @return int|bool * @return int|bool
*/ */
protected function ftell() { protected function ftell() {
@ -2200,6 +2212,8 @@ abstract class getid3_handler
/** /**
* @param int $bytes * @param int $bytes
* *
* @phpstan-impure
*
* @return string|false * @return string|false
* *
* @throws getid3_exception * @throws getid3_exception
@ -2245,6 +2259,8 @@ abstract class getid3_handler
* @param int $bytes * @param int $bytes
* @param int $whence * @param int $whence
* *
* @phpstan-impure
*
* @return int * @return int
* *
* @throws getid3_exception * @throws getid3_exception
@ -2286,6 +2302,8 @@ abstract class getid3_handler
} }
/** /**
* @phpstan-impure
*
* @return string|false * @return string|false
* *
* @throws getid3_exception * @throws getid3_exception
@ -2341,6 +2359,8 @@ abstract class getid3_handler
} }
/** /**
* @phpstan-impure
*
* @return bool * @return bool
*/ */
protected function feof() { protected function feof() {

View File

@ -1,27 +0,0 @@
getID3() Commercial License
===========================
getID3() is licensed under the "GNU Public License" (GPL) and/or the
"getID3() Commercial License" (gCL). This document describes the gCL.
---------------------------------------------------------------------
The license is non-exclusively granted to a single person or company,
per payment of the license fee, for the lifetime of that person or
company. The license is non-transferrable.
The gCL grants the licensee the right to use getID3() in commercial
closed-source projects. Modifications may be made to getID3() with no
obligation to release the modified source code. getID3() (or pieces
thereof) may be included in any number of projects authored (in whole
or in part) by the licensee.
The licensee may use any version of getID3(), past, present or future,
as is most convenient. This license does not entitle the licensee to
receive any technical support, updates or bugfixes, except as such are
made publicly available to all getID3() users.
The licensee may not sub-license getID3() itself, meaning that any
commercially released product containing all or parts of getID3() must
have added functionality beyond what is available in getID3();
getID3() itself may not be re-licensed by the licensee.

View File

@ -20,7 +20,8 @@ GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2) Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2)
getID3 Commercial License: https://www.getid3.org/#gCL (payment required) getID3 Commercial License: https://www.getid3.org/#gCL
(no longer available, existing licenses remain valid)
***************************************************************** *****************************************************************
***************************************************************** *****************************************************************

View File

@ -193,7 +193,7 @@ class getid3_asf extends getid3_handler
$info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000); $info['playtime_seconds'] = ($thisfile_asf_filepropertiesobject['play_duration'] / 10000000) - ($thisfile_asf_filepropertiesobject['preroll'] / 1000);
//$info['bitrate'] = $thisfile_asf_filepropertiesobject['max_bitrate']; //$info['bitrate'] = $thisfile_asf_filepropertiesobject['max_bitrate'];
$info['bitrate'] = ((isset($thisfile_asf_filepropertiesobject['filesize']) ? $thisfile_asf_filepropertiesobject['filesize'] : $info['filesize']) * 8) / $info['playtime_seconds']; $info['bitrate'] = getid3_lib::SafeDiv($thisfile_asf_filepropertiesobject['filesize'] * 8, $info['playtime_seconds']);
} }
break; break;
@ -1066,7 +1066,7 @@ class getid3_asf extends getid3_handler
break; break;
} }
if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { // @phpstan-ignore-line
foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
$thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate']; $thisfile_asf_audiomedia_currentstream['bitrate'] = $dataarray['bitrate'];
@ -1152,7 +1152,7 @@ class getid3_asf extends getid3_handler
$videomediaoffset += 4; $videomediaoffset += 4;
$thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'], $videomediaoffset); $thisfile_asf_videomedia_currentstream['format_data']['codec_data'] = substr($streamdata['type_specific_data'], $videomediaoffset);
if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { if (!empty($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'])) { // @phpstan-ignore-line
foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) { foreach ($thisfile_asf['stream_bitrate_properties_object']['bitrate_records'] as $dummy => $dataarray) {
if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) { if (isset($dataarray['flags']['stream_number']) && ($dataarray['flags']['stream_number'] == $streamnumber)) {
$thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate']; $thisfile_asf_videomedia_currentstream['bitrate'] = $dataarray['bitrate'];

View File

@ -292,12 +292,12 @@ class getid3_matroska extends getid3_handler
$track_info['display_x'] = (isset($trackarray['DisplayWidth']) ? $trackarray['DisplayWidth'] : $trackarray['PixelWidth']); $track_info['display_x'] = (isset($trackarray['DisplayWidth']) ? $trackarray['DisplayWidth'] : $trackarray['PixelWidth']);
$track_info['display_y'] = (isset($trackarray['DisplayHeight']) ? $trackarray['DisplayHeight'] : $trackarray['PixelHeight']); $track_info['display_y'] = (isset($trackarray['DisplayHeight']) ? $trackarray['DisplayHeight'] : $trackarray['PixelHeight']);
if (isset($trackarray['PixelCropBottom'])) { $track_info['crop_bottom'] = $trackarray['PixelCropBottom']; } if (isset($trackarray['PixelCropBottom'])) { $track_info['crop_bottom'] = $trackarray['PixelCropBottom']; }
if (isset($trackarray['PixelCropTop'])) { $track_info['crop_top'] = $trackarray['PixelCropTop']; } if (isset($trackarray['PixelCropTop'])) { $track_info['crop_top'] = $trackarray['PixelCropTop']; }
if (isset($trackarray['PixelCropLeft'])) { $track_info['crop_left'] = $trackarray['PixelCropLeft']; } if (isset($trackarray['PixelCropLeft'])) { $track_info['crop_left'] = $trackarray['PixelCropLeft']; }
if (isset($trackarray['PixelCropRight'])) { $track_info['crop_right'] = $trackarray['PixelCropRight']; } if (isset($trackarray['PixelCropRight'])) { $track_info['crop_right'] = $trackarray['PixelCropRight']; }
if (isset($trackarray['DefaultDuration'])) { $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3); } if (!empty($trackarray['DefaultDuration'])) { $track_info['frame_rate'] = round(1000000000 / $trackarray['DefaultDuration'], 3); }
if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; } if (isset($trackarray['CodecName'])) { $track_info['codec'] = $trackarray['CodecName']; }
switch ($trackarray['CodecID']) { switch ($trackarray['CodecID']) {
case 'V_MS/VFW/FOURCC': case 'V_MS/VFW/FOURCC':

View File

@ -152,7 +152,7 @@ class getid3_quicktime extends getid3_handler
} elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M } elseif (strlen($lat_deg) == 4) { // [+-]DDMM.M
$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); $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
$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); $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval((int) 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
@ -160,7 +160,7 @@ class getid3_quicktime extends getid3_handler
} elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M } elseif (strlen($lon_deg) == 5) { // [+-]DDDMM.M
$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); $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
$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); $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval((int) 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
@ -168,7 +168,7 @@ class getid3_quicktime extends getid3_handler
} elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M } elseif (strlen($alt_deg) == 5) { // [+-]DDDMM.M
$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); $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
$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); $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval((int) ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
} }
foreach (array('latitude', 'longitude', 'altitude') as $key) { foreach (array('latitude', 'longitude', 'altitude') as $key) {
@ -332,7 +332,7 @@ class getid3_quicktime extends getid3_handler
} }
} elseif (isset($value_array['time_to_sample_table'])) { } elseif (isset($value_array['time_to_sample_table'])) {
foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0) && !empty($info['quicktime']['time_scale'])) {
$framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
$framecount = $value_array2['sample_count']; $framecount = $value_array2['sample_count'];
} }
@ -776,8 +776,8 @@ class getid3_quicktime extends getid3_handler
case 'stsd': // Sample Table Sample Description atom case 'stsd': // Sample Table Sample Description atom
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); // hardcoded: 0x00
$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: 0x000000
$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4));
// see: https://github.com/JamesHeinrich/getID3/issues/111 // see: https://github.com/JamesHeinrich/getID3/issues/111
@ -805,7 +805,6 @@ class getid3_quicktime extends getid3_handler
$stsdEntriesDataOffset += 2; $stsdEntriesDataOffset += 2;
$atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2)); $atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
$stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2); $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
if (substr($atom_structure['sample_description_table'][$i]['data'], 1, 54) == 'application/octet-stream;type=com.parrot.videometadata') { if (substr($atom_structure['sample_description_table'][$i]['data'], 1, 54) == 'application/octet-stream;type=com.parrot.videometadata') {
// special handling for apparently-malformed (TextMetaDataSampleEntry?) data for some version of Parrot drones // special handling for apparently-malformed (TextMetaDataSampleEntry?) data for some version of Parrot drones
$atom_structure['sample_description_table'][$i]['parrot_frame_metadata']['mime_type'] = substr($atom_structure['sample_description_table'][$i]['data'], 1, 55); $atom_structure['sample_description_table'][$i]['parrot_frame_metadata']['mime_type'] = substr($atom_structure['sample_description_table'][$i]['data'], 1, 55);
@ -893,7 +892,8 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
break; break;
case 'mp4a': case 'mp4a':
default: $atom_structure['sample_description_table'][$i]['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_structure['sample_description_table'][$i]['data'], 20), $baseoffset + $stsdEntriesDataOffset - 20 - 16, $atomHierarchy, $ParseAllPossibleAtoms);
$info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
$info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
$info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels'];
@ -919,6 +919,9 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
break; break;
} }
break; break;
default:
break;
} }
break; break;
@ -1666,7 +1669,7 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
); );
$atom_structure['data'] = $atom_data; $atom_structure['data'] = $atom_data;
$atom_structure['image_mime'] = 'image/jpeg'; $atom_structure['image_mime'] = 'image/jpeg';
$atom_structure['description'] = isset($descriptions[$atomname]) ? $descriptions[$atomname] : 'Nikon preview image'; $atom_structure['description'] = $descriptions[$atomname];
$info['quicktime']['comments']['picture'][] = array( $info['quicktime']['comments']['picture'][] = array(
'image_mime' => $atom_structure['image_mime'], 'image_mime' => $atom_structure['image_mime'],
'data' => $atom_data, 'data' => $atom_data,
@ -1683,7 +1686,7 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
case 'NCHD': // Nikon:MakerNoteVersion - https://exiftool.org/TagNames/Nikon.html case 'NCHD': // Nikon:MakerNoteVersion - https://exiftool.org/TagNames/Nikon.html
$makerNoteVersion = ''; $makerNoteVersion = '';
for ($i = 0, $iMax = strlen($atom_data); $i < $iMax; ++$i) { for ($i = 0, $iMax = strlen($atom_data); $i < $iMax; ++$i) {
if (ord($atom_data[$i]) >= 0x00 && ord($atom_data[$i]) <= 0x1F) { if (ord($atom_data[$i]) <= 0x1F) {
$makerNoteVersion .= ' '.ord($atom_data[$i]); $makerNoteVersion .= ' '.ord($atom_data[$i]);
} else { } else {
$makerNoteVersion .= $atom_data[$i]; $makerNoteVersion .= $atom_data[$i];
@ -2101,6 +2104,97 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
break; break;
case 'esds': // Elementary Stream DeScriptor
// https://github.com/JamesHeinrich/getID3/issues/414
// https://chromium.googlesource.com/chromium/src/media/+/refs/heads/main/formats/mp4/es_descriptor.cc
// https://chromium.googlesource.com/chromium/src/media/+/refs/heads/main/formats/mp4/es_descriptor.h
$atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); // hardcoded: 0x00
$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x000000
$esds_offset = 4;
$atom_structure['ES_DescrTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
if ($atom_structure['ES_DescrTag'] != 0x03) {
$this->warning('expecting esds.ES_DescrTag = 0x03, found 0x'.getid3_lib::PrintHexBytes($atom_structure['ES_DescrTag']).'), at offset '.$atom_structure['offset']);
break;
}
$atom_structure['ES_DescrSize'] = $this->quicktime_read_mp4_descr_length($atom_data, $esds_offset);
$atom_structure['ES_ID'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 2));
$esds_offset += 2;
$atom_structure['ES_flagsraw'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
$atom_structure['ES_flags']['stream_dependency'] = (bool) ($atom_structure['ES_flagsraw'] & 0x80);
$atom_structure['ES_flags']['url_flag'] = (bool) ($atom_structure['ES_flagsraw'] & 0x40);
$atom_structure['ES_flags']['ocr_stream'] = (bool) ($atom_structure['ES_flagsraw'] & 0x20);
$atom_structure['ES_stream_priority'] = ($atom_structure['ES_flagsraw'] & 0x1F);
if ($atom_structure['ES_flags']['url_flag']) {
$this->warning('Unsupported esds.url_flag enabled at offset '.$atom_structure['offset']);
break;
}
if ($atom_structure['ES_flags']['stream_dependency']) {
$atom_structure['ES_dependsOn_ES_ID'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 2));
$esds_offset += 2;
}
if ($atom_structure['ES_flags']['ocr_stream']) {
$atom_structure['ES_OCR_ES_Id'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 2));
$esds_offset += 2;
}
$atom_structure['ES_DecoderConfigDescrTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
if ($atom_structure['ES_DecoderConfigDescrTag'] != 0x04) {
$this->warning('expecting esds.ES_DecoderConfigDescrTag = 0x04, found 0x'.getid3_lib::PrintHexBytes($atom_structure['ES_DecoderConfigDescrTag']).'), at offset '.$atom_structure['offset']);
break;
}
$atom_structure['ES_DecoderConfigDescrTagSize'] = $this->quicktime_read_mp4_descr_length($atom_data, $esds_offset);
$atom_structure['ES_objectTypeIndication'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
// https://stackoverflow.com/questions/3987850
// 0x40 = "Audio ISO/IEC 14496-3" = MPEG-4 Audio
// 0x67 = "Audio ISO/IEC 13818-7 LowComplexity Profile" = MPEG-2 AAC LC
// 0x69 = "Audio ISO/IEC 13818-3" = MPEG-2 Backward Compatible Audio (MPEG-2 Layers 1, 2, and 3)
// 0x6B = "Audio ISO/IEC 11172-3" = MPEG-1 Audio (MPEG-1 Layers 1, 2, and 3)
$streamTypePlusFlags = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
$atom_structure['ES_streamType'] = ($streamTypePlusFlags & 0xFC) >> 2;
$atom_structure['ES_upStream'] = (bool) ($streamTypePlusFlags & 0x02) >> 1;
$atom_structure['ES_bufferSizeDB'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 3));
$esds_offset += 3;
$atom_structure['ES_maxBitrate'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 4));
$esds_offset += 4;
$atom_structure['ES_avgBitrate'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 4));
$esds_offset += 4;
if ($atom_structure['ES_avgBitrate']) {
$info['quicktime']['audio']['bitrate'] = $atom_structure['ES_avgBitrate'];
$info['audio']['bitrate'] = $atom_structure['ES_avgBitrate'];
}
$atom_structure['ES_DecSpecificInfoTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
if ($atom_structure['ES_DecSpecificInfoTag'] != 0x05) {
$this->warning('expecting esds.ES_DecSpecificInfoTag = 0x05, found 0x'.getid3_lib::PrintHexBytes($atom_structure['ES_DecSpecificInfoTag']).'), at offset '.$atom_structure['offset']);
break;
}
$atom_structure['ES_DecSpecificInfoTagSize'] = $this->quicktime_read_mp4_descr_length($atom_data, $esds_offset);
$atom_structure['ES_DecSpecificInfo'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, $atom_structure['ES_DecSpecificInfoTagSize']));
$esds_offset += $atom_structure['ES_DecSpecificInfoTagSize'];
$atom_structure['ES_SLConfigDescrTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, 1));
$esds_offset += 1;
if ($atom_structure['ES_SLConfigDescrTag'] != 0x06) {
$this->warning('expecting esds.ES_SLConfigDescrTag = 0x05, found 0x'.getid3_lib::PrintHexBytes($atom_structure['ES_SLConfigDescrTag']).'), at offset '.$atom_structure['offset']);
break;
}
$atom_structure['ES_SLConfigDescrTagSize'] = $this->quicktime_read_mp4_descr_length($atom_data, $esds_offset);
$atom_structure['ES_SLConfigDescr'] = getid3_lib::BigEndian2Int(substr($atom_data, $esds_offset, $atom_structure['ES_SLConfigDescrTagSize']));
$esds_offset += $atom_structure['ES_SLConfigDescrTagSize'];
break;
// AVIF-related - https://docs.rs/avif-parse/0.13.2/src/avif_parse/boxes.rs.html // AVIF-related - https://docs.rs/avif-parse/0.13.2/src/avif_parse/boxes.rs.html
case 'pitm': // Primary ITeM case 'pitm': // Primary ITeM
case 'iloc': // Item LOCation case 'iloc': // Item LOCation
@ -2991,6 +3085,7 @@ $this->error('fragmented mp4 files not currently supported');
return array(); return array();
} }
/** /**
* @param array $info * @param array $info
* *

View File

@ -214,7 +214,7 @@ class getid3_riff extends getid3_handler
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV) if (empty($info['playtime_seconds'])) { // may already be set (e.g. DTS-WAV)
$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); $info['playtime_seconds'] = (float)getid3_lib::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $thisfile_audio['bitrate']);
} }
$thisfile_audio['lossless'] = false; $thisfile_audio['lossless'] = false;
@ -440,11 +440,11 @@ class getid3_riff extends getid3_handler
$thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML; $thisfile_riff_WAVE['iXML'][0]['parsed'] = $parsedXML;
if (isset($parsedXML['SPEED']['MASTER_SPEED'])) { if (isset($parsedXML['SPEED']['MASTER_SPEED'])) {
@list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']); @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['MASTER_SPEED']);
$thisfile_riff_WAVE['iXML'][0]['master_speed'] = $numerator / ($denominator ? $denominator : 1000); $thisfile_riff_WAVE['iXML'][0]['master_speed'] = (int) $numerator / ($denominator ? $denominator : 1000);
} }
if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) { if (isset($parsedXML['SPEED']['TIMECODE_RATE'])) {
@list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']); @list($numerator, $denominator) = explode('/', $parsedXML['SPEED']['TIMECODE_RATE']);
$thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = $numerator / ($denominator ? $denominator : 1000); $thisfile_riff_WAVE['iXML'][0]['timecode_rate'] = (int) $numerator / ($denominator ? $denominator : 1000);
} }
if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) { if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
$samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0')); $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
@ -521,7 +521,7 @@ class getid3_riff extends getid3_handler
if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
$info['playtime_seconds'] = (float) ((($info['avdataend'] - $info['avdataoffset']) * 8) / $thisfile_audio['bitrate']); $info['playtime_seconds'] = (float)getid3_lib::SafeDiv((($info['avdataend'] - $info['avdataoffset']) * 8), $thisfile_audio['bitrate']);
} }
if (!empty($info['wavpack'])) { if (!empty($info['wavpack'])) {
@ -531,7 +531,7 @@ class getid3_riff extends getid3_handler
// Reset to the way it was - RIFF parsing will have messed this up // Reset to the way it was - RIFF parsing will have messed this up
$info['avdataend'] = $Original['avdataend']; $info['avdataend'] = $Original['avdataend'];
$thisfile_audio['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; $thisfile_audio['bitrate'] = getid3_lib::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $info['playtime_seconds']);
$this->fseek($info['avdataoffset'] - 44); $this->fseek($info['avdataoffset'] - 44);
$RIFFdata = $this->fread(44); $RIFFdata = $this->fread(44);
@ -632,7 +632,7 @@ class getid3_riff extends getid3_handler
} }
} }
if ($info['avdataend'] > $info['filesize']) { if ($info['avdataend'] > $info['filesize']) {
switch (!empty($thisfile_audio_dataformat) ? $thisfile_audio_dataformat : '') { switch ($thisfile_audio_dataformat) {
case 'wavpack': // WavPack case 'wavpack': // WavPack
case 'lpac': // LPAC case 'lpac': // LPAC
case 'ofr': // OptimFROG case 'ofr': // OptimFROG
@ -672,7 +672,7 @@ class getid3_riff extends getid3_handler
$this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored'); $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
} }
} }
if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) { if ($thisfile_audio_dataformat == 'ac3') {
unset($thisfile_audio['bits_per_sample']); unset($thisfile_audio['bits_per_sample']);
if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) { if (!empty($info['ac3']['bitrate']) && ($info['ac3']['bitrate'] != $thisfile_audio['bitrate'])) {
$thisfile_audio['bitrate'] = $info['ac3']['bitrate']; $thisfile_audio['bitrate'] = $info['ac3']['bitrate'];
@ -781,15 +781,15 @@ class getid3_riff extends getid3_handler
/** @var array $thisfile_riff_video_current */ /** @var array $thisfile_riff_video_current */
$thisfile_riff_video_current = &$thisfile_riff_video[$streamindex]; $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
if ($thisfile_riff_raw_avih['dwWidth'] > 0) { if ($thisfile_riff_raw_avih['dwWidth'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth']; $thisfile_riff_video_current['frame_width'] = $thisfile_riff_raw_avih['dwWidth'];
$thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width']; $thisfile_video['resolution_x'] = $thisfile_riff_video_current['frame_width'];
} }
if ($thisfile_riff_raw_avih['dwHeight'] > 0) { if ($thisfile_riff_raw_avih['dwHeight'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight']; $thisfile_riff_video_current['frame_height'] = $thisfile_riff_raw_avih['dwHeight'];
$thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height']; $thisfile_video['resolution_y'] = $thisfile_riff_video_current['frame_height'];
} }
if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { if ($thisfile_riff_raw_avih['dwTotalFrames'] > 0) { // @phpstan-ignore-line
$thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames']; $thisfile_riff_video_current['total_frames'] = $thisfile_riff_raw_avih['dwTotalFrames'];
$thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames']; $thisfile_video['total_frames'] = $thisfile_riff_video_current['total_frames'];
} }
@ -1913,7 +1913,7 @@ class getid3_riff extends getid3_handler
if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) { if (isset($RIFFchunk[$chunkname][$thisindex]) && empty($RIFFchunk[$chunkname][$thisindex])) {
unset($RIFFchunk[$chunkname][$thisindex]); unset($RIFFchunk[$chunkname][$thisindex]);
} }
if (isset($RIFFchunk[$chunkname]) && empty($RIFFchunk[$chunkname])) { if (count($RIFFchunk[$chunkname]) === 0) {
unset($RIFFchunk[$chunkname]); unset($RIFFchunk[$chunkname]);
} }
$RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize); $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['data'] = $this->fread($chunksize);
@ -2034,7 +2034,7 @@ class getid3_riff extends getid3_handler
foreach ($RIFFinfoKeyLookup as $key => $value) { foreach ($RIFFinfoKeyLookup as $key => $value) {
if (isset($RIFFinfoArray[$key])) { if (isset($RIFFinfoArray[$key])) {
foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) { foreach ($RIFFinfoArray[$key] as $commentid => $commentdata) {
if (trim($commentdata['data']) != '') { if (!empty($commentdata['data']) && trim($commentdata['data']) != '') {
if (isset($CommentsTargetArray[$value])) { if (isset($CommentsTargetArray[$value])) {
$CommentsTargetArray[$value][] = trim($commentdata['data']); $CommentsTargetArray[$value][] = trim($commentdata['data']);
} else { } else {

View File

@ -1380,11 +1380,11 @@ class getid3_mp3 extends getid3_handler
$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1; $Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1;
$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1; $Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1;
if (++$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 = getid3_lib::SafeDiv($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) {
foreach ($value1 as $key2 => $value2) { foreach ($value1 as $key2 => $value2) {
$Distribution[$key1][$key2] = round($value2 / $pct_data_scanned); $Distribution[$key1][$key2] = $pct_data_scanned ? round($value2 / $pct_data_scanned) : 1;
} }
} }
break; break;
@ -1475,7 +1475,7 @@ class getid3_mp3 extends getid3_handler
$SyncSeekAttemptsMax = 1000; $SyncSeekAttemptsMax = 1000;
$FirstFrameThisfileInfo = null; $FirstFrameThisfileInfo = null;
while ($SynchSeekOffset < $sync_seek_buffer_size) { while ($SynchSeekOffset < $sync_seek_buffer_size) {
if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) { if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !$this->feof()) {
if ($SynchSeekOffset > $sync_seek_buffer_size) { if ($SynchSeekOffset > $sync_seek_buffer_size) {
// if a synch's not found within the first 128k bytes, then give up // if a synch's not found within the first 128k bytes, then give up
@ -1490,20 +1490,6 @@ class getid3_mp3 extends getid3_handler
unset($info['mpeg']); unset($info['mpeg']);
} }
return false; return false;
} elseif (feof($this->getid3->fp)) {
$this->error('Could not find valid MPEG audio synch before end of file');
if (isset($info['audio']['bitrate'])) {
unset($info['audio']['bitrate']);
}
if (isset($info['mpeg']['audio'])) {
unset($info['mpeg']['audio']);
}
if (isset($info['mpeg']) && (!is_array($info['mpeg']) || (count($info['mpeg']) == 0))) {
unset($info['mpeg']);
}
return false;
} }
} }
@ -1652,7 +1638,7 @@ class getid3_mp3 extends getid3_handler
} }
$frames_scanned++; $frames_scanned++;
if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) { if ($frames_scan_per_segment && (++$frames_scanned_this_segment >= $frames_scan_per_segment)) {
$this_pct_scanned = ($this->ftell() - $scan_start_offset[$current_segment]) / ($info['avdataend'] - $info['avdataoffset']); $this_pct_scanned = getid3_lib::SafeDiv($this->ftell() - $scan_start_offset[$current_segment], $info['avdataend'] - $info['avdataoffset']);
if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) { if (($current_segment == 0) && (($this_pct_scanned * $max_scan_segments) >= 1)) {
// file likely contains < $max_frames_scan, just scan as one segment // file likely contains < $max_frames_scan, just scan as one segment
$max_scan_segments = 1; $max_scan_segments = 1;
@ -1743,6 +1729,10 @@ class getid3_mp3 extends getid3_handler
} }
$info['audio']['channels'] = $info['mpeg']['audio']['channels']; $info['audio']['channels'] = $info['mpeg']['audio']['channels'];
if ($info['audio']['channels'] < 1) {
$this->error('Corrupt MP3 file: no channels');
return false;
}
$info['audio']['channelmode'] = $info['mpeg']['audio']['channelmode']; $info['audio']['channelmode'] = $info['mpeg']['audio']['channelmode'];
$info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate'];
return true; return true;

View File

@ -210,8 +210,8 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
$filedataoffset += 20; $filedataoffset += 20;
$info['ogg']['skeleton']['fishead']['version'] = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor']; $info['ogg']['skeleton']['fishead']['version'] = $info['ogg']['skeleton']['fishead']['raw']['version_major'].'.'.$info['ogg']['skeleton']['fishead']['raw']['version_minor'];
$info['ogg']['skeleton']['fishead']['presentationtime'] = $info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator']; $info['ogg']['skeleton']['fishead']['presentationtime'] = getid3_lib::SafeDiv($info['ogg']['skeleton']['fishead']['raw']['presentationtime_numerator'], $info['ogg']['skeleton']['fishead']['raw']['presentationtime_denominator']);
$info['ogg']['skeleton']['fishead']['basetime'] = $info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'] / $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator']; $info['ogg']['skeleton']['fishead']['basetime'] = getid3_lib::SafeDiv($info['ogg']['skeleton']['fishead']['raw']['basetime_numerator'], $info['ogg']['skeleton']['fishead']['raw']['basetime_denominator']);
$info['ogg']['skeleton']['fishead']['utc'] = $info['ogg']['skeleton']['fishead']['raw']['utc']; $info['ogg']['skeleton']['fishead']['utc'] = $info['ogg']['skeleton']['fishead']['raw']['utc'];
@ -288,7 +288,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
$info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate']; $info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate'];
$info['audio']['channels'] = $info['flac']['STREAMINFO']['channels']; $info['audio']['channels'] = $info['flac']['STREAMINFO']['channels'];
$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample']; $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
$info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate']; $info['playtime_seconds'] = getid3_lib::SafeDiv($info['flac']['STREAMINFO']['samples_stream'], $info['flac']['STREAMINFO']['sample_rate']);
} }
} else { } else {
@ -359,7 +359,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
return false; return false;
} }
if (!empty($info['audio']['sample_rate'])) { if (!empty($info['audio']['sample_rate'])) {
$info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / ($info['ogg']['samples'] / $info['audio']['sample_rate']); $info['ogg']['bitrate_average'] = (($info['avdataend'] - $info['avdataoffset']) * 8) * $info['audio']['sample_rate'] / $info['ogg']['samples'];
} }
} }
@ -534,12 +534,12 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['
$filedata = $this->fread($this->getid3->fread_buffer_size()); $filedata = $this->fread($this->getid3->fread_buffer_size());
$filedataoffset = 0; $filedataoffset = 0;
while ((substr($filedata, $filedataoffset++, 4) != 'OggS')) { while (substr($filedata, $filedataoffset++, 4) != 'OggS') {
if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) { if (($this->ftell() - $oggheader['page_start_offset']) >= $this->getid3->fread_buffer_size()) {
// should be found before here // should be found before here
return false; return false;
} }
if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) { if (($filedataoffset + 28) > strlen($filedata)) {
if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) { if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) {
// get some more data, unless eof, in which case fail // get some more data, unless eof, in which case fail
return false; return false;

View File

@ -267,7 +267,7 @@ class getid3_apetag extends getid3_handler
case 'cover art (publisher logo)': case 'cover art (publisher logo)':
case 'cover art (recording)': case 'cover art (recording)':
case 'cover art (studio)': case 'cover art (studio)':
// list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html // list of possible cover arts from https://github.com/mono/taglib-sharp/blob/taglib-sharp-2.0.3.2/src/TagLib/Ape/Tag.cs
if (is_array($thisfile_ape_items_current['data'])) { if (is_array($thisfile_ape_items_current['data'])) {
$this->warning('APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8'); $this->warning('APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8');
$thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']); $thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']);
@ -332,7 +332,7 @@ class getid3_apetag extends getid3_handler
$info['ape']['comments']['picture'][] = $comments_picture_data; $info['ape']['comments']['picture'][] = $comments_picture_data;
unset($comments_picture_data); unset($comments_picture_data);
} }
} while (false); } while (false); // @phpstan-ignore-line
break; break;
default: default:

View File

@ -66,7 +66,7 @@ class getid3_id3v1 extends getid3_handler
if (!empty($ParsedID3v1['genre'])) { if (!empty($ParsedID3v1['genre'])) {
unset($ParsedID3v1['genreid']); unset($ParsedID3v1['genreid']);
} }
if (isset($ParsedID3v1['genre']) && (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown'))) { if (empty($ParsedID3v1['genre']) || ($ParsedID3v1['genre'] == 'Unknown')) {
unset($ParsedID3v1['genre']); unset($ParsedID3v1['genre']);
} }

View File

@ -1494,7 +1494,7 @@ class getid3_id3v2 extends getid3_handler
unset($comments_picture_data); unset($comments_picture_data);
} }
} }
} while (false); } while (false); // @phpstan-ignore-line
} }
} elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GEOB')) || // 4.15 GEOB General encapsulated object } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GEOB')) || // 4.15 GEOB General encapsulated object
@ -3753,18 +3753,12 @@ class getid3_id3v2 extends getid3_handler
* @return bool * @return bool
*/ */
public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) { public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
for ($i = 0; $i < strlen($numberstring); $i++) { $pattern = '#^';
if ((chr($numberstring[$i]) < chr('0')) || (chr($numberstring[$i]) > chr('9'))) { $pattern .= ($allownegative ? '\\-?' : '');
if (($numberstring[$i] == '.') && $allowdecimal) { $pattern .= '[0-9]+';
// allowed $pattern .= ($allowdecimal ? '(\\.[0-9]+)?' : '');
} elseif (($numberstring[$i] == '-') && $allownegative && ($i == 0)) { $pattern .= '$#';
// allowed return preg_match($pattern, $numberstring);
} else {
return false;
}
}
}
return true;
} }
/** /**
@ -3773,10 +3767,7 @@ class getid3_id3v2 extends getid3_handler
* @return bool * @return bool
*/ */
public static function IsValidDateStampString($datestamp) { public static function IsValidDateStampString($datestamp) {
if (strlen($datestamp) != 8) { if (!preg_match('#^[12][0-9]{3}[01][0-9][0123][0-9]$#', $datestamp)) {
return false;
}
if (!self::IsANumber($datestamp, false)) {
return false; return false;
} }
$year = substr($datestamp, 0, 4); $year = substr($datestamp, 0, 4);

View File

@ -20,7 +20,8 @@ GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2) Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2)
getID3 Commercial License: https://www.getid3.org/#gCL (payment required) getID3 Commercial License: https://www.getid3.org/#gCL
(no longer available, existing licenses remain valid)
***************************************************************** *****************************************************************
***************************************************************** *****************************************************************

View File

@ -16,7 +16,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '6.5-alpha-56974'; $wp_version = '6.5-alpha-56975';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.