External Libraries: Update getID3 to version `1.9.22`.

This updates the getID3 library from version `1.9.21` to `1.9.22`, which contains a number of bug fixes and improvements to PHP 8.1 support.

A full list of changes can be found on GitHub: https://github.com/JamesHeinrich/getID3/compare/v1.9.21...v1.9.22.

Props jrf, desrosj.
Fixes #56692.
Built from https://develop.svn.wordpress.org/trunk@54376


git-svn-id: http://core.svn.wordpress.org/trunk@53935 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
desrosj 2022-10-04 02:08:11 +00:00
parent aade6aa5f9
commit e63726d593
9 changed files with 277 additions and 44 deletions

View File

@ -11,6 +11,13 @@
// /// // ///
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
if(!defined('GETID3_LIBXML_OPTIONS') && defined('LIBXML_VERSION')) {
if(LIBXML_VERSION >= 20621) {
define('GETID3_LIBXML_OPTIONS', LIBXML_NOENT | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_COMPACT);
} else {
define('GETID3_LIBXML_OPTIONS', LIBXML_NOENT | LIBXML_NONET | LIBXML_NOWARNING);
}
}
class getid3_lib class getid3_lib
{ {
@ -303,11 +310,10 @@ class getid3_lib
} }
} elseif (($exponent == 0) && ($fraction == 0)) { } elseif (($exponent == 0) && ($fraction == 0)) {
if ($signbit == '1') { if ($signbit == '1') {
$floatvalue = -0; $floatvalue = -0.0;
} else { } else {
$floatvalue = 0; $floatvalue = 0.0;
} }
$floatvalue = ($signbit ? 0 : -0);
} elseif (($exponent == 0) && ($fraction != 0)) { } elseif (($exponent == 0) && ($fraction != 0)) {
// These are 'unnormalized' values // These are 'unnormalized' values
$floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring); $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
@ -732,7 +738,7 @@ class getid3_lib
// This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
// disabled by default, but is still needed when LIBXML_NOENT is used. // disabled by default, but is still needed when LIBXML_NOENT is used.
$loader = @libxml_disable_entity_loader(true); $loader = @libxml_disable_entity_loader(true);
$XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT); $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', GETID3_LIBXML_OPTIONS);
$return = self::SimpleXMLelement2array($XMLobject); $return = self::SimpleXMLelement2array($XMLobject);
@libxml_disable_entity_loader($loader); @libxml_disable_entity_loader($loader);
return $return; return $return;

View File

