diff --git a/wp-includes/ID3/getid3.lib.php b/wp-includes/ID3/getid3.lib.php index 46a39ee3b2..8514e9781f 100644 --- a/wp-includes/ID3/getid3.lib.php +++ b/wp-includes/ID3/getid3.lib.php @@ -242,7 +242,7 @@ class getid3_lib /** * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic * - * @link https://web.archive.org/web/20120325162206/http://www.psc.edu/general/software/packages/ieee/ieee.php + * @link http://www.psc.edu/general/software/packages/ieee/ieee.html * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html * * @param string $byteword @@ -294,12 +294,12 @@ class getid3_lib if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) { // Not a Number - $floatvalue = NAN; + $floatvalue = false; } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) { if ($signbit == '1') { - $floatvalue = -INF; + $floatvalue = '-infinity'; } else { - $floatvalue = INF; + $floatvalue = '+infinity'; } } elseif (($exponent == 0) && ($fraction == 0)) { if ($signbit == '1') { @@ -427,20 +427,14 @@ class getid3_lib * @return string */ public static function Dec2Bin($number) { - if (!is_numeric($number)) { - // https://github.com/JamesHeinrich/getID3/issues/299 - trigger_error('TypeError: Dec2Bin(): Argument #1 ($number) must be numeric, '.gettype($number).' given', E_USER_WARNING); - return ''; - } - $bytes = array(); while ($number >= 256) { - $bytes[] = (int) (($number / 256) - (floor($number / 256))) * 256; + $bytes[] = (($number / 256) - (floor($number / 256))) * 256; $number = floor($number / 256); } - $bytes[] = (int) $number; + $bytes[] = $number; $binstring = ''; - foreach ($bytes as $i => $byte) { - $binstring = (($i == count($bytes) - 1) ? decbin($byte) : str_pad(decbin($byte), 8, '0', STR_PAD_LEFT)).$binstring; + for ($i = 0; $i < count($bytes); $i++) { + $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring; } return $binstring; } @@ -671,7 +665,6 @@ class getid3_lib // or // $foo['path']['to']['my'] = 'file.txt'; $ArrayPath = ltrim($ArrayPath, $Separator); - $ReturnedArray = array(); if (($pos = strpos($ArrayPath, $Separator)) !== false) { $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value); } else { @@ -1545,21 +1538,12 @@ class getid3_lib public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) { // Copy all entries from ['tags'] into common ['comments'] if (!empty($ThisFileInfo['tags'])) { - - // Some tag types can only support limited character sets and may contain data in non-standard encoding (usually ID3v1) - // and/or poorly-transliterated tag values that are also in tag formats that do support full-range character sets - // To make the output more user-friendly, process the potentially-problematic tag formats last to enhance the chance that - // the first entries in [comments] are the most correct and the "bad" ones (if any) come later. - // https://github.com/JamesHeinrich/getID3/issues/338 - $processLastTagTypes = array('id3v1','riff'); - foreach ($processLastTagTypes as $processLastTagType) { - if (isset($ThisFileInfo['tags'][$processLastTagType])) { - // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings - $temp = $ThisFileInfo['tags'][$processLastTagType]; - unset($ThisFileInfo['tags'][$processLastTagType]); - $ThisFileInfo['tags'][$processLastTagType] = $temp; - unset($temp); - } + if (isset($ThisFileInfo['tags']['id3v1'])) { + // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings + $ID3v1 = $ThisFileInfo['tags']['id3v1']; + unset($ThisFileInfo['tags']['id3v1']); + $ThisFileInfo['tags']['id3v1'] = $ID3v1; + unset($ID3v1); } foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) { foreach ($tagarray as $tagname => $tagdata) { @@ -1578,30 +1562,20 @@ class getid3_lib // new value is identical but shorter-than (or equal-length to) one already in comments - skip break 2; } - - if (function_exists('mb_convert_encoding')) { - if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { - // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. - // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character - break 2; - } + } + if (function_exists('mb_convert_encoding')) { + if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { + // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. + // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character + break 2; } } } elseif (!is_array($value)) { - $newvaluelength = strlen(trim($value)); - $newvaluelengthMB = mb_strlen(trim($value)); + $newvaluelength = strlen(trim($value)); foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { - $oldvaluelength = strlen(trim($existingvalue)); - $oldvaluelengthMB = mb_strlen(trim($existingvalue)); - if (($newvaluelengthMB == $oldvaluelengthMB) && ($existingvalue == getid3_lib::iconv_fallback('UTF-8', 'ASCII', $value))) { - // https://github.com/JamesHeinrich/getID3/issues/338 - // check for tags containing extended characters that may have been forced into limited-character storage (e.g. UTF8 values into ASCII) - // which will usually display unrepresentable characters as "?" - $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); - break; - } + $oldvaluelength = strlen(trim($existingvalue)); if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); break; @@ -1627,16 +1601,14 @@ class getid3_lib } // attempt to standardize spelling of returned keys - if (!empty($ThisFileInfo['comments'])) { - $StandardizeFieldNames = array( - 'tracknumber' => 'track_number', - 'track' => 'track_number', - ); - foreach ($StandardizeFieldNames as $badkey => $goodkey) { - if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { - $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; - unset($ThisFileInfo['comments'][$badkey]); - } + $StandardizeFieldNames = array( + 'tracknumber' => 'track_number', + 'track' => 'track_number', + ); + foreach ($StandardizeFieldNames as $badkey => $goodkey) { + if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { + $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; + unset($ThisFileInfo['comments'][$badkey]); } } @@ -1762,7 +1734,6 @@ class getid3_lib * @return float|bool */ public static function getFileSizeSyscall($path) { - $commandline = null; $filesize = false; if (GETID3_OS_ISWINDOWS) { @@ -1824,7 +1795,7 @@ class getid3_lib * * @return string */ - public static function mb_basename($path, $suffix = '') { + public static function mb_basename($path, $suffix = null) { $splited = preg_split('#/#', rtrim($path, '/ ')); return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); } diff --git a/wp-includes/ID3/getid3.php b/wp-includes/ID3/getid3.php index 2008025b85..5cb3c036c0 100644 --- a/wp-includes/ID3/getid3.php +++ b/wp-includes/ID3/getid3.php @@ -17,6 +17,10 @@ if (!defined('GETID3_OS_ISWINDOWS')) { if (!defined('GETID3_INCLUDEPATH')) { define('GETID3_INCLUDEPATH', dirname(__FILE__).DIRECTORY_SEPARATOR); } +// Workaround Bug #39923 (https://bugs.php.net/bug.php?id=39923) +if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) { + define('IMG_JPG', IMAGETYPE_JPEG); +} if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); } @@ -53,7 +57,7 @@ if ($open_basedir) { if (substr($basedir, -1, 1) != DIRECTORY_SEPARATOR) { $basedir .= DIRECTORY_SEPARATOR; } - if (strpos($temp_dir, $basedir) === 0) { + if (preg_match('#^'.preg_quote($basedir).'#', $temp_dir)) { $found_valid_tempdir = true; break; } @@ -210,140 +214,6 @@ class getID3 */ public $option_fread_buffer_size = 32768; - - - // module-specific options - - /** archive.rar - * if true use PHP RarArchive extension, if false (non-extension parsing not yet written in getID3) - * - * @var bool - */ - public $options_archive_rar_use_php_rar_extension = true; - - /** archive.gzip - * Optional file list - disable for speed. - * Decode gzipped files, if possible, and parse recursively (.tar.gz for example). - * - * @var bool - */ - public $options_archive_gzip_parse_contents = false; - - /** audio.midi - * if false only parse most basic information, much faster for some files but may be inaccurate - * - * @var bool - */ - public $options_audio_midi_scanwholefile = true; - - /** audio.mp3 - * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, - * unrecommended, but may provide data from otherwise-unusable files. - * - * @var bool - */ - public $options_audio_mp3_allow_bruteforce = false; - - /** audio.mp3 - * number of frames to scan to determine if MPEG-audio sequence is valid - * Lower this number to 5-20 for faster scanning - * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams - * - * @var int - */ - public $options_audio_mp3_mp3_valid_check_frames = 50; - - /** audio.wavpack - * Avoid scanning all frames (break after finding ID_RIFF_HEADER and ID_CONFIG_BLOCK, - * significantly faster for very large files but other data may be missed - * - * @var bool - */ - public $options_audio_wavpack_quick_parsing = false; - - /** audio-video.flv - * Break out of the loop if too many frames have been scanned; only scan this - * many if meta frame does not contain useful duration. - * - * @var int - */ - public $options_audiovideo_flv_max_frames = 100000; - - /** audio-video.matroska - * 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 $options_audiovideo_matroska_hide_clusters = true; - - /** audio-video.matroska - * True to parse the whole file, not only header [default: FALSE]. - * - * @var bool - */ - public $options_audiovideo_matroska_parse_whole_file = false; - - /** audio-video.quicktime - * return all parsed data from all atoms if true, otherwise just returned parsed metadata - * - * @var bool - */ - public $options_audiovideo_quicktime_ReturnAtomData = false; - - /** audio-video.quicktime - * return all parsed data from all atoms if true, otherwise just returned parsed metadata - * - * @var bool - */ - public $options_audiovideo_quicktime_ParseAllPossibleAtoms = false; - - /** audio-video.swf - * return all parsed tags if true, otherwise do not return tags not parsed by getID3 - * - * @var bool - */ - public $options_audiovideo_swf_ReturnAllTagData = false; - - /** graphic.bmp - * return BMP palette - * - * @var bool - */ - public $options_graphic_bmp_ExtractPalette = false; - - /** graphic.bmp - * return image data - * - * @var bool - */ - public $options_graphic_bmp_ExtractData = false; - - /** graphic.png - * If data chunk is larger than this do not read it completely (getID3 only needs the first - * few dozen bytes for parsing). - * - * @var int - */ - public $options_graphic_png_max_data_bytes = 10000000; - - /** misc.pdf - * return full details of PDF Cross-Reference Table (XREF) - * - * @var bool - */ - public $options_misc_pdf_returnXREF = false; - - /** misc.torrent - * Assume all .torrent files are less than 1MB and just read entire thing into memory for easy processing. - * Override this value if you need to process files larger than 1MB - * - * @var int - */ - public $options_misc_torrent_max_torrent_filesize = 1048576; - - - // Public variables /** @@ -387,7 +257,7 @@ class getID3 */ protected $startup_warning = ''; - const VERSION = '1.9.21-202109171300'; + const VERSION = '1.9.20-202006061653'; const FREAD_BUFFER_SIZE = 32768; const ATTACHMENTS_NONE = false; @@ -767,18 +637,6 @@ class getID3 return $this->error('Format not supported, module "'.$determined_format['include'].'" is corrupt.'); } $class = new $class_name($this); - - // set module-specific options - foreach (get_object_vars($this) as $getid3_object_vars_key => $getid3_object_vars_value) { - if (preg_match('#^options_([^_]+)_([^_]+)_(.+)$#i', $getid3_object_vars_key, $matches)) { - list($dummy, $GOVgroup, $GOVmodule, $GOVsetting) = $matches; - $GOVgroup = (($GOVgroup == 'audiovideo') ? 'audio-video' : $GOVgroup); // variable names can only contain 0-9a-z_ so standardize here - if (($GOVgroup == $determined_format['group']) && ($GOVmodule == $determined_format['module'])) { - $class->$GOVsetting = $getid3_object_vars_value; - } - } - } - $class->Analyze(); unset($class); @@ -1497,16 +1355,6 @@ class getID3 'fail_ape' => 'ERROR', ), - // TORRENT - .torrent - 'torrent' => array( - 'pattern' => '^(d8\\:announce|d7\\:comment)', - 'group' => 'misc', - 'module' => 'torrent', - 'mime_type' => 'application/x-bittorrent', - 'fail_id3' => 'ERROR', - 'fail_ape' => 'ERROR', - ), - // CUE - data - CUEsheet (index to single-file disc images) 'cue' => array( 'pattern' => '', // empty pattern means cannot be automatically detected, will fall through all other formats and match based on filename and very basic file contents @@ -1641,7 +1489,7 @@ class getID3 if (is_string($value)) { $value = trim($value, " \r\n\t"); // do not trim nulls from $value!! Unicode characters will get mangled if trailing nulls are removed! } - if (isset($value) && $value !== "") { + if ($value) { if (!is_numeric($key)) { $this->info['tags'][trim($tag_name)][trim($tag_key)][$key] = $value; } else { @@ -2248,25 +2096,19 @@ abstract class getid3_handler $this->data_string_position = $this->data_string_length + $bytes; break; } - return 0; // fseek returns 0 on success + return 0; + } else { + $pos = $bytes; + if ($whence == SEEK_CUR) { + $pos = $this->ftell() + $bytes; + } elseif ($whence == SEEK_END) { + $pos = $this->getid3->info['filesize'] + $bytes; + } + if (!getid3_lib::intValueSupported($pos)) { + throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); + } } - - $pos = $bytes; - if ($whence == SEEK_CUR) { - $pos = $this->ftell() + $bytes; - } elseif ($whence == SEEK_END) { - $pos = $this->getid3->info['filesize'] + $bytes; - } - if (!getid3_lib::intValueSupported($pos)) { - throw new getid3_exception('cannot fseek('.$pos.') because beyond PHP filesystem limit', 10); - } - - // https://github.com/JamesHeinrich/getID3/issues/327 - $result = fseek($this->getid3->fp, $bytes, $whence); - if ($result !== 0) { // fseek returns 0 on success - throw new getid3_exception('cannot fseek('.$pos.'). resource/stream does not appear to support seeking', 10); - } - return $result; + return fseek($this->getid3->fp, $bytes, $whence); } /** @@ -2382,8 +2224,6 @@ abstract class getid3_handler * @throws getid3_exception */ public function saveAttachment($name, $offset, $length, $image_mime=null) { - $fp_dest = null; - $dest = null; try { // do not extract at all diff --git a/wp-includes/ID3/module.audio-video.asf.php b/wp-includes/ID3/module.audio-video.asf.php index 85edb7d755..fce923c027 100644 --- a/wp-includes/ID3/module.audio-video.asf.php +++ b/wp-includes/ID3/module.audio-video.asf.php @@ -93,7 +93,6 @@ class getid3_asf extends getid3_handler $offset = 0; $thisfile_asf_streambitratepropertiesobject = array(); $thisfile_asf_codeclistobject = array(); - $StreamPropertiesObjectData = array(); for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { $NextObjectGUID = substr($ASFHeaderData, $offset, 16); @@ -284,7 +283,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_headerextensionobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); $offset += 2; if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) { - $this->warning('header_extension_object.reserved_2 ('.$thisfile_asf_headerextensionobject['reserved_2'].') does not match expected value of "6"'); + $this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"'); //return false; break; } @@ -536,7 +535,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); $offset += 2; if ($thisfile_asf_markerobject['reserved_2'] != 0) { - $this->warning('marker_object.reserved_2 ('.$thisfile_asf_markerobject['reserved_2'].') does not match expected value of "0"'); + $this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"'); break; } $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2)); @@ -1194,7 +1193,7 @@ class getid3_asf extends getid3_handler $thisfile_asf_dataobject['reserved'] = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2)); $offset += 2; if ($thisfile_asf_dataobject['reserved'] != 0x0101) { - $this->warning('data_object.reserved (0x'.sprintf('%04X', $thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'); + $this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"'); //return false; break; } diff --git a/wp-includes/ID3/module.audio-video.flv.php b/wp-includes/ID3/module.audio-video.flv.php index 3b59e596e3..7e684072e3 100644 --- a/wp-includes/ID3/module.audio-video.flv.php +++ b/wp-includes/ID3/module.audio-video.flv.php @@ -161,7 +161,6 @@ class getid3_flv extends getid3_handler $info['flv']['video']['videoCodec'] = $LastHeaderByte & 0x07; $FLVvideoHeader = $this->fread(11); - $PictureSizeEnc = array(); if ($info['flv']['video']['videoCodec'] == GETID3_FLV_VIDEO_H264) { // this code block contributed by: moysevichØgmail*com diff --git a/wp-includes/ID3/module.audio-video.matroska.php b/wp-includes/ID3/module.audio-video.matroska.php index 128e614e2c..a285108590 100644 --- a/wp-includes/ID3/module.audio-video.matroska.php +++ b/wp-includes/ID3/module.audio-video.matroska.php @@ -224,14 +224,14 @@ class getid3_matroska extends getid3_handler * * @var bool */ - public $hide_clusters = true; + public static $hide_clusters = true; /** * True to parse the whole file, not only header [default: FALSE]. * * @var bool */ - public $parse_whole_file = false; + public static $parse_whole_file = false; /* * Private parser settings/placeholders. @@ -586,7 +586,7 @@ class getid3_matroska extends getid3_handler $info['matroska']['segment'][0]['length'] = $top_element['length']; while ($this->getEBMLelement($element_data, $top_element['end'])) { - if ($element_data['id'] != EBML_ID_CLUSTER || !$this->hide_clusters) { // collect clusters only if required + if ($element_data['id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required $info['matroska']['segments'][] = $element_data; } switch ($element_data['id']) { @@ -618,7 +618,7 @@ class getid3_matroska extends getid3_handler $this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']); break; } - if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !$this->hide_clusters) { // collect clusters only if required + if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required $info['matroska']['seek'][] = $seek_entry; } break; @@ -905,7 +905,7 @@ class getid3_matroska extends getid3_handler break; case EBML_ID_CUES: // A top-level element to speed seeking access. All entries are local to the segment. Should be mandatory for non "live" streams. - if ($this->hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway + if (self::$hide_clusters) { // do not parse cues if hide clusters is "ON" till they point to clusters anyway $this->current_offset = $element_data['end']; break; } @@ -1246,12 +1246,12 @@ class getid3_matroska extends getid3_handler } $this->current_offset = $subelement['end']; } - if (!$this->hide_clusters) { + if (!self::$hide_clusters) { $info['matroska']['cluster'][] = $cluster_entry; } // check to see if all the data we need exists already, if so, break out of the loop - if (!$this->parse_whole_file) { + if (!self::$parse_whole_file) { if (isset($info['matroska']['info']) && is_array($info['matroska']['info'])) { if (isset($info['matroska']['tracks']['tracks']) && is_array($info['matroska']['tracks']['tracks'])) { if (count($info['matroska']['track_data_offsets']) == count($info['matroska']['tracks']['tracks'])) { diff --git a/wp-includes/ID3/module.audio-video.quicktime.php b/wp-includes/ID3/module.audio-video.quicktime.php index c3bccfd086..1cf1c0590b 100644 --- a/wp-includes/ID3/module.audio-video.quicktime.php +++ b/wp-includes/ID3/module.audio-video.quicktime.php @@ -24,18 +24,7 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE_ class getid3_quicktime extends getid3_handler { - /** audio-video.quicktime - * return all parsed data from all atoms if true, otherwise just returned parsed metadata - * - * @var bool - */ - public $ReturnAtomData = false; - - /** audio-video.quicktime - * return all parsed data from all atoms if true, otherwise just returned parsed metadata - * - * @var bool - */ + public $ReturnAtomData = true; public $ParseAllPossibleAtoms = false; /** @@ -181,7 +170,7 @@ class getid3_quicktime extends getid3_handler } } - if (!isset($info['bitrate']) && !empty($info['playtime_seconds'])) { + if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) { $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; } if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) { @@ -571,28 +560,15 @@ class getid3_quicktime extends getid3_handler default: $atom_structure['data'] = substr($boxdata, 8); if ($atomname == 'covr') { - if (!empty($atom_structure['data'])) { - $atom_structure['image_mime'] = 'image/unknown'; // provide default MIME type to ensure array keys exist - if (function_exists('getimagesizefromstring') && ($getimagesize = getimagesizefromstring($atom_structure['data'])) && !empty($getimagesize['mime'])) { - $atom_structure['image_mime'] = $getimagesize['mime']; - } else { - // if getimagesizefromstring is not available, or fails for some reason, fall back to simple detection of common image formats - $ImageFormatSignatures = array( - 'image/jpeg' => "\xFF\xD8\xFF", - 'image/png' => "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", - 'image/gif' => 'GIF', - ); - foreach ($ImageFormatSignatures as $mime => $image_format_signature) { - if (substr($atom_structure['data'], 0, strlen($image_format_signature)) == $image_format_signature) { - $atom_structure['image_mime'] = $mime; - break; - } - } - } - $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover'); - } else { - $this->warning('Unknown empty "covr" image at offset '.$baseoffset); + // not a foolproof check, but better than nothing + if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/jpeg'; + } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/png'; + } elseif (preg_match('#^GIF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/gif'; } + $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover'); } break; @@ -752,13 +728,11 @@ class getid3_quicktime extends getid3_handler $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; - $ptv_lookup = array( - 0 => 'normal', - 1 => 'double', - 2 => 'half', - 3 => 'full', - 4 => 'current' - ); + $ptv_lookup[0] = 'normal'; + $ptv_lookup[1] = 'double'; + $ptv_lookup[2] = 'half'; + $ptv_lookup[3] = 'full'; + $ptv_lookup[4] = 'current'; if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; } else { @@ -934,13 +908,13 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); - $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (((int) $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); + $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); - $info['quicktime']['video']['codec'] = (((int) $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; @@ -1624,61 +1598,33 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in break; case 'NCDT': - // https://exiftool.org/TagNames/Nikon.html + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); break; case 'NCTH': // Nikon Camera THumbnail image case 'NCVW': // Nikon Camera preVieW image - case 'NCM1': // Nikon Camera preview iMage 1 - case 'NCM2': // Nikon Camera preview iMage 2 - // https://exiftool.org/TagNames/Nikon.html + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) { - $descriptions = array( - 'NCTH' => 'Nikon Camera Thumbnail Image', - 'NCVW' => 'Nikon Camera Preview Image', - 'NCM1' => 'Nikon Camera Preview Image 1', - 'NCM2' => 'Nikon Camera Preview Image 2', - ); $atom_structure['data'] = $atom_data; $atom_structure['image_mime'] = 'image/jpeg'; - $atom_structure['description'] = isset($descriptions[$atomname]) ? $descriptions[$atomname] : 'Nikon preview image'; - $info['quicktime']['comments']['picture'][] = array( - 'image_mime' => $atom_structure['image_mime'], - 'data' => $atom_data, - 'description' => $atom_structure['description'] - ); + $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); + $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); } break; - case 'NCTG': // Nikon - https://exiftool.org/TagNames/Nikon.html#NCTG - getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.nikon-nctg.php', __FILE__, true); - $nikonNCTG = new getid3_tag_nikon_nctg($this->getid3); - - $atom_structure['data'] = $nikonNCTG->parse($atom_data); + case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); break; - case 'NCHD': // Nikon:MakerNoteVersion - https://exiftool.org/TagNames/Nikon.html - $makerNoteVersion = ''; - for ($i = 0, $iMax = strlen($atom_data); $i < $iMax; ++$i) { - if (ord($atom_data[$i]) >= 0x00 && ord($atom_data[$i]) <= 0x1F) { - $makerNoteVersion .= ' '.ord($atom_data[$i]); - } else { - $makerNoteVersion .= $atom_data[$i]; - } - } - $makerNoteVersion = rtrim($makerNoteVersion, "\x00"); - $atom_structure['data'] = array( - 'MakerNoteVersion' => $makerNoteVersion - ); - break; - case 'NCDB': // Nikon - https://exiftool.org/TagNames/Nikon.html - case 'CNCV': // Canon:CompressorVersion - https://exiftool.org/TagNames/Canon.html + case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html $atom_structure['data'] = $atom_data; break; case "\x00\x00\x00\x00": // some kind of metacontainer, may contain a big data dump such as: // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4 - // https://xhelmboyx.tripod.com/formats/qti-layout.txt + // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); @@ -1775,7 +1721,6 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in 'unknown_data' => array(), 'debug_list' => '', // Used to debug variables stored as comma delimited strings ); - $debug_structure = array(); $debug_structure['debug_items'] = array(); // Can start loop here to decode all sensor data in 32 Byte chunks: foreach (str_split($atom_SENSOR_data, 32) as $sensor_key => $sensor_data) { @@ -2094,7 +2039,7 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in * @return array|false */ public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { - $atom_structure = array(); + $atom_structure = false; $subatomoffset = 0; $subatomcounter = 0; if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) { @@ -2112,22 +2057,17 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in $subatomoffset += 4; continue; } - break; + return $atom_structure; } if (strlen($subatomdata) < ($subatomsize - 8)) { // we don't have enough data to decode the subatom. // this may be because we are refusing to parse large subatoms, or it may be because this atom had its size set too large // so we passed in the start of a following atom incorrectly? - break; + return $atom_structure; } $atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms); $subatomoffset += $subatomsize; } - - if (empty($atom_structure)) { - return false; - } - return $atom_structure; } @@ -2612,9 +2552,8 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in static $QuicktimeContentRatingLookup = array(); if (empty($QuicktimeContentRatingLookup)) { $QuicktimeContentRatingLookup[0] = 'None'; - $QuicktimeContentRatingLookup[1] = 'Explicit'; $QuicktimeContentRatingLookup[2] = 'Clean'; - $QuicktimeContentRatingLookup[4] = 'Explicit (old)'; + $QuicktimeContentRatingLookup[4] = 'Explicit'; } return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid'); } @@ -2667,6 +2606,189 @@ $this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid'); } + /** + * @param string $atom_data + * + * @return array + */ + public function QuicktimeParseNikonNCTG($atom_data) { + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 + // Data is stored as records of: + // * 4 bytes record type + // * 2 bytes size of data field type: + // 0x0001 = flag (size field *= 1-byte) + // 0x0002 = char (size field *= 1-byte) + // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB + // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD + // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together + // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? + // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? + // * 2 bytes data size field + // * ? bytes data (string data may be null-padded; datestamp fields are in the format "2011:05:25 20:24:15") + // all integers are stored BigEndian + + $NCTGtagName = array( + 0x00000001 => 'Make', + 0x00000002 => 'Model', + 0x00000003 => 'Software', + 0x00000011 => 'CreateDate', + 0x00000012 => 'DateTimeOriginal', + 0x00000013 => 'FrameCount', + 0x00000016 => 'FrameRate', + 0x00000022 => 'FrameWidth', + 0x00000023 => 'FrameHeight', + 0x00000032 => 'AudioChannels', + 0x00000033 => 'AudioBitsPerSample', + 0x00000034 => 'AudioSampleRate', + 0x02000001 => 'MakerNoteVersion', + 0x02000005 => 'WhiteBalance', + 0x0200000b => 'WhiteBalanceFineTune', + 0x0200001e => 'ColorSpace', + 0x02000023 => 'PictureControlData', + 0x02000024 => 'WorldTime', + 0x02000032 => 'UnknownInfo', + 0x02000083 => 'LensType', + 0x02000084 => 'Lens', + ); + + $offset = 0; + $data = null; + $datalength = strlen($atom_data); + $parsed = array(); + while ($offset < $datalength) { + $record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4; + $data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; + $data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; + switch ($data_size_type) { + case 0x0001: // 0x0001 = flag (size field *= 1-byte) + $data = getid3_lib::BigEndian2Int(substr($atom_data, $offset, $data_size * 1)); + $offset += ($data_size * 1); + break; + case 0x0002: // 0x0002 = char (size field *= 1-byte) + $data = substr($atom_data, $offset, $data_size * 1); + $offset += ($data_size * 1); + $data = rtrim($data, "\x00"); + break; + case 0x0003: // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB + $data = ''; + for ($i = $data_size - 1; $i >= 0; $i--) { + $data .= substr($atom_data, $offset + ($i * 2), 2); + } + $data = getid3_lib::BigEndian2Int($data); + $offset += ($data_size * 2); + break; + case 0x0004: // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD + $data = ''; + for ($i = $data_size - 1; $i >= 0; $i--) { + $data .= substr($atom_data, $offset + ($i * 4), 4); + } + $data = getid3_lib::BigEndian2Int($data); + $offset += ($data_size * 4); + break; + case 0x0005: // 0x0005 = float (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together + $data = array(); + for ($i = 0; $i < $data_size; $i++) { + $numerator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 0, 4)); + $denomninator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 4, 4)); + if ($denomninator == 0) { + $data[$i] = false; + } else { + $data[$i] = (double) $numerator / $denomninator; + } + } + $offset += (8 * $data_size); + if (count($data) == 1) { + $data = $data[0]; + } + break; + case 0x0007: // 0x0007 = bytes (size field *= 1-byte), values are stored as ?????? + $data = substr($atom_data, $offset, $data_size * 1); + $offset += ($data_size * 1); + break; + case 0x0008: // 0x0008 = ????? (size field *= 2-byte), values are stored as ?????? + $data = substr($atom_data, $offset, $data_size * 2); + $offset += ($data_size * 2); + break; + default: + echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
'; + break 2; + } + + switch ($record_type) { + case 0x00000011: // CreateDate + case 0x00000012: // DateTimeOriginal + $data = strtotime($data); + break; + case 0x0200001e: // ColorSpace + switch ($data) { + case 1: + $data = 'sRGB'; + break; + case 2: + $data = 'Adobe RGB'; + break; + } + break; + case 0x02000023: // PictureControlData + $PictureControlAdjust = array(0=>'default', 1=>'quick', 2=>'full'); + $FilterEffect = array(0x80=>'off', 0x81=>'yellow', 0x82=>'orange', 0x83=>'red', 0x84=>'green', 0xff=>'n/a'); + $ToningEffect = array(0x80=>'b&w', 0x81=>'sepia', 0x82=>'cyanotype', 0x83=>'red', 0x84=>'yellow', 0x85=>'green', 0x86=>'blue-green', 0x87=>'blue', 0x88=>'purple-blue', 0x89=>'red-purple', 0xff=>'n/a'); + $data = array( + 'PictureControlVersion' => substr($data, 0, 4), + 'PictureControlName' => rtrim(substr($data, 4, 20), "\x00"), + 'PictureControlBase' => rtrim(substr($data, 24, 20), "\x00"), + //'?' => substr($data, 44, 4), + 'PictureControlAdjust' => $PictureControlAdjust[ord(substr($data, 48, 1))], + 'PictureControlQuickAdjust' => ord(substr($data, 49, 1)), + 'Sharpness' => ord(substr($data, 50, 1)), + 'Contrast' => ord(substr($data, 51, 1)), + 'Brightness' => ord(substr($data, 52, 1)), + 'Saturation' => ord(substr($data, 53, 1)), + 'HueAdjustment' => ord(substr($data, 54, 1)), + 'FilterEffect' => $FilterEffect[ord(substr($data, 55, 1))], + 'ToningEffect' => $ToningEffect[ord(substr($data, 56, 1))], + 'ToningSaturation' => ord(substr($data, 57, 1)), + ); + break; + case 0x02000024: // WorldTime + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#WorldTime + // timezone is stored as offset from GMT in minutes + $timezone = getid3_lib::BigEndian2Int(substr($data, 0, 2)); + if ($timezone & 0x8000) { + $timezone = 0 - (0x10000 - $timezone); + } + $timezone /= 60; + + $dst = (bool) getid3_lib::BigEndian2Int(substr($data, 2, 1)); + switch (getid3_lib::BigEndian2Int(substr($data, 3, 1))) { + case 2: + $datedisplayformat = 'D/M/Y'; break; + case 1: + $datedisplayformat = 'M/D/Y'; break; + case 0: + default: + $datedisplayformat = 'Y/M/D'; break; + } + + $data = array('timezone'=>floatval($timezone), 'dst'=>$dst, 'display'=>$datedisplayformat); + break; + case 0x02000083: // LensType + $data = array( + //'_' => $data, + 'mf' => (bool) ($data & 0x01), + 'd' => (bool) ($data & 0x02), + 'g' => (bool) ($data & 0x04), + 'vr' => (bool) ($data & 0x08), + ); + break; + } + $tag_name = (isset($NCTGtagName[$record_type]) ? $NCTGtagName[$record_type] : '0x'.str_pad(dechex($record_type), 8, '0', STR_PAD_LEFT)); + $parsed[$tag_name] = $data; + } + return $parsed; + } + /** * @param string $keyname * @param string|array $data diff --git a/wp-includes/ID3/module.audio-video.riff.php b/wp-includes/ID3/module.audio-video.riff.php index 6ef1116ad1..cdf553386b 100644 --- a/wp-includes/ID3/module.audio-video.riff.php +++ b/wp-includes/ID3/module.audio-video.riff.php @@ -56,7 +56,6 @@ class getid3_riff extends getid3_handler $thisfile_riff_video = &$thisfile_riff['video']; $thisfile_riff_WAVE = array(); - $Original = array(); $Original['avdataoffset'] = $info['avdataoffset']; $Original['avdataend'] = $info['avdataend']; @@ -297,18 +296,9 @@ class getid3_riff extends getid3_handler // shortcut $thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0]; - $thisfile_riff_WAVE_bext_0['title'] = substr($thisfile_riff_WAVE_bext_0['data'], 0, 256); - $thisfile_riff_WAVE_bext_0['author'] = substr($thisfile_riff_WAVE_bext_0['data'], 256, 32); - $thisfile_riff_WAVE_bext_0['reference'] = substr($thisfile_riff_WAVE_bext_0['data'], 288, 32); - foreach (array('title','author','reference') as $bext_key) { - // Some software (notably Logic Pro) may not blank existing data before writing a null-terminated string to the offsets - // assigned for text fields, resulting in a null-terminated string (or possibly just a single null) followed by garbage - // Keep only string as far as first null byte, discard rest of fixed-width data - // https://github.com/JamesHeinrich/getID3/issues/263 - $null_terminator_offset = strpos($thisfile_riff_WAVE_bext_0[$bext_key], "\x00"); - $thisfile_riff_WAVE_bext_0[$bext_key] = substr($thisfile_riff_WAVE_bext_0[$bext_key], 0, $null_terminator_offset); - } - + $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256)); + $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32)); + $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32)); $thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10); $thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8); $thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8)); @@ -317,7 +307,6 @@ class getid3_riff extends getid3_handler $thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601))); if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) { if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) { - $bext_timestamp = array(); list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date; list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time; $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']); @@ -462,62 +451,7 @@ class getid3_riff extends getid3_handler } } - if (isset($thisfile_riff_WAVE['guan'][0]['data'])) { - // shortcut - $thisfile_riff_WAVE_guan_0 = &$thisfile_riff_WAVE['guan'][0]; - if (!empty($thisfile_riff_WAVE_guan_0['data']) && (substr($thisfile_riff_WAVE_guan_0['data'], 0, 14) == 'GUANO|Version:')) { - $thisfile_riff['guano'] = array(); - foreach (explode("\n", $thisfile_riff_WAVE_guan_0['data']) as $line) { - if ($line) { - @list($key, $value) = explode(':', $line, 2); - if (substr($value, 0, 3) == '[{"') { - if ($decoded = @json_decode($value, true)) { - if (!empty($decoded) && (count($decoded) == 1)) { - $value = $decoded[0]; - } else { - $value = $decoded; - } - } - } - $thisfile_riff['guano'] = array_merge_recursive($thisfile_riff['guano'], getid3_lib::CreateDeepArray($key, '|', $value)); - } - } - // https://www.wildlifeacoustics.com/SCHEMA/GUANO.html - foreach ($thisfile_riff['guano'] as $key => $value) { - switch ($key) { - case 'Loc Position': - if (preg_match('#^([\\+\\-]?[0-9]+\\.[0-9]+) ([\\+\\-]?[0-9]+\\.[0-9]+)$#', $value, $matches)) { - list($dummy, $latitude, $longitude) = $matches; - $thisfile_riff['comments']['gps_latitude'][0] = floatval($latitude); - $thisfile_riff['comments']['gps_longitude'][0] = floatval($longitude); - $thisfile_riff['guano'][$key] = floatval($latitude).' '.floatval($longitude); - } - break; - case 'Loc Elevation': // Elevation/altitude above mean sea level in meters - $thisfile_riff['comments']['gps_altitude'][0] = floatval($value); - $thisfile_riff['guano'][$key] = (float) $value; - break; - case 'Filter HP': // High-pass filter frequency in kHz - case 'Filter LP': // Low-pass filter frequency in kHz - case 'Humidity': // Relative humidity as a percentage - case 'Length': // Recording length in seconds - case 'Loc Accuracy': // Estimated Position Error in meters - case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing - case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing - $thisfile_riff['guano'][$key] = (float) $value; - break; - case 'Samplerate': // Recording sample rate, Hz - case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed. - $thisfile_riff['guano'][$key] = (int) $value; - break; - } - } - - } else { - $this->warning('RIFF.guan data not in expected format'); - } - } if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) { $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate']; @@ -799,7 +733,6 @@ class getid3_riff extends getid3_handler } if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) { if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) { - $thisfile_riff_raw_strf_strhfccType_streamindex = null; for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) { if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) { $strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data']; @@ -1136,7 +1069,7 @@ class getid3_riff extends getid3_handler if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) { 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_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_id3v2 = new getid3_id3v2($getid3_temp); $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8; if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) { @@ -1239,7 +1172,7 @@ class getid3_riff extends getid3_handler getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true); $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_mpeg = new getid3_mpeg($getid3_temp); $getid3_mpeg->Analyze(); if (empty($getid3_temp->info['error'])) { @@ -1325,7 +1258,7 @@ class getid3_riff extends getid3_handler 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_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_id3v2 = new getid3_id3v2($getid3_temp); $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8; if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) { @@ -1581,9 +1514,6 @@ class getid3_riff extends getid3_handler $RIFFchunk = false; $FoundAllChunksWeNeed = false; - $LISTchunkParent = null; - $LISTchunkMaxOffset = null; - $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77" try { $this->fseek($startoffset); @@ -1627,7 +1557,7 @@ class getid3_riff extends getid3_handler // MP3 if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) { $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); @@ -1645,10 +1575,11 @@ class getid3_riff extends getid3_handler unset($getid3_temp, $getid3_mp3); } - } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) { + } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) { + // AC3 $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_temp->info['avdataoffset'] = $this->ftell() - 4; $getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize; $getid3_ac3 = new getid3_ac3($getid3_temp); @@ -1709,7 +1640,7 @@ class getid3_riff extends getid3_handler // Probably is MP3 data if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) { $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; $getid3_temp->info['avdataend'] = $info['avdataend']; $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__); @@ -1721,12 +1652,12 @@ class getid3_riff extends getid3_handler unset($getid3_temp, $getid3_mp3); } - } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) { + } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) { // This is probably AC-3 data $getid3_temp = new getID3(); if ($isRegularAC3) { - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; $getid3_temp->info['avdataend'] = $info['avdataend']; } @@ -1742,8 +1673,6 @@ class getid3_riff extends getid3_handler $ac3_data .= substr($testData, 8 + $i + 1, 1); $ac3_data .= substr($testData, 8 + $i + 0, 1); } - $getid3_ac3->getid3->info['avdataoffset'] = 0; - $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data); $getid3_ac3->AnalyzeString($ac3_data); } @@ -1762,7 +1691,7 @@ class getid3_riff extends getid3_handler // This is probably DTS data $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp); + $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp); $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; $getid3_dts = new getid3_dts($getid3_temp); $getid3_dts->Analyze(); @@ -1803,8 +1732,6 @@ class getid3_riff extends getid3_handler case 'indx': case 'MEXT': case 'DISP': - case 'wamd': - case 'guan': // always read data in case 'JUNK': // should be: never read data in @@ -2149,7 +2076,6 @@ class getid3_riff extends getid3_handler */ public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { - $parsed = array(); $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure $parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels $parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner diff --git a/wp-includes/ID3/module.audio.flac.php b/wp-includes/ID3/module.audio.flac.php index 014061da94..1cea4364c2 100644 --- a/wp-includes/ID3/module.audio.flac.php +++ b/wp-includes/ID3/module.audio.flac.php @@ -402,7 +402,6 @@ class getid3_flac extends getid3_handler public function parsePICTURE() { $info = &$this->getid3->info; - $picture = array(); $picture['typeid'] = getid3_lib::BigEndian2Int($this->fread(4)); $picture['picturetype'] = self::pictureTypeLookup($picture['typeid']); $picture['image_mime'] = $this->fread(getid3_lib::BigEndian2Int($this->fread(4))); diff --git a/wp-includes/ID3/module.audio.mp3.php b/wp-includes/ID3/module.audio.mp3.php index 1f5a566b83..26b28068f8 100644 --- a/wp-includes/ID3/module.audio.mp3.php +++ b/wp-includes/ID3/module.audio.mp3.php @@ -18,6 +18,12 @@ if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that acce exit; } +// number of frames to scan to determine if MPEG-audio sequence is valid +// Lower this number to 5-20 for faster scanning +// Increase this number to 50+ for most accurate detection of valid VBR/CBR +// mpeg-audio streams +define('GETID3_MP3_VALID_CHECK_FRAMES', 35); + class getid3_mp3 extends getid3_handler { @@ -29,15 +35,6 @@ class getid3_mp3 extends getid3_handler */ public $allow_bruteforce = false; - /** - * number of frames to scan to determine if MPEG-audio sequence is valid - * Lower this number to 5-20 for faster scanning - * Increase this number to 50+ for most accurate detection of valid VBR/CBR mpeg-audio streams - * - * @var int - */ - public $mp3_valid_check_frames = 50; - /** * @return bool */ @@ -58,7 +55,6 @@ class getid3_mp3 extends getid3_handler $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); } - $CurrentDataLAMEversionString = null; if (((isset($info['id3v2']['headerlength']) && ($info['avdataoffset'] > $info['id3v2']['headerlength'])) || (!isset($info['id3v2']) && ($info['avdataoffset'] > 0) && ($info['avdataoffset'] != $initialOffset)))) { $synchoffsetwarning = 'Unknown data before synch '; @@ -125,12 +121,6 @@ class getid3_mp3 extends getid3_handler if (substr($PossiblyLongerLAMEversion_String, 0, strlen($CurrentDataLAMEversionString)) == $CurrentDataLAMEversionString) { $PossiblyLongerLAMEversion_NewString = substr($PossiblyLongerLAMEversion_String, 0, strspn($PossiblyLongerLAMEversion_String, 'LAME0123456789., (abcdefghijklmnopqrstuvwxyzJFSOND)')); //"LAME3.90.3" "LAME3.87 (beta 1, Sep 27 2000)" "LAME3.88 (beta)" if (empty($info['audio']['encoder']) || (strlen($PossiblyLongerLAMEversion_NewString) > strlen($info['audio']['encoder']))) { - if (!empty($info['audio']['encoder']) && !empty($info['mpeg']['audio']['LAME']['short_version']) && ($info['audio']['encoder'] == $info['mpeg']['audio']['LAME']['short_version'])) { - if (preg_match('#^LAME[0-9\\.]+#', $PossiblyLongerLAMEversion_NewString, $matches)) { - // "LAME3.100" -> "LAME3.100.1", but avoid including "(alpha)" and similar - $info['mpeg']['audio']['LAME']['short_version'] = $matches[0]; - } - } $info['audio']['encoder'] = $PossiblyLongerLAMEversion_NewString; } } @@ -305,7 +295,7 @@ class getid3_mp3 extends getid3_handler } elseif (!empty($info['audio']['bitrate'])) { if ($info['audio']['bitrate_mode'] == 'cbr') { - $encoder_options = strtoupper($info['audio']['bitrate_mode']).round($info['audio']['bitrate'] / 1000); + $encoder_options = strtoupper($info['audio']['bitrate_mode']).ceil($info['audio']['bitrate'] / 1000); } else { $encoder_options = strtoupper($info['audio']['bitrate_mode']); } @@ -498,7 +488,7 @@ class getid3_mp3 extends getid3_handler if ($MPEGaudioHeaderValidCache[$head4_key]) { $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; } else { - $this->warning('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); + $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); return false; } @@ -732,200 +722,197 @@ class getid3_mp3 extends getid3_handler $thisfile_mpeg_audio_lame['long_version'] = substr($headerstring, $VBRidOffset + 120, 20); $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9); - - //$thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); - $thisfile_mpeg_audio_lame['numeric_version'] = ''; - if (preg_match('#^LAME([0-9\\.a-z]*)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { + $thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']); + if (preg_match('#^LAME([0-9\\.a-z]+)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) { $thisfile_mpeg_audio_lame['short_version'] = $matches[0]; $thisfile_mpeg_audio_lame['numeric_version'] = $matches[1]; } - if (strlen($thisfile_mpeg_audio_lame['numeric_version']) > 0) { - foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { - $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); + foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) { + $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number); + } + + //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { + if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 + + // extra 11 chars are not part of version string when LAMEtag present + unset($thisfile_mpeg_audio_lame['long_version']); + + // It the LAME tag was only introduced in LAME v3.90 + // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 + + // 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 + // MPEG-1 non-mono, but not for other combinations + $LAMEtagOffsetContant = $VBRidOffset - 0x24; + + // shortcuts + $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); + $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; + $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; + $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; + $thisfile_mpeg_audio_lame['raw'] = array(); + $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; + + // byte $9B VBR Quality + // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. + // Actually overwrites original Xing bytes + unset($thisfile_mpeg_audio['VBR_scale']); + $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); + + // bytes $9C-$A4 Encoder short VersionString + $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); + + // byte $A5 Info Tag revision + VBR method + $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); + + $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; + $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; + $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); + $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' + + // byte $A6 Lowpass filter value + $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; + + // bytes $A7-$AE Replay Gain + // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html + // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" + if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { + // LAME 3.94a16 and later - 9.23 fixed point + // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 + $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); + } else { + // LAME 3.94a15 and earlier - 32-bit floating point + // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 + $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); + } + if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { + unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); + } else { + $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); } - //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') { - if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207 - // extra 11 chars are not part of version string when LAMEtag present - unset($thisfile_mpeg_audio_lame['long_version']); + $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); + $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); - // It the LAME tag was only introduced in LAME v3.90 - // http://www.hydrogenaudio.org/?act=ST&f=15&t=9933 - // 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 - // MPEG-1 non-mono, but not for other combinations - $LAMEtagOffsetContant = $VBRidOffset - 0x24; + if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { - // shortcuts - $thisfile_mpeg_audio_lame['RGAD'] = array('track'=>array(), 'album'=>array()); - $thisfile_mpeg_audio_lame_RGAD = &$thisfile_mpeg_audio_lame['RGAD']; - $thisfile_mpeg_audio_lame_RGAD_track = &$thisfile_mpeg_audio_lame_RGAD['track']; - $thisfile_mpeg_audio_lame_RGAD_album = &$thisfile_mpeg_audio_lame_RGAD['album']; - $thisfile_mpeg_audio_lame['raw'] = array(); - $thisfile_mpeg_audio_lame_raw = &$thisfile_mpeg_audio_lame['raw']; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; + $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; + $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); + $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); + $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); - // byte $9B VBR Quality - // This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications. - // Actually overwrites original Xing bytes - unset($thisfile_mpeg_audio['VBR_scale']); - $thisfile_mpeg_audio_lame['vbr_quality'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1)); - - // bytes $9C-$A4 Encoder short VersionString - $thisfile_mpeg_audio_lame['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9); - - // byte $A5 Info Tag revision + VBR method - $LAMEtagRevisionVBRmethod = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1)); - - $thisfile_mpeg_audio_lame['tag_revision'] = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4; - $thisfile_mpeg_audio_lame_raw['vbr_method'] = $LAMEtagRevisionVBRmethod & 0x0F; - $thisfile_mpeg_audio_lame['vbr_method'] = self::LAMEvbrMethodLookup($thisfile_mpeg_audio_lame_raw['vbr_method']); - $thisfile_mpeg_audio['bitrate_mode'] = substr($thisfile_mpeg_audio_lame['vbr_method'], 0, 3); // usually either 'cbr' or 'vbr', but truncates 'vbr-old / vbr-rh' to 'vbr' - - // byte $A6 Lowpass filter value - $thisfile_mpeg_audio_lame['lowpass_frequency'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100; - - // bytes $A7-$AE Replay Gain - // http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html - // bytes $A7-$AA : 32 bit floating point "Peak signal amplitude" - if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.94b') { - // LAME 3.94a16 and later - 9.23 fixed point - // ie 0x0059E2EE / (2^23) = 5890798 / 8388608 = 0.7022378444671630859375 - $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = (float) ((getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4))) / 8388608); - } else { - // LAME 3.94a15 and earlier - 32-bit floating point - // Actually 3.94a16 will fall in here too and be WRONG, but is hard to detect 3.94a16 vs 3.94a15 - $thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] = getid3_lib::LittleEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4)); + if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { + $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; } - if ($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'] == 0) { - unset($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); - } else { - $thisfile_mpeg_audio_lame_RGAD['peak_db'] = getid3_lib::RGADamplitude2dB($thisfile_mpeg_audio_lame_RGAD['peak_amplitude']); + $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; + $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; + } else { + unset($thisfile_mpeg_audio_lame_RGAD['track']); + } + if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { + + $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; + $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; + $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); + $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); + $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); + + if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { + $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; } - - $thisfile_mpeg_audio_lame_raw['RGAD_track'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2)); - $thisfile_mpeg_audio_lame_raw['RGAD_album'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2)); + $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; + $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; + } else { + unset($thisfile_mpeg_audio_lame_RGAD['album']); + } + if (empty($thisfile_mpeg_audio_lame_RGAD)) { + unset($thisfile_mpeg_audio_lame['RGAD']); + } - if ($thisfile_mpeg_audio_lame_raw['RGAD_track'] != 0) { + // byte $AF Encoding flags + ATH Type + $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); + $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); + $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); + $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); + $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); + $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; - $thisfile_mpeg_audio_lame_RGAD_track['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0xE000) >> 13; - $thisfile_mpeg_audio_lame_RGAD_track['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x1C00) >> 10; - $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x0200) >> 9; - $thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_track'] & 0x01FF; - $thisfile_mpeg_audio_lame_RGAD_track['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['name']); - $thisfile_mpeg_audio_lame_RGAD_track['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['originator']); - $thisfile_mpeg_audio_lame_RGAD_track['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_track['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_track['raw']['sign_bit']); + // byte $B0 if ABR {specified bitrate} else {minimal bitrate} + $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); + if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) + $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; + } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) + // ignore + } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate + $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; + } - if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { - $info['replay_gain']['track']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; - } - $info['replay_gain']['track']['originator'] = $thisfile_mpeg_audio_lame_RGAD_track['originator']; - $info['replay_gain']['track']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_track['gain_db']; - } else { - unset($thisfile_mpeg_audio_lame_RGAD['track']); - } - if ($thisfile_mpeg_audio_lame_raw['RGAD_album'] != 0) { + // bytes $B1-$B3 Encoder delays + $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); + $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; + $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; - $thisfile_mpeg_audio_lame_RGAD_album['raw']['name'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0xE000) >> 13; - $thisfile_mpeg_audio_lame_RGAD_album['raw']['originator'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x1C00) >> 10; - $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit'] = ($thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x0200) >> 9; - $thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'] = $thisfile_mpeg_audio_lame_raw['RGAD_album'] & 0x01FF; - $thisfile_mpeg_audio_lame_RGAD_album['name'] = getid3_lib::RGADnameLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['name']); - $thisfile_mpeg_audio_lame_RGAD_album['originator'] = getid3_lib::RGADoriginatorLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['originator']); - $thisfile_mpeg_audio_lame_RGAD_album['gain_db'] = getid3_lib::RGADadjustmentLookup($thisfile_mpeg_audio_lame_RGAD_album['raw']['gain_adjust'], $thisfile_mpeg_audio_lame_RGAD_album['raw']['sign_bit']); + // byte $B4 Misc + $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); + $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); + $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; + $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; + $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; + $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; + $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); + $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; + $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); - if (!empty($thisfile_mpeg_audio_lame_RGAD['peak_amplitude'])) { - $info['replay_gain']['album']['peak'] = $thisfile_mpeg_audio_lame_RGAD['peak_amplitude']; - } - $info['replay_gain']['album']['originator'] = $thisfile_mpeg_audio_lame_RGAD_album['originator']; - $info['replay_gain']['album']['adjustment'] = $thisfile_mpeg_audio_lame_RGAD_album['gain_db']; - } else { - unset($thisfile_mpeg_audio_lame_RGAD['album']); - } - if (empty($thisfile_mpeg_audio_lame_RGAD)) { - unset($thisfile_mpeg_audio_lame['RGAD']); - } + // byte $B5 MP3 Gain + $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); + $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; + $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); + + // bytes $B6-$B7 Preset and surround info + $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); + // Reserved = ($PresetSurroundBytes & 0xC000); + $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); + $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); + $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); + $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); + if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { + $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); + } + if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { + // this may change if 3.90.4 ever comes out + $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; + } + + // bytes $B8-$BB MusicLength + $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); + $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); + + // bytes $BC-$BD MusicCRC + $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); + + // bytes $BE-$BF CRC-16 of Info Tag + $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); - // byte $AF Encoding flags + ATH Type - $EncodingFlagsATHtype = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1)); - $thisfile_mpeg_audio_lame['encoding_flags']['nspsytune'] = (bool) ($EncodingFlagsATHtype & 0x10); - $thisfile_mpeg_audio_lame['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20); - $thisfile_mpeg_audio_lame['encoding_flags']['nogap_next'] = (bool) ($EncodingFlagsATHtype & 0x40); - $thisfile_mpeg_audio_lame['encoding_flags']['nogap_prev'] = (bool) ($EncodingFlagsATHtype & 0x80); - $thisfile_mpeg_audio_lame['ath_type'] = $EncodingFlagsATHtype & 0x0F; + // LAME CBR + if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { - // byte $B0 if ABR {specified bitrate} else {minimal bitrate} - $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1)); - if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 2) { // Average BitRate (ABR) - $thisfile_mpeg_audio_lame['bitrate_abr'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; - } elseif ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { // Constant BitRate (CBR) - // ignore - } elseif ($thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate'] > 0) { // Variable BitRate (VBR) - minimum bitrate - $thisfile_mpeg_audio_lame['bitrate_min'] = $thisfile_mpeg_audio_lame['raw']['abrbitrate_minbitrate']; - } - - // bytes $B1-$B3 Encoder delays - $EncoderDelays = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3)); - $thisfile_mpeg_audio_lame['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12; - $thisfile_mpeg_audio_lame['end_padding'] = $EncoderDelays & 0x000FFF; - - // byte $B4 Misc - $MiscByte = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1)); - $thisfile_mpeg_audio_lame_raw['noise_shaping'] = ($MiscByte & 0x03); - $thisfile_mpeg_audio_lame_raw['stereo_mode'] = ($MiscByte & 0x1C) >> 2; - $thisfile_mpeg_audio_lame_raw['not_optimal_quality'] = ($MiscByte & 0x20) >> 5; - $thisfile_mpeg_audio_lame_raw['source_sample_freq'] = ($MiscByte & 0xC0) >> 6; - $thisfile_mpeg_audio_lame['noise_shaping'] = $thisfile_mpeg_audio_lame_raw['noise_shaping']; - $thisfile_mpeg_audio_lame['stereo_mode'] = self::LAMEmiscStereoModeLookup($thisfile_mpeg_audio_lame_raw['stereo_mode']); - $thisfile_mpeg_audio_lame['not_optimal_quality'] = (bool) $thisfile_mpeg_audio_lame_raw['not_optimal_quality']; - $thisfile_mpeg_audio_lame['source_sample_freq'] = self::LAMEmiscSourceSampleFrequencyLookup($thisfile_mpeg_audio_lame_raw['source_sample_freq']); - - // byte $B5 MP3 Gain - $thisfile_mpeg_audio_lame_raw['mp3_gain'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true); - $thisfile_mpeg_audio_lame['mp3_gain_db'] = (getid3_lib::RGADamplitude2dB(2) / 4) * $thisfile_mpeg_audio_lame_raw['mp3_gain']; - $thisfile_mpeg_audio_lame['mp3_gain_factor'] = pow(2, ($thisfile_mpeg_audio_lame['mp3_gain_db'] / 6)); - - // bytes $B6-$B7 Preset and surround info - $PresetSurroundBytes = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2)); - // Reserved = ($PresetSurroundBytes & 0xC000); - $thisfile_mpeg_audio_lame_raw['surround_info'] = ($PresetSurroundBytes & 0x3800); - $thisfile_mpeg_audio_lame['surround_info'] = self::LAMEsurroundInfoLookup($thisfile_mpeg_audio_lame_raw['surround_info']); - $thisfile_mpeg_audio_lame['preset_used_id'] = ($PresetSurroundBytes & 0x07FF); - $thisfile_mpeg_audio_lame['preset_used'] = self::LAMEpresetUsedLookup($thisfile_mpeg_audio_lame); - if (!empty($thisfile_mpeg_audio_lame['preset_used_id']) && empty($thisfile_mpeg_audio_lame['preset_used'])) { - $this->warning('Unknown LAME preset used ('.$thisfile_mpeg_audio_lame['preset_used_id'].') - please report to info@getid3.org'); - } - if (($thisfile_mpeg_audio_lame['short_version'] == 'LAME3.90.') && !empty($thisfile_mpeg_audio_lame['preset_used_id'])) { - // this may change if 3.90.4 ever comes out - $thisfile_mpeg_audio_lame['short_version'] = 'LAME3.90.3'; - } - - // bytes $B8-$BB MusicLength - $thisfile_mpeg_audio_lame['audio_bytes'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4)); - $ExpectedNumberOfAudioBytes = (($thisfile_mpeg_audio_lame['audio_bytes'] > 0) ? $thisfile_mpeg_audio_lame['audio_bytes'] : $thisfile_mpeg_audio['VBR_bytes']); - - // bytes $BC-$BD MusicCRC - $thisfile_mpeg_audio_lame['music_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2)); - - // bytes $BE-$BF CRC-16 of Info Tag - $thisfile_mpeg_audio_lame['lame_tag_crc'] = getid3_lib::BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2)); - - - // LAME CBR - if ($thisfile_mpeg_audio_lame_raw['vbr_method'] == 1) { - - $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; - $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); - $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; - //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { - // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; - //} - - } + $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; + $thisfile_mpeg_audio['bitrate'] = self::ClosestStandardMP3Bitrate($thisfile_mpeg_audio['bitrate']); + $info['audio']['bitrate'] = $thisfile_mpeg_audio['bitrate']; + //if (empty($thisfile_mpeg_audio['bitrate']) || (!empty($thisfile_mpeg_audio_lame['bitrate_min']) && ($thisfile_mpeg_audio_lame['bitrate_min'] != 255))) { + // $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio_lame['bitrate_min']; + //} } + } } @@ -1022,22 +1009,6 @@ class getid3_mp3 extends getid3_handler if (!$this->RecursiveFrameScanning($offset, $nextframetestoffset, $ScanAsCBR)) { return false; } - if (!empty($this->getid3->info['mp3_validity_check_bitrates']) && !empty($thisfile_mpeg_audio['bitrate_mode']) && ($thisfile_mpeg_audio['bitrate_mode'] == 'vbr') && !empty($thisfile_mpeg_audio['VBR_bitrate'])) { - // https://github.com/JamesHeinrich/getID3/issues/287 - if (count(array_keys($this->getid3->info['mp3_validity_check_bitrates'])) == 1) { - list($cbr_bitrate_in_short_scan) = array_keys($this->getid3->info['mp3_validity_check_bitrates']); - $deviation_cbr_from_header_bitrate = abs($thisfile_mpeg_audio['VBR_bitrate'] - $cbr_bitrate_in_short_scan) / $cbr_bitrate_in_short_scan; - if ($deviation_cbr_from_header_bitrate < 0.01) { - // VBR header bitrate may differ slightly from true bitrate of frames, perhaps accounting for overhead of VBR header frame itself? - // If measured CBR bitrate is within 1% of specified bitrate in VBR header then assume that file is truly CBR - $thisfile_mpeg_audio['bitrate_mode'] = 'cbr'; - //$this->warning('VBR header ignored, assuming CBR '.round($cbr_bitrate_in_short_scan / 1000).'kbps based on scan of '.$this->mp3_valid_check_frames.' frames'); - } - } - } - if (isset($this->getid3->info['mp3_validity_check_bitrates'])) { - unset($this->getid3->info['mp3_validity_check_bitrates']); - } } @@ -1159,9 +1130,8 @@ class getid3_mp3 extends getid3_handler $firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']); $this->decodeMPEGaudioHeader($offset, $firstframetestarray, false); - $info['mp3_validity_check_bitrates'] = array(); - for ($i = 0; $i < $this->mp3_valid_check_frames; $i++) { - // check next (default: 50) frames for validity, to make sure we haven't run across a false synch + for ($i = 0; $i < GETID3_MP3_VALID_CHECK_FRAMES; $i++) { + // check next GETID3_MP3_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch if (($nextframetestoffset + 4) >= $info['avdataend']) { // end of file return true; @@ -1169,7 +1139,6 @@ class getid3_mp3 extends getid3_handler $nextframetestarray = array('error' => array(), 'warning' => array(), 'avdataend' => $info['avdataend'], 'avdataoffset'=>$info['avdataoffset']); if ($this->decodeMPEGaudioHeader($nextframetestoffset, $nextframetestarray, false)) { - getid3_lib::safe_inc($info['mp3_validity_check_bitrates'][$nextframetestarray['mpeg']['audio']['bitrate']]); 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 if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($firstframetestarray['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $firstframetestarray['mpeg']['audio']['bitrate'])) { @@ -1304,7 +1273,6 @@ class getid3_mp3 extends getid3_handler $LongMPEGbitrateLookup = array(); $LongMPEGpaddingLookup = array(); $LongMPEGfrequencyLookup = array(); - $Distribution = array(); $Distribution['bitrate'] = array(); $Distribution['frequency'] = array(); $Distribution['layer'] = array(); @@ -1465,9 +1433,6 @@ class getid3_mp3 extends getid3_handler $header = $this->fread($sync_seek_buffer_size); $sync_seek_buffer_size = strlen($header); $SynchSeekOffset = 0; - $SyncSeekAttempts = 0; - $SyncSeekAttemptsMax = 1000; - $FirstFrameThisfileInfo = null; while ($SynchSeekOffset < $sync_seek_buffer_size) { if ((($avdataoffset + $SynchSeekOffset) < $info['avdataend']) && !feof($this->getid3->fp)) { @@ -1506,24 +1471,7 @@ class getid3_mp3 extends getid3_handler return false; } - if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // possible synch detected - if (++$SyncSeekAttempts >= $SyncSeekAttemptsMax) { - // https://github.com/JamesHeinrich/getID3/issues/286 - // corrupt files claiming to be MP3, with a large number of 0xFF bytes near the beginning, can cause this loop to take a very long time - // should have escape condition to avoid spending too much time scanning a corrupt file - // if a synch's not found within the first 128k bytes, then give up - $this->error('Could not find valid MPEG audio synch after scanning '.$SyncSeekAttempts.' candidate offsets'); - if (isset($info['audio']['bitrate'])) { - unset($info['audio']['bitrate']); - } - if (isset($info['mpeg']['audio'])) { - unset($info['mpeg']['audio']); - } - if (empty($info['mpeg'])) { - unset($info['mpeg']); - } - return false; - } + if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected $FirstFrameAVDataOffset = null; if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) { $FirstFrameThisfileInfo = $info; @@ -1563,9 +1511,9 @@ class getid3_mp3 extends getid3_handler if ($this->decodeMPEGaudioHeader($GarbageOffsetEnd, $dummy, true, true)) { $info = $dummy; $info['avdataoffset'] = $GarbageOffsetEnd; - $this->warning('apparently-valid VBR header not used because could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd); + $this->warning('apparently-valid VBR header not used because could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd); } else { - $this->warning('using data from VBR header even though could not find '.$this->mp3_valid_check_frames.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')'); + $this->warning('using data from VBR header even though could not find '.GETID3_MP3_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')'); } } } @@ -1610,7 +1558,6 @@ class getid3_mp3 extends getid3_handler $pct_data_scanned = 0; for ($current_segment = 0; $current_segment < $max_scan_segments; $current_segment++) { $frames_scanned_this_segment = 0; - $scan_start_offset = array(); if ($this->ftell() >= $info['avdataend']) { break; } @@ -1940,7 +1887,6 @@ class getid3_mp3 extends getid3_handler return false; } - $MPEGrawHeader = array(); $MPEGrawHeader['synch'] = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4; $MPEGrawHeader['version'] = (ord($Header4Bytes[1]) & 0x18) >> 3; // BB $MPEGrawHeader['layer'] = (ord($Header4Bytes[1]) & 0x06) >> 1; // CC diff --git a/wp-includes/ID3/module.audio.ogg.php b/wp-includes/ID3/module.audio.ogg.php index 5786fd0d59..fe092d9d94 100644 --- a/wp-includes/ID3/module.audio.ogg.php +++ b/wp-includes/ID3/module.audio.ogg.php @@ -529,7 +529,6 @@ class getid3_ogg extends getid3_handler */ public function ParseOggPageHeader() { // http://xiph.org/ogg/vorbis/doc/framing.html - $oggheader = array(); $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file $filedata = $this->fread($this->getid3->fread_buffer_size()); @@ -681,39 +680,35 @@ class getid3_ogg extends getid3_handler $VorbisCommentPage++; - if ($oggpageinfo = $this->ParseOggPageHeader()) { - $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; + $oggpageinfo = $this->ParseOggPageHeader(); + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']] = $oggpageinfo; - // First, save what we haven't read yet - $AsYetUnusedData = substr($commentdata, $commentdataoffset); + // First, save what we haven't read yet + $AsYetUnusedData = substr($commentdata, $commentdataoffset); - // Then take that data off the end - $commentdata = substr($commentdata, 0, $commentdataoffset); + // Then take that data off the end + $commentdata = substr($commentdata, 0, $commentdataoffset); - // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct - $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); - $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + // Add [headerlength] bytes of dummy data for the Ogg Page Header, just to keep absolute offsets correct + $commentdata .= str_repeat("\x00", 27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); + $commentdataoffset += (27 + $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_segments']); - // Finally, stick the unused data back on the end - $commentdata .= $AsYetUnusedData; + // Finally, stick the unused data back on the end + $commentdata .= $AsYetUnusedData; - //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); - if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { - $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); - break; - } - $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); - if ($readlength <= 0) { - $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); - break; - } - $commentdata .= $this->fread($readlength); - - //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; - } else { - $this->warning('failed to ParseOggPageHeader() at offset '.$this->ftell()); + //$commentdata .= $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']); + if (!isset($info['ogg']['pageheader'][$VorbisCommentPage])) { + $this->warning('undefined Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); break; } + $readlength = self::OggPageSegmentLength($info['ogg']['pageheader'][$VorbisCommentPage], 1); + if ($readlength <= 0) { + $this->warning('invalid length Vorbis Comment page "'.$VorbisCommentPage.'" at offset '.$this->ftell()); + break; + } + $commentdata .= $this->fread($readlength); + + //$filebaseoffset += $oggpageinfo['header_end_offset'] - $oggpageinfo['page_start_offset']; } $ThisFileInfo_ogg_comments_raw[$i]['offset'] = $commentdataoffset; $commentstring = substr($commentdata, $commentdataoffset, $ThisFileInfo_ogg_comments_raw[$i]['size']); diff --git a/wp-includes/ID3/module.tag.apetag.php b/wp-includes/ID3/module.tag.apetag.php index c5502133fc..26be982c73 100644 --- a/wp-includes/ID3/module.tag.apetag.php +++ b/wp-includes/ID3/module.tag.apetag.php @@ -360,7 +360,6 @@ class getid3_apetag extends getid3_handler // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html // shortcut - $headerfooterinfo = array(); $headerfooterinfo['raw'] = array(); $headerfooterinfo_raw = &$headerfooterinfo['raw']; @@ -390,7 +389,6 @@ class getid3_apetag extends getid3_handler // "Note: APE Tags 1.0 do not use any of the APE Tag flags. // All are set to zero on creation and ignored on reading." // http://wiki.hydrogenaud.io/index.php?title=Ape_Tags_Flags - $flags = array(); $flags['header'] = (bool) ($rawflagint & 0x80000000); $flags['footer'] = (bool) ($rawflagint & 0x40000000); $flags['this_is_header'] = (bool) ($rawflagint & 0x20000000); diff --git a/wp-includes/ID3/module.tag.id3v1.php b/wp-includes/ID3/module.tag.id3v1.php index b1de25784b..16dcf253b6 100644 --- a/wp-includes/ID3/module.tag.id3v1.php +++ b/wp-includes/ID3/module.tag.id3v1.php @@ -31,22 +31,14 @@ class getid3_id3v1 extends getid3_handler return false; } - if($info['filesize'] < 256) { - $this->fseek(-128, SEEK_END); - $preid3v1 = ''; - $id3v1tag = $this->fread(128); - } else { - $this->fseek(-256, SEEK_END); - $preid3v1 = $this->fread(128); - $id3v1tag = $this->fread(128); - } - + $this->fseek(-256, SEEK_END); + $preid3v1 = $this->fread(128); + $id3v1tag = $this->fread(128); if (substr($id3v1tag, 0, 3) == 'TAG') { $info['avdataend'] = $info['filesize'] - 128; - $ParsedID3v1 = array(); $ParsedID3v1['title'] = $this->cutfield(substr($id3v1tag, 3, 30)); $ParsedID3v1['artist'] = $this->cutfield(substr($id3v1tag, 33, 30)); $ParsedID3v1['album'] = $this->cutfield(substr($id3v1tag, 63, 30)); @@ -305,50 +297,6 @@ class getid3_id3v1 extends getid3_handler 145 => 'Anime', 146 => 'JPop', 147 => 'Synthpop', - 148 => 'Abstract', - 149 => 'Art Rock', - 150 => 'Baroque', - 151 => 'Bhangra', - 152 => 'Big Beat', - 153 => 'Breakbeat', - 154 => 'Chillout', - 155 => 'Downtempo', - 156 => 'Dub', - 157 => 'EBM', - 158 => 'Eclectic', - 159 => 'Electro', - 160 => 'Electroclash', - 161 => 'Emo', - 162 => 'Experimental', - 163 => 'Garage', - 164 => 'Global', - 165 => 'IDM', - 166 => 'Illbient', - 167 => 'Industro-Goth', - 168 => 'Jam Band', - 169 => 'Krautrock', - 170 => 'Leftfield', - 171 => 'Lounge', - 172 => 'Math Rock', - 173 => 'New Romantic', - 174 => 'Nu-Breakz', - 175 => 'Post-Punk', - 176 => 'Post-Rock', - 177 => 'Psytrance', - 178 => 'Shoegaze', - 179 => 'Space Rock', - 180 => 'Trop Rock', - 181 => 'World Music', - 182 => 'Neoclassical', - 183 => 'Audiobook', - 184 => 'Audio Theatre', - 185 => 'Neue Deutsche Welle', - 186 => 'Podcast', - 187 => 'Indie-Rock', - 188 => 'G-Funk', - 189 => 'Dubstep', - 190 => 'Garage Rock', - 191 => 'Psybient', 255 => 'Unknown', diff --git a/wp-includes/ID3/module.tag.id3v2.php b/wp-includes/ID3/module.tag.id3v2.php index 99e56a5fdb..85dd7a147a 100644 --- a/wp-includes/ID3/module.tag.id3v2.php +++ b/wp-includes/ID3/module.tag.id3v2.php @@ -345,7 +345,7 @@ class getid3_id3v2 extends getid3_handler } if (($frame_size <= strlen($framedata)) && ($this->IsValidID3v2FrameName($frame_name, $id3v2_majorversion))) { - $parsedFrame = array(); + unset($parsedFrame); $parsedFrame['frame_name'] = $frame_name; $parsedFrame['frame_flags_raw'] = $frame_flags; $parsedFrame['data'] = substr($framedata, 0, $frame_size); @@ -978,7 +978,7 @@ class getid3_id3v2 extends getid3_handler } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USLT')) || // 4.8 USLT Unsynchronised lyric/text transcription - (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription + (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) { // 4.9 ULT Unsynchronised lyric/text transcription // There may be more than one 'Unsynchronised lyrics/text transcription' frame // in each tag, but only one with the same language and content descriptor. //
@@ -994,28 +994,24 @@ class getid3_id3v2 extends getid3_handler $this->warning('Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding'); $frame_textencoding_terminator = "\x00"; } - if (strlen($parsedFrame['data']) >= (4 + strlen($frame_textencoding_terminator))) { // shouldn't be an issue but badly-written files have been spotted in the wild with not only no contents but also missing the required language field, see https://github.com/JamesHeinrich/getID3/issues/315 - $frame_language = substr($parsedFrame['data'], $frame_offset, 3); - $frame_offset += 3; - $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset); - if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) { - $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 - } - $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); - $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']); - $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); - $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator); + $frame_language = substr($parsedFrame['data'], $frame_offset, 3); + $frame_offset += 3; + $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset); + if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) { + $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00 + } + $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset); + $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']); + $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); + $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator); - $parsedFrame['encodingid'] = $frame_textencoding; - $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); + $parsedFrame['encodingid'] = $frame_textencoding; + $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); - $parsedFrame['language'] = $frame_language; - $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); - if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); - } - } else { - $this->warning('Invalid data in frame "'.$parsedFrame['frame_name'].'" at offset '.$parsedFrame['dataoffset']); + $parsedFrame['language'] = $frame_language; + $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false); + if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) { + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']); } unset($parsedFrame['data']); @@ -1374,8 +1370,6 @@ class getid3_id3v2 extends getid3_handler $frame_textencoding_terminator = "\x00"; } - $frame_imagetype = null; - $frame_mimetype = null; if ($id3v2_majorversion == 2 && strlen($parsedFrame['data']) > $frame_offset) { $frame_imagetype = substr($parsedFrame['data'], $frame_offset, 3); if (strtolower($frame_imagetype) == 'ima') { @@ -1962,14 +1956,18 @@ class getid3_id3v2 extends getid3_handler $frame_offset = 0; $parsedFrame['peakamplitude'] = getid3_lib::BigEndian2Float(substr($parsedFrame['data'], $frame_offset, 4)); $frame_offset += 4; - foreach (array('track','album') as $rgad_entry_type) { - $rg_adjustment_word = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2)); - $frame_offset += 2; - $parsedFrame['raw'][$rgad_entry_type]['name'] = ($rg_adjustment_word & 0xE000) >> 13; - $parsedFrame['raw'][$rgad_entry_type]['originator'] = ($rg_adjustment_word & 0x1C00) >> 10; - $parsedFrame['raw'][$rgad_entry_type]['signbit'] = ($rg_adjustment_word & 0x0200) >> 9; - $parsedFrame['raw'][$rgad_entry_type]['adjustment'] = ($rg_adjustment_word & 0x0100); - } + $rg_track_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $rg_album_adjustment = getid3_lib::Dec2Bin(substr($parsedFrame['data'], $frame_offset, 2)); + $frame_offset += 2; + $parsedFrame['raw']['track']['name'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 0, 3)); + $parsedFrame['raw']['track']['originator'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 3, 3)); + $parsedFrame['raw']['track']['signbit'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 6, 1)); + $parsedFrame['raw']['track']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_track_adjustment, 7, 9)); + $parsedFrame['raw']['album']['name'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 0, 3)); + $parsedFrame['raw']['album']['originator'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 3, 3)); + $parsedFrame['raw']['album']['signbit'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 6, 1)); + $parsedFrame['raw']['album']['adjustment'] = getid3_lib::Bin2Dec(substr($rg_album_adjustment, 7, 9)); $parsedFrame['track']['name'] = getid3_lib::RGADnameLookup($parsedFrame['raw']['track']['name']); $parsedFrame['track']['originator'] = getid3_lib::RGADoriginatorLookup($parsedFrame['raw']['track']['originator']); $parsedFrame['track']['adjustment'] = getid3_lib::RGADadjustmentLookup($parsedFrame['raw']['track']['adjustment'], $parsedFrame['raw']['track']['signbit']); @@ -2446,8 +2444,7 @@ class getid3_id3v2 extends getid3_handler TMM Manats TND Dinars TOP Pa'anga - TRL Liras (old) - TRY Liras + TRL Liras TTD Dollars TVD Tuvalu Dollars TWD New Dollars @@ -2648,7 +2645,6 @@ class getid3_id3v2 extends getid3_handler TND Tunisia TOP Tonga TRL Turkey - TRY Turkey TTD Trinidad and Tobago TVD Tuvalu TWD Taiwan diff --git a/wp-includes/ID3/module.tag.lyrics3.php b/wp-includes/ID3/module.tag.lyrics3.php index c8b2cf6305..b2375057e7 100644 --- a/wp-includes/ID3/module.tag.lyrics3.php +++ b/wp-includes/ID3/module.tag.lyrics3.php @@ -33,9 +33,6 @@ class getid3_lyrics3 extends getid3_handler } $this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size] - $lyrics3offset = null; - $lyrics3version = null; - $lyrics3size = null; $lyrics3_id3v1 = $this->fread(128 + 9 + 6); $lyrics3lsz = (int) substr($lyrics3_id3v1, 0, 6); // Lyrics3size $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200 diff --git a/wp-includes/ID3/readme.txt b/wp-includes/ID3/readme.txt index 0888bc4de2..e48bcef917 100644 --- a/wp-includes/ID3/readme.txt +++ b/wp-includes/ID3/readme.txt @@ -625,4 +625,3 @@ Reference material: * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html * http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header * http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf -* https://fileformats.fandom.com/wiki/Torrent_file \ No newline at end of file diff --git a/wp-includes/version.php b/wp-includes/version.php index f8e8096f51..6565d8e6a8 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '5.9-alpha-51900'; +$wp_version = '5.9-alpha-51901'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.