diff -r 3d4e9c994f10 -r a86126ab1dd4 wp/wp-includes/ID3/module.audio-video.matroska.php --- a/wp/wp-includes/ID3/module.audio-video.matroska.php Tue Oct 22 16:11:46 2019 +0200 +++ b/wp/wp-includes/ID3/module.audio-video.matroska.php Tue Dec 15 13:49:49 2020 +0100 @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.matriska.php // @@ -14,6 +14,9 @@ // /// ///////////////////////////////////////////////////////////////// +if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers + exit; +} define('EBML_ID_CHAPTERS', 0x0043A770); // [10][43][A7][70] -- A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation. define('EBML_ID_SEEKHEAD', 0x014D9B74); // [11][4D][9B][74] -- Contains the position of other level 1 elements. @@ -72,7 +75,7 @@ define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file. define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible. define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values: -define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with. +define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with. define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents. define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with. define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values: @@ -215,17 +218,33 @@ */ class getid3_matroska extends getid3_handler { - // public options - public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE] - public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE] + /** + * If true, do not return information about CLUSTER chunks, since there's a lot of them + * and they're not usually useful [default: TRUE]. + * + * @var bool + */ + public static $hide_clusters = true; - // private parser settings/placeholders + /** + * True to parse the whole file, not only header [default: FALSE]. + * + * @var bool + */ + public static $parse_whole_file = false; + + /* + * Private parser settings/placeholders. + */ private $EBMLbuffer = ''; private $EBMLbuffer_offset = 0; private $EBMLbuffer_length = 0; private $current_offset = 0; private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID); + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -313,7 +332,7 @@ break;*/ } - $info['video']['streams'][] = $track_info; + $info['video']['streams'][$trackarray['TrackUID']] = $track_info; break; case 2: // Audio @@ -326,7 +345,7 @@ switch ($trackarray['CodecID']) { case 'A_PCM/INT/LIT': case 'A_PCM/INT/BIG': - $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth']; + $track_info['bitrate'] = $track_info['sample_rate'] * $track_info['channels'] * $trackarray['BitDepth']; break; case 'A_AC3': @@ -346,7 +365,7 @@ // create temp instance $getid3_temp = new getID3(); if ($track_info['dataformat'] != 'flac') { - $getid3_temp->openfile($this->getid3->filename); + $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); } $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset']; if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') { @@ -366,8 +385,8 @@ if (!empty($getid3_temp->info[$header_data_key])) { $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key]; if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { - foreach ($getid3_temp->info['audio'] as $key => $value) { - $track_info[$key] = $value; + foreach ($getid3_temp->info['audio'] as $sub_key => $value) { + $track_info[$sub_key] = $value; } } } @@ -421,8 +440,8 @@ if (!empty($getid3_temp->info['ogg'])) { $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg']; if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { - foreach ($getid3_temp->info['audio'] as $key => $value) { - $track_info[$key] = $value; + foreach ($getid3_temp->info['audio'] as $sub_key => $value) { + $track_info[$sub_key] = $value; } } } @@ -449,9 +468,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']); - foreach ($parsed as $key => $value) { - if ($key != 'raw') { - $track_info[$key] = $value; + foreach ($parsed as $sub_key => $value) { + if ($sub_key != 'raw') { + $track_info[$sub_key] = $value; } } $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed; @@ -462,7 +481,7 @@ break; } - $info['audio']['streams'][] = $track_info; + $info['audio']['streams'][$trackarray['TrackUID']] = $track_info; break; } } @@ -493,9 +512,36 @@ unset($info['mime_type']); } + // use _STATISTICS_TAGS if available to set audio/video bitrates + if (!empty($info['matroska']['tags'])) { + $_STATISTICS_byTrackUID = array(); + foreach ($info['matroska']['tags'] as $key1 => $value1) { + if (!empty($value1['Targets']['TagTrackUID'][0]) && !empty($value1['SimpleTag'])) { + foreach ($value1['SimpleTag'] as $key2 => $value2) { + if (!empty($value2['TagName']) && isset($value2['TagString'])) { + $_STATISTICS_byTrackUID[$value1['Targets']['TagTrackUID'][0]][$value2['TagName']] = $value2['TagString']; + } + } + } + } + foreach (array('audio','video') as $avtype) { + if (!empty($info[$avtype]['streams'])) { + foreach ($info[$avtype]['streams'] as $trackUID => $trackdata) { + if (!isset($trackdata['bitrate']) && !empty($_STATISTICS_byTrackUID[$trackUID]['BPS'])) { + $info[$avtype]['streams'][$trackUID]['bitrate'] = (int) $_STATISTICS_byTrackUID[$trackUID]['BPS']; + @$info[$avtype]['bitrate'] += $info[$avtype]['streams'][$trackUID]['bitrate']; + } + } + } + } + } + return true; } + /** + * @param array $info + */ private function parseEBML(&$info) { // http://www.matroska.org/technical/specs/index.html#EBMLBasics $this->current_offset = $info['avdataoffset']; @@ -595,8 +641,10 @@ while ($this->getEBMLelement($subelement, $track_entry['end'], array(EBML_ID_VIDEO, EBML_ID_AUDIO, EBML_ID_CONTENTENCODINGS, EBML_ID_CODECPRIVATE))) { switch ($subelement['id']) { + case EBML_ID_TRACKUID: + $track_entry[$subelement['id_name']] = getid3_lib::PrintHexBytes($subelement['data'], true, false); + break; case EBML_ID_TRACKNUMBER: - case EBML_ID_TRACKUID: case EBML_ID_TRACKTYPE: case EBML_ID_MINCACHE: case EBML_ID_MAXCACHE: @@ -944,7 +992,7 @@ case EBML_ID_TAGEDITIONUID: case EBML_ID_TAGCHAPTERUID: case EBML_ID_TAGATTACHMENTUID: - $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']); + $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::PrintHexBytes($sub_sub_subelement['data'], true, false); break; default: @@ -1228,6 +1276,11 @@ } } + /** + * @param int $min_data + * + * @return bool + */ private function EnsureBufferHasEnoughData($min_data=1024) { if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) { $read_bytes = max($min_data, $this->getid3->fread_buffer_size()); @@ -1249,6 +1302,9 @@ return true; } + /** + * @return int|float|false + */ private function readEBMLint() { $actual_offset = $this->current_offset - $this->EBMLbuffer_offset; @@ -1281,6 +1337,12 @@ return $int_value; } + /** + * @param int $length + * @param bool $check_buffer + * + * @return string|false + */ private function readEBMLelementData($length, $check_buffer=false) { if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) { return false; @@ -1290,6 +1352,13 @@ return $data; } + /** + * @param array $element + * @param int $parent_end + * @param array|bool $get_data + * + * @return bool + */ private function getEBMLelement(&$element, $parent_end, $get_data=false) { if ($this->current_offset >= $parent_end) { return false; @@ -1326,6 +1395,11 @@ return true; } + /** + * @param string $type + * @param int $line + * @param array $element + */ private function unhandledElement($type, $line, $element) { // warn only about unknown and missed elements, not about unuseful if (!in_array($element['id'], $this->unuseful_elements)) { @@ -1338,6 +1412,11 @@ } } + /** + * @param array $SimpleTagArray + * + * @return bool + */ private function ExtractCommentsSimpleTag($SimpleTagArray) { if (!empty($SimpleTagArray['SimpleTag'])) { foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) { @@ -1353,6 +1432,11 @@ return true; } + /** + * @param int $parent_end + * + * @return array + */ private function HandleEMBLSimpleTag($parent_end) { $simpletag_entry = array(); @@ -1383,6 +1467,13 @@ return $simpletag_entry; } + /** + * @param array $element + * @param int $block_type + * @param array $info + * + * @return array + */ private function HandleEMBLClusterBlock($element, $block_type, &$info) { // http://www.matroska.org/technical/specs/index.html#block_structure // http://www.matroska.org/technical/specs/index.html#simpleblock_structure @@ -1446,6 +1537,11 @@ return $block_data; } + /** + * @param string $EBMLstring + * + * @return int|float|false + */ private static function EBML2Int($EBMLstring) { // http://matroska.org/specs/ @@ -1488,12 +1584,22 @@ return getid3_lib::BigEndian2Int($EBMLstring); } + /** + * @param int $EBMLdatestamp + * + * @return float + */ private static function EBMLdate2unix($EBMLdatestamp) { // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC) // 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC return round(($EBMLdatestamp / 1000000000) + 978307200); } + /** + * @param int $target_type + * + * @return string|int + */ public static function TargetTypeValue($target_type) { // http://www.matroska.org/technical/specs/tagging/index.html static $TargetTypeValue = array(); @@ -1509,6 +1615,11 @@ return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type); } + /** + * @param int $lacingtype + * + * @return string|int + */ public static function BlockLacingType($lacingtype) { // http://matroska.org/technical/specs/index.html#block_structure static $BlockLacingType = array(); @@ -1521,6 +1632,11 @@ return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype); } + /** + * @param string $codecid + * + * @return string + */ public static function CodecIDtoCommonName($codecid) { // http://www.matroska.org/technical/specs/codecid/index.html static $CodecIDlist = array(); @@ -1557,6 +1673,11 @@ return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid); } + /** + * @param int $value + * + * @return string + */ private static function EBMLidName($value) { static $EBMLidList = array(); if (empty($EBMLidList)) { @@ -1755,6 +1876,11 @@ return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value)); } + /** + * @param int $value + * + * @return string + */ public static function displayUnit($value) { // http://www.matroska.org/technical/specs/index.html#DisplayUnit static $units = array( @@ -1766,8 +1892,14 @@ return (isset($units[$value]) ? $units[$value] : 'unknown'); } + /** + * @param array $streams + * + * @return array + */ private static function getDefaultStreamInfo($streams) { + $stream = array(); foreach (array_reverse($streams) as $stream) { if ($stream['default']) { break;