@ -182,7 +182,7 @@ class getID3
public $option_md5_data = false; public $option_md5_data = false;
/** /**
* Use MD5 of source file if availble - only FLAC and OptimFROG * Use MD5 of source file if available - only FLAC and OptimFROG
* *
* @var bool * @var bool
*/ */
@ -387,12 +387,15 @@ class getID3
*/ */
protected $startup_warning = ''; protected $startup_warning = '';
const VERSION = '1.9.21-202109171300'; const VERSION = '1.9.22-202207161647';
const FREAD_BUFFER_SIZE = 32768; const FREAD_BUFFER_SIZE = 32768;
const ATTACHMENTS_NONE = false; const ATTACHMENTS_NONE = false;
const ATTACHMENTS_INLINE = true; const ATTACHMENTS_INLINE = true;
/**
* @throws getid3_exception
*/
public function __construct() { public function __construct() {
// Check for PHP version // Check for PHP version
@ -569,7 +572,7 @@ class getID3
$this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false); $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
// remote files not supported // remote files not supported
if (preg_match('#^(ht|f)tp://#', $filename)) { if (preg_match('#^(ht|f)tps?://#', $filename)) {
throw new getid3_exception('Remote files are not supported - please copy the file locally first'); throw new getid3_exception('Remote files are not supported - please copy the file locally first');
} }
@ -1055,15 +1058,16 @@ class getID3
'mime_type' => 'audio/x-monkeys-audio', 'mime_type' => 'audio/x-monkeys-audio',
), ),
// has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
// // MOD - audio - MODule (assorted sub-formats) // MOD - audio - MODule (SoundTracker)
// 'mod' => array( 'mod' => array(
// 'pattern' => '^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)', //'pattern' => '^.{1080}(M\\.K\\.|M!K!|FLT4|FLT8|[5-9]CHN|[1-3][0-9]CH)', // has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
// 'group' => 'audio', 'pattern' => '^.{1080}(M\\.K\\.)',
// 'module' => 'mod', 'group' => 'audio',
// 'option' => 'mod', 'module' => 'mod',
// 'mime_type' => 'audio/mod', 'option' => 'mod',
// ), 'mime_type' => 'audio/mod',
),
// MOD - audio - MODule (Impulse Tracker) // MOD - audio - MODule (Impulse Tracker)
'it' => array( 'it' => array(
@ -1094,7 +1098,7 @@ class getID3
// MPC - audio - Musepack / MPEGplus // MPC - audio - Musepack / MPEGplus
'mpc' => array( 'mpc' => array(
'pattern' => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])', 'pattern' => '^(MPCK|MP\\+)',
'group' => 'audio', 'group' => 'audio',
'module' => 'mpc', 'module' => 'mpc',
'mime_type' => 'audio/x-musepack', 'mime_type' => 'audio/x-musepack',
@ -1551,6 +1555,13 @@ class getID3
$info = $GetFileFormatArray['mp3']; $info = $GetFileFormatArray['mp3'];
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php'; $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
return $info; return $info;
} elseif (preg_match('#\\.mp[cp\\+]$#i', $filename) && preg_match('#[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0]#s', $filedata)) {
// old-format (SV4-SV6) Musepack header that has a very loose pattern match and could falsely match other data (e.g. corrupt mp3)
// only enable this pattern check if the filename ends in .mpc/mpp/mp+
$GetFileFormatArray = $this->GetFileFormatArray();
$info = $GetFileFormatArray['mpc'];
$info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
return $info;
} elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) { } elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
// there's not really a useful consistent "magic" at the beginning of .cue files to identify them // there's not really a useful consistent "magic" at the beginning of .cue files to identify them
// so until I think of something better, just go by filename if all other format checks fail // so until I think of something better, just go by filename if all other format checks fail
@ -2198,6 +2209,11 @@ abstract class getid3_handler
$this->data_string_position += $bytes; $this->data_string_position += $bytes;
return substr($this->data_string, $this->data_string_position - $bytes, $bytes); return substr($this->data_string, $this->data_string_position - $bytes, $bytes);
} }
if ($bytes == 0) {
return '';
} elseif ($bytes < 0) {
throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().')', 10);
}
$pos = $this->ftell() + $bytes; $pos = $this->ftell() + $bytes;
if (!getid3_lib::intValueSupported($pos)) { if (!getid3_lib::intValueSupported($pos)) {
throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10); throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);

View File

@ -20,6 +20,24 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php',
class getid3_asf extends getid3_handler class getid3_asf extends getid3_handler
{ {
protected static $ASFIndexParametersObjectIndexSpecifiersIndexTypes = array(
1 => 'Nearest Past Data Packet',
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint'
);
protected static $ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes = array(
1 => 'Nearest Past Data Packet',
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint',
0xFF => 'Frame Number Offset'
);
protected static $ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes = array(
2 => 'Nearest Past Media Object',
3 => 'Nearest Past Cleanpoint'
);
/** /**
* @param getID3 $getid3 * @param getID3 $getid3
*/ */
@ -317,6 +335,7 @@ class getid3_asf extends getid3_handler
// shortcut // shortcut
$thisfile_asf['codec_list_object'] = array(); $thisfile_asf['codec_list_object'] = array();
/** @var mixed[] $thisfile_asf_codeclistobject */
$thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object']; $thisfile_asf_codeclistobject = &$thisfile_asf['codec_list_object'];
$thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset; $thisfile_asf_codeclistobject['offset'] = $NextObjectOffset + $offset;
@ -332,6 +351,9 @@ class getid3_asf extends getid3_handler
break; break;
} }
$thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); $thisfile_asf_codeclistobject['codec_entries_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
if ($thisfile_asf_codeclistobject['codec_entries_count'] > 0) {
$thisfile_asf_codeclistobject['codec_entries'] = array();
}
$offset += 4; $offset += 4;
for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) { for ($CodecEntryCounter = 0; $CodecEntryCounter < $thisfile_asf_codeclistobject['codec_entries_count']; $CodecEntryCounter++) {
// shortcut // shortcut
@ -528,7 +550,7 @@ class getid3_asf extends getid3_handler
$offset += 16; $offset += 16;
$thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']); $thisfile_asf_markerobject['reserved_guid'] = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) { if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
$this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}'); $this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
break; break;
} }
$thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4)); $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
@ -648,7 +670,7 @@ class getid3_asf extends getid3_handler
break; break;
default: default:
$this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}'); $this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['error_correction_type']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}');
//return false; //return false;
break; break;
} }
@ -1442,7 +1464,7 @@ class getid3_asf extends getid3_handler
} }
} }
} }
$info['bitrate'] = (isset($thisfile_audio['bitrate']) ? $thisfile_audio['bitrate'] : 0) + (isset($thisfile_video['bitrate']) ? $thisfile_video['bitrate'] : 0); $info['bitrate'] = 0 + (isset($thisfile_audio['bitrate']) ? $thisfile_audio['bitrate'] : 0) + (isset($thisfile_video['bitrate']) ? $thisfile_video['bitrate'] : 0);
if ((!isset($info['playtime_seconds']) || ($info['playtime_seconds'] <= 0)) && ($info['bitrate'] > 0)) { if ((!isset($info['playtime_seconds']) || ($info['playtime_seconds'] <= 0)) && ($info['bitrate'] > 0)) {
$info['playtime_seconds'] = ($info['filesize'] - $info['avdataoffset']) / ($info['bitrate'] / 8); $info['playtime_seconds'] = ($info['filesize'] - $info['avdataoffset']) / ($info['bitrate'] / 8);
@ -1577,8 +1599,9 @@ class getid3_asf extends getid3_handler
'GETID3_ASF_Audio_Media' => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B', 'GETID3_ASF_Audio_Media' => 'F8699E40-5B4D-11CF-A8FD-00805F5C442B',
'GETID3_ASF_Media_Object_Index_Object' => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C', 'GETID3_ASF_Media_Object_Index_Object' => 'FEB103F8-12AD-4C64-840F-2A1D2F7AD48C',
'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE', 'GETID3_ASF_Alt_Extended_Content_Encryption_Obj' => 'FF889EF1-ADEE-40DA-9E71-98704BB928CE',
'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html 'GETID3_ASF_Index_Placeholder_Object' => 'D9AADE20-7C17-4F9C-BC28-8555DD98E2A2', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // http://cpan.uwinnipeg.ca/htdocs/Audio-WMA/Audio/WMA.pm.html 'GETID3_ASF_Compatibility_Object' => '26F18B5D-4584-47EC-9F5F-0E651F0452C9', // https://metacpan.org/dist/Audio-WMA/source/WMA.pm
'GETID3_ASF_Media_Object_Index_Parameters_Object'=> '6B203BAD-3F11-48E4-ACA8-D7613DE2CFA7',
); );
return $GUIDarray; return $GUIDarray;
} }
@ -1741,7 +1764,7 @@ class getid3_asf extends getid3_handler
* @return array * @return array
*/ */
public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
// http://msdn.microsoft.com/en-us/library/bb643323.aspx // https://web.archive.org/web/20140419205228/http://msdn.microsoft.com/en-us/library/bb643323.aspx
$offset = 0; $offset = 0;
$objectOffset = 0; $objectOffset = 0;
@ -1805,8 +1828,8 @@ class getid3_asf extends getid3_handler
$thisObject['stream_language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); $thisObject['stream_language_id_index'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2; $offset += 2;
$thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); $thisObject['average_time_per_frame'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 8));
$offset += 4; $offset += 8;
$thisObject['stream_name_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); $thisObject['stream_name_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2; $offset += 2;
@ -1823,7 +1846,7 @@ class getid3_asf extends getid3_handler
$streamName['stream_name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2)); $streamName['stream_name_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2; $offset += 2;
$streamName['stream_name'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length'])); $streamName['stream_name'] = substr($asf_header_extension_object_data, $offset, $streamName['stream_name_length']);
$offset += $streamName['stream_name_length']; $offset += $streamName['stream_name_length'];
$thisObject['stream_names'][$i] = $streamName; $thisObject['stream_names'][$i] = $streamName;
@ -1845,7 +1868,7 @@ class getid3_asf extends getid3_handler
$payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4)); $payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4; $offset += 4;
$payloadExtensionSystem['extension_system_info_length'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length'])); $payloadExtensionSystem['extension_system_info'] = substr($asf_header_extension_object_data, $offset, $payloadExtensionSystem['extension_system_info_length']);
$offset += $payloadExtensionSystem['extension_system_info_length']; $offset += $payloadExtensionSystem['extension_system_info_length'];
$thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem; $thisObject['payload_extension_systems'][$i] = $payloadExtensionSystem;
@ -1853,6 +1876,40 @@ class getid3_asf extends getid3_handler
break; break;
case GETID3_ASF_Advanced_Mutual_Exclusion_Object:
$thisObject['exclusion_type'] = substr($asf_header_extension_object_data, $offset, 16);
$offset += 16;
$thisObject['exclusion_type_text'] = $this->BytestringToGUID($thisObject['exclusion_type']);
$thisObject['stream_numbers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
for ($i = 0; $i < $thisObject['stream_numbers_count']; $i++) {
$thisObject['stream_numbers'][$i] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
}
break;
case GETID3_ASF_Stream_Prioritization_Object:
$thisObject['priority_records_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
for ($i = 0; $i < $thisObject['priority_records_count']; $i++) {
$priorityRecord = array();
$priorityRecord['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$priorityRecord['flags_raw'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$priorityRecord['flags']['mandatory'] = (bool) $priorityRecord['flags_raw'] & 0x00000001;
$thisObject['priority_records'][$i] = $priorityRecord;
}
break;
case GETID3_ASF_Padding_Object: case GETID3_ASF_Padding_Object:
// padding, skip it // padding, skip it
break; break;
@ -1970,6 +2027,103 @@ class getid3_asf extends getid3_handler
} }
break; break;
case GETID3_ASF_Index_Parameters_Object:
$thisObject['index_entry_time_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;
$thisObject['index_specifiers'][$i] = $indexSpecifier;
}
break;
case GETID3_ASF_Media_Object_Index_Parameters_Object:
$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFMediaObjectIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;
$thisObject['index_specifiers'][$i] = $indexSpecifier;
}
break;
case GETID3_ASF_Timecode_Index_Parameters_Object:
// 4.11 Timecode Index Parameters Object (mandatory only if TIMECODE index is present in file, 0 or 1)
// Field name Field type Size (bits)
// Object ID GUID 128 // GUID for the Timecode Index Parameters Object - ASF_Timecode_Index_Parameters_Object
// Object Size QWORD 64 // Specifies the size, in bytes, of the Timecode Index Parameters Object. Valid values are at least 34 bytes.
// Index Entry Count Interval DWORD 32 // This value is ignored for the Timecode Index Parameters Object.
// Index Specifiers Count WORD 16 // Specifies the number of entries in the Index Specifiers list. Valid values are 1 and greater.
// Index Specifiers array of: varies //
// * Stream Number WORD 16 // Specifies the stream number that the Index Specifiers refer to. Valid values are between 1 and 127.
// * Index Type WORD 16 // Specifies the type of index. Values are defined as follows (1 is not a valid value):
// 2 = Nearest Past Media Object - indexes point to the closest data packet containing an entire video frame or the first fragment of a video frame
// 3 = Nearest Past Cleanpoint - indexes point to the closest data packet containing an entire video frame (or first fragment of a video frame) that is a key frame.
// Nearest Past Media Object is the most common value
$thisObject['index_entry_count_interval'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 4));
$offset += 4;
$thisObject['index_specifiers_count'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
for ($i = 0; $i < $thisObject['index_specifiers_count']; $i++) {
$indexSpecifier = array();
$indexSpecifier['stream_number'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 2));
$offset += 2;
$indexSpecifier['index_type_text'] = isset(static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']])
? static::$ASFTimecodeIndexParametersObjectIndexSpecifiersIndexTypes[$indexSpecifier['index_type']]
: 'invalid'
;
$thisObject['index_specifiers'][$i] = $indexSpecifier;
}
break;
case GETID3_ASF_Compatibility_Object:
$thisObject['profile'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
$offset += 1;
$thisObject['mode'] = getid3_lib::LittleEndian2Int(substr($asf_header_extension_object_data, $offset, 1));
$offset += 1;
break;
default: default:
$unhandled_sections++; $unhandled_sections++;
if ($this->GUIDname($thisObject['guid_text'])) { if ($this->GUIDname($thisObject['guid_text'])) {

View File

@ -61,12 +61,16 @@ class getid3_quicktime extends getid3_handler
$this->fseek($offset); $this->fseek($offset);
$AtomHeader = $this->fread(8); $AtomHeader = $this->fread(8);
// https://github.com/JamesHeinrich/getID3/issues/382
// Atom sizes are stored as 32-bit number in most cases, but sometimes (notably for "mdat")
// a 64-bit value is required, in which case the normal 32-bit size field is set to 0x00000001
// and the 64-bit "real" size value is the next 8 bytes.
$atom_size_extended_bytes = 0;
$atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4)); $atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
$atomname = substr($AtomHeader, 4, 4); $atomname = substr($AtomHeader, 4, 4);
// 64-bit MOV patch by jlegateØktnc*com
if ($atomsize == 1) { if ($atomsize == 1) {
$atomsize = getid3_lib::BigEndian2Int($this->fread(8)); $atom_size_extended_bytes = 8;
$atomsize = getid3_lib::BigEndian2Int($this->fread($atom_size_extended_bytes));
} }
if (($offset + $atomsize) > $info['avdataend']) { if (($offset + $atomsize) > $info['avdataend']) {
@ -85,12 +89,14 @@ class getid3_quicktime extends getid3_handler
$info['quicktime'][$atomname]['offset'] = $offset; $info['quicktime'][$atomname]['offset'] = $offset;
break; break;
} }
$atomHierarchy = array(); $atomHierarchy = array();
$parsedAtomData = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms); $parsedAtomData = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize - $atom_size_extended_bytes, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
$parsedAtomData['name'] = $atomname; $parsedAtomData['name'] = $atomname;
$parsedAtomData['size'] = $atomsize; $parsedAtomData['size'] = $atomsize;
$parsedAtomData['offset'] = $offset; $parsedAtomData['offset'] = $offset;
if ($atom_size_extended_bytes) {
$parsedAtomData['xsize_bytes'] = $atom_size_extended_bytes;
}
if (in_array($atomname, array('uuid'))) { if (in_array($atomname, array('uuid'))) {
@$info['quicktime'][$atomname][] = $parsedAtomData; @$info['quicktime'][$atomname][] = $parsedAtomData;
} else { } else {
@ -108,7 +114,7 @@ class getid3_quicktime extends getid3_handler
unset($info['avdataend_tmp']); unset($info['avdataend_tmp']);
} }
if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) { if (isset($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
$durations = $this->quicktime_time_to_sample_table($info); $durations = $this->quicktime_time_to_sample_table($info);
for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) { for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
$bookmark = array(); $bookmark = array();
@ -259,7 +265,9 @@ class getid3_quicktime extends getid3_handler
} else { } else {
switch ($atomname) { switch ($atomname) {
case 'moov': // MOVie container atom case 'moov': // MOVie container atom
case 'moof': // MOvie Fragment box
case 'trak': // TRAcK container atom case 'trak': // TRAcK container atom
case 'traf': // TRAck Fragment box
case 'clip': // CLIPping container atom case 'clip': // CLIPping container atom
case 'matt': // track MATTe container atom case 'matt': // track MATTe container atom
case 'edts': // EDiTS container atom case 'edts': // EDiTS container atom
@ -843,6 +851,7 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
case 'dvcp': case 'dvcp':
case 'gif ': case 'gif ':
case 'h263': case 'h263':
case 'hvc1':
case 'jpeg': case 'jpeg':
case 'kpcd': case 'kpcd':
case 'mjpa': case 'mjpa':
@ -1541,6 +1550,21 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
unset($mdat_offset, $chapter_string_length, $chapter_matches); unset($mdat_offset, $chapter_string_length, $chapter_matches);
break; break;
case 'ID32': // ID3v2
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
$getid3_temp = new getID3();
$getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
$getid3_id3v2->StartingOffset = $atom_structure['offset'] + 14; // framelength(4)+framename(4)+flags(4)+??(2)
if ($atom_structure['valid'] = $getid3_id3v2->Analyze()) {
$atom_structure['id3v2'] = $getid3_temp->info['id3v2'];
} else {
$this->warning('ID32 frame at offset '.$atom_structure['offset'].' did not parse');
}
unset($getid3_temp, $getid3_id3v2);
break;
case 'free': // FREE space atom case 'free': // FREE space atom
case 'skip': // SKIP atom case 'skip': // SKIP atom
case 'wide': // 64-bit expansion placeholder atom case 'wide': // 64-bit expansion placeholder atom
@ -1700,7 +1724,8 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
$atom_structure['language'] = substr($atom_data, 4 + 0, 2); $atom_structure['language'] = substr($atom_data, 4 + 0, 2);
$atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2)); $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
$atom_structure['data'] = substr($atom_data, 4 + 4); $atom_structure['data'] = substr($atom_data, 4 + 4);
$atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++]; $atom_structure['key_name'] = (isset($info['quicktime']['temp_meta_key_names'][$metaDATAkey]) ? $info['quicktime']['temp_meta_key_names'][$metaDATAkey] : '');
$metaDATAkey++;
if ($atom_structure['key_name'] && $atom_structure['data']) { if ($atom_structure['key_name'] && $atom_structure['data']) {
@$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data']; @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
@ -2075,6 +2100,28 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
$atom_structure['track_number'] = getid3_lib::BigEndian2Int($atom_data); $atom_structure['track_number'] = getid3_lib::BigEndian2Int($atom_data);
break; break;
// AVIF-related - https://docs.rs/avif-parse/0.13.2/src/avif_parse/boxes.rs.html
case 'pitm': // Primary ITeM
case 'iloc': // Item LOCation
case 'iinf': // Item INFo
case 'iref': // Image REFerence
case 'iprp': // Image PRoPerties
$this->error('AVIF files not currently supported');
$atom_structure['data'] = $atom_data;
break;
case 'tfdt': // Track Fragment base media Decode Time box
case 'tfhd': // Track Fragment HeaDer box
case 'mfhd': // Movie Fragment HeaDer box
case 'trun': // Track fragment RUN box
$this->error('fragmented mp4 files not currently supported');
$atom_structure['data'] = $atom_data;
break;
case 'mvex': // MoVie EXtends box
case 'pssh': // Protection System Specific Header box
case 'sidx': // Segment InDeX box
default: default:
$this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).'), '.$atomsize.' bytes at offset '.$baseoffset); $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).'), '.$atomsize.' bytes at offset '.$baseoffset);
$atom_structure['data'] = $atom_data; $atom_structure['data'] = $atom_data;
@ -2323,6 +2370,7 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in
$QuicktimeVideoCodecLookup['gif '] = 'GIF'; $QuicktimeVideoCodecLookup['gif '] = 'GIF';
$QuicktimeVideoCodecLookup['h261'] = 'H261'; $QuicktimeVideoCodecLookup['h261'] = 'H261';
$QuicktimeVideoCodecLookup['h263'] = 'H263'; $QuicktimeVideoCodecLookup['h263'] = 'H263';
$QuicktimeVideoCodecLookup['hvc1'] = 'H.265/HEVC';
$QuicktimeVideoCodecLookup['IV41'] = 'Indeo4'; $QuicktimeVideoCodecLookup['IV41'] = 'Indeo4';
$QuicktimeVideoCodecLookup['jpeg'] = 'JPEG'; $QuicktimeVideoCodecLookup['jpeg'] = 'JPEG';
$QuicktimeVideoCodecLookup['kpcd'] = 'PhotoCD'; $QuicktimeVideoCodecLookup['kpcd'] = 'PhotoCD';

View File

@ -808,6 +808,9 @@ class getid3_riff extends getid3_handler
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) { if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'])) {
$strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data']; $strfData = $thisfile_riff['AVI ']['hdrl']['strl']['strf'][$i]['data'];
if (!isset($thisfile_riff_raw['strf'][$strhfccType][$streamindex])) {
$thisfile_riff_raw['strf'][$strhfccType][$streamindex] = null;
}
// shortcut // shortcut
$thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex]; $thisfile_riff_raw_strf_strhfccType_streamindex = &$thisfile_riff_raw['strf'][$strhfccType][$streamindex];
@ -1353,10 +1356,10 @@ class getid3_riff extends getid3_handler
if (!isset($info['playtime_seconds'])) { if (!isset($info['playtime_seconds'])) {
$info['playtime_seconds'] = 0; $info['playtime_seconds'] = 0;
} }
if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { if (isset($thisfile_riff_raw['strh'][0]['dwLength']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line
// needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie // needed for >2GB AVIs where 'avih' chunk only lists number of frames in that chunk, not entire movie
$info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); $info['playtime_seconds'] = $thisfile_riff_raw['strh'][0]['dwLength'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
} elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { } elseif (isset($thisfile_riff_raw['avih']['dwTotalFrames']) && isset($thisfile_riff_raw['avih']['dwMicroSecPerFrame'])) { // @phpstan-ignore-line
$info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000); $info['playtime_seconds'] = $thisfile_riff_raw['avih']['dwTotalFrames'] * ($thisfile_riff_raw['avih']['dwMicroSecPerFrame'] / 1000000);
} }
@ -1579,7 +1582,7 @@ class getid3_riff extends getid3_handler
public function ParseRIFF($startoffset, $maxoffset) { public function ParseRIFF($startoffset, $maxoffset) {
$info = &$this->getid3->info; $info = &$this->getid3->info;
$RIFFchunk = false; $RIFFchunk = array();
$FoundAllChunksWeNeed = false; $FoundAllChunksWeNeed = false;
$LISTchunkParent = null; $LISTchunkParent = null;
$LISTchunkMaxOffset = null; $LISTchunkMaxOffset = null;
@ -1934,7 +1937,7 @@ class getid3_riff extends getid3_handler
} }
} }
return $RIFFchunk; return !empty($RIFFchunk) ? $RIFFchunk : false;
} }
/** /**

View File

@ -315,6 +315,10 @@ class getid3_mp3 extends getid3_handler
$encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min']; $encoder_options .= ' -b'.$thisfile_mpeg_audio_lame['bitrate_min'];
} }
if (isset($thisfile_mpeg_audio['bitrate']) && $thisfile_mpeg_audio['bitrate'] === 'free') {
$encoder_options .= ' --freeformat';
}
if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) { if (!empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev']) || !empty($thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'])) {
$encoder_options .= ' --nogap'; $encoder_options .= ' --nogap';
} }
@ -750,7 +754,8 @@ class getid3_mp3 extends getid3_handler
unset($thisfile_mpeg_audio_lame['long_version']); unset($thisfile_mpeg_audio_lame['long_version']);
// It the LAME tag was only introduced in LAME v3.90 // It the LAME tag was only introduced in LAME v3.90
// http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 // https://wiki.hydrogenaud.io/index.php/LAME#VBR_header_and_LAME_tag
// https://hydrogenaud.io/index.php?topic=9933
// Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html // Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
// are assuming a 'Xing' identifier offset of 0x24, which is the case for // are assuming a 'Xing' identifier offset of 0x24, which is the case for
@ -786,7 +791,7 @@ class getid3_mp3 extends getid3_handler
$thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
// bytes $A7-$AE Replay Gain // bytes $A7-$AE Replay Gain
// http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html // https://web.archive.org/web/20021015212753/http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
// bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') {
// LAME 3.94a16 and later - 9.23 fixed point // LAME 3.94a16 and later - 9.23 fixed point
@ -914,7 +919,7 @@ class getid3_mp3 extends getid3_handler
// LAME CBR // LAME CBR
if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1 && $thisfile_mpeg_audio['bitrate'] !== 'free') {
$thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; $thisfile_mpeg_audio['bitrate_mode'] = 'cbr';
$thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']);
@ -1169,6 +1174,7 @@ class getid3_mp3 extends getid3_handler
$nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']);
if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) {
/** @phpstan-ignore-next-line */
getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]); getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]);
if ($ScanAsCBR) { if ($ScanAsCBR) {
// force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header // force CBR mode, used for trying to pick out invalid audio streams with valid(?) VBR headers, or VBR streams with no VBR header

View File

@ -186,7 +186,7 @@ class getid3_ogg extends getid3_handler
if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) { if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
$info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
} }
$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable'); $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
} elseif (substr($filedata, 0, 8) == "fishead\x00") { } elseif (substr($filedata, 0, 8) == "fishead\x00") {

View File

@ -2064,7 +2064,7 @@ class getid3_id3v2 extends getid3_handler
$parsedFrame['subframes'][] = $subframe; $parsedFrame['subframes'][] = $subframe;
break; break;
case 'WXXX': case 'WXXX':
list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2); @list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2);
$parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url']; $parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url'];
$parsedFrame['subframes'][] = $subframe; $parsedFrame['subframes'][] = $subframe;
break; break;

View File

@ -16,7 +16,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '6.1-beta2-54375'; $wp_version = '6.1-beta2-54376';
/** /**
* 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.