Make WordPress Core


Ignore:
Timestamp:
09/14/2019 07:06:09 PM (7 years ago)
Author:
jorbin
Message:

Update getID3 library to fix issues with PHP7.4

Updates to trunk version that includes fixes for PHP7.4

Changelog:
https://github.com/JamesHeinrich/getID3/compare/v1.9.14...00f3fbfd77e583099ca70a3cf0bc092e113d2b20

See: #47751,#47783.
Fixes: #48040.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/ID3/module.tag.id3v2.php

    r41196 r46112  
    11<?php
     2
    23/////////////////////////////////////////////////////////////////
    34/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
    8 // See readme.txt for more details                             //
     5//  available at https://github.com/JamesHeinrich/getID3       //
     6//            or https://www.getid3.org                        //
     7//            or http://getid3.sourceforge.net                 //
     8//  see readme.txt for more details                            //
    99/////////////////////////////////////////////////////////////////
    1010///                                                            //
     
    2121        public $StartingOffset = 0;
    2222
     23        /**
     24         * @return bool
     25         */
    2326        public function Analyze() {
    2427                $info = &$this->getid3->info;
     
    5760                if (substr($header, 0, 3) == 'ID3'  &&  strlen($header) == 10) {
    5861
    59                         $thisfile_id3v2['majorversion'] = ord($header{3});
    60                         $thisfile_id3v2['minorversion'] = ord($header{4});
     62                        $thisfile_id3v2['majorversion'] = ord($header[3]);
     63                        $thisfile_id3v2['minorversion'] = ord($header[4]);
    6164
    6265                        // shortcut
     
    7780                }
    7881
    79                 $id3_flags = ord($header{5});
     82                $id3_flags = ord($header[5]);
    8083                switch ($id3v2_majorversion) {
    8184                        case 2:
     
    258261                                        $thisfile_id3v2['padding']['valid']  = true;
    259262                                        for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
    260                                                 if ($framedata{$i} != "\x00") {
     263                                                if ($framedata[$i] != "\x00") {
    261264                                                        $thisfile_id3v2['padding']['valid'] = false;
    262265                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
     
    267270                                        break; // skip rest of ID3v2 header
    268271                                }
     272                                $frame_header = null;
     273                                $frame_name   = null;
     274                                $frame_size   = null;
     275                                $frame_flags  = null;
    269276                                if ($id3v2_majorversion == 2) {
    270277                                        // Frame ID  $xx xx xx (three characters)
     
    320327                                        $len = strlen($framedata);
    321328                                        for ($i = 0; $i < $len; $i++) {
    322                                                 if ($framedata{$i} != "\x00") {
     329                                                if ($framedata[$i] != "\x00") {
    323330                                                        $thisfile_id3v2['padding']['valid'] = false;
    324331                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
     
    428435                        if (substr($footer, 0, 3) == '3DI') {
    429436                                $thisfile_id3v2['footer'] = true;
    430                                 $thisfile_id3v2['majorversion_footer'] = ord($footer{3});
    431                                 $thisfile_id3v2['minorversion_footer'] = ord($footer{4});
     437                                $thisfile_id3v2['majorversion_footer'] = ord($footer[3]);
     438                                $thisfile_id3v2['minorversion_footer'] = ord($footer[4]);
    432439                        }
    433440                        if ($thisfile_id3v2['majorversion_footer'] <= 4) {
    434                                 $id3_flags = ord(substr($footer{5}));
     441                                $id3_flags = ord($footer[5]);
    435442                                $thisfile_id3v2_flags['unsynch_footer']  = (bool) ($id3_flags & 0x80);
    436443                                $thisfile_id3v2_flags['extfoot_footer']  = (bool) ($id3_flags & 0x40);
     
    453460                }
    454461
    455                 if (isset($thisfile_id3v2['comments']['track'])) {
    456                         foreach ($thisfile_id3v2['comments']['track'] as $key => $value) {
     462                if (isset($thisfile_id3v2['comments']['track_number'])) {
     463                        foreach ($thisfile_id3v2['comments']['track_number'] as $key => $value) {
    457464                                if (strstr($value, '/')) {
    458                                         list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]);
     465                                        list($thisfile_id3v2['comments']['track_number'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track_number'][$key]);
    459466                                }
    460467                        }
     
    499506        }
    500507
    501 
     508        /**
     509         * @param string $genrestring
     510         *
     511         * @return array
     512         */
    502513        public function ParseID3v2GenreString($genrestring) {
    503514                // Parse genres into arrays of genreName and genreID
     
    531542                        $element = trim($element);
    532543                        if ($element) {
    533                                 if (preg_match('#^[0-9]{1,3}#', $element)) {
     544                                if (preg_match('#^[0-9]{1,3}$#', $element)) {
    534545                                        $clean_genres[] = getid3_id3v1::LookupGenreName($element);
    535546                                } else {
     
    541552        }
    542553
    543 
     554        /**
     555         * @param array $parsedFrame
     556         *
     557         * @return bool
     558         */
    544559        public function ParseID3v2Frame(&$parsedFrame) {
    545560
     
    658673                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    659674                        }
    660                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    661                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    662                                 // if description only contains a BOM or terminator then make it blank
    663                                 $frame_description = '';
    664                         }
     675                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     676                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    665677                        $parsedFrame['encodingid']  = $frame_textencoding;
    666678                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
    667679
    668                         $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $frame_description));
     680                        $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['description']));
    669681                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
     682                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
    670683                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
    671684                                $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
     
    679692
    680693
    681                 } elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame
     694                } elseif ($parsedFrame['frame_name'][0] == 'T') { // 4.2. T??[?] Text information frame
    682695                        //   There may only be one text information frame of its kind in an tag.
    683696                        // <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
     
    693706
    694707                        $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
     708                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
    695709
    696710                        $parsedFrame['encodingid'] = $frame_textencoding;
    697711                        $parsedFrame['encoding']   = $this->TextEncodingNameLookup($frame_textencoding);
    698 
    699712                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
    700713                                // ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
     
    752765                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    753766                        }
    754                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    755                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    756                                 // if description only contains a BOM or terminator then make it blank
    757                                 $frame_description = '';
    758                         }
    759                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    760 
    761                         $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator);
    762                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    763                                 $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    764                         }
    765                         if ($frame_terminatorpos) {
    766                                 // there are null bytes after the data - this is not according to spec
    767                                 // only use data up to first null byte
    768                                 $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
    769                         } else {
    770                                 // no null bytes following data, just use all data
    771                                 $frame_urldata = (string) $parsedFrame['data'];
    772                         }
    773 
    774767                        $parsedFrame['encodingid']  = $frame_textencoding;
    775768                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
    776 
    777                         $parsedFrame['url']         = $frame_urldata;
    778                         $parsedFrame['description'] = $frame_description;
     769                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);           // according to the frame text encoding
     770                        $parsedFrame['url']         = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); // always ISO-8859-1
     771                        $parsedFrame['description'] = $this->RemoveStringTerminator($parsedFrame['description'], $frame_textencoding_terminator);
     772                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
     773
    779774                        if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
    780                                 $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']);
     775                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
    781776                        }
    782777                        unset($parsedFrame['data']);
    783778
    784779
    785                 } elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames
     780                } elseif ($parsedFrame['frame_name'][0] == 'W') { // 4.3. W??? URL link frames
    786781                        //   There may only be one URL link frame of its kind in a tag,
    787782                        //   except when stated otherwise in the frame description
     
    790785                        // URL              <text string>
    791786
    792                         $parsedFrame['url'] = trim($parsedFrame['data']);
     787                        $parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1
    793788                        if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
    794                                 $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url'];
     789                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
    795790                        }
    796791                        unset($parsedFrame['data']);
     
    814809                        $parsedFrame['data_raw']   = (string) substr($parsedFrame['data'], $frame_offset);
    815810
    816                         // http://www.getid3.org/phpBB3/viewtopic.php?t=1369
     811                        // https://www.getid3.org/phpBB3/viewtopic.php?t=1369
    817812                        // "this tag typically contains null terminated strings, which are associated in pairs"
    818813                        // "there are users that use the tag incorrectly"
     
    934929                        $parsedFrame['bitsformsdeviation']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
    935930                        $parsedFrame['data'] = substr($parsedFrame['data'], 10);
     931                        $deviationbitstream = '';
    936932                        while ($frame_offset < strlen($parsedFrame['data'])) {
    937933                                $deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
     
    995991                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    996992                        }
    997                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    998                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    999                                 // if description only contains a BOM or terminator then make it blank
    1000                                 $frame_description = '';
    1001                         }
     993                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     994                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    1002995                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
     996                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
    1003997
    1004998                        $parsedFrame['encodingid']   = $frame_textencoding;
     
    10071001                        $parsedFrame['language']     = $frame_language;
    10081002                        $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
    1009                         $parsedFrame['description']  = $frame_description;
    10101003                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
    10111004                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
     
    10621055
    10631056                                        $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
    1064                                         if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
     1057                                        if (($timestampindex == 0) && (ord($frame_remainingdata[0]) != 0)) {
    10651058                                                // timestamp probably omitted for first data item
    10661059                                        } else {
     
    11031096                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    11041097                                }
    1105                                 $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    1106                                 if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    1107                                         // if description only contains a BOM or terminator then make it blank
    1108                                         $frame_description = '';
    1109                                 }
     1098                                $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     1099                                $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    11101100                                $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
     1101                                $frame_text = $this->RemoveStringTerminator($frame_text, $frame_textencoding_terminator);
    11111102
    11121103                                $parsedFrame['encodingid']   = $frame_textencoding;
     
    11151106                                $parsedFrame['language']     = $frame_language;
    11161107                                $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
    1117                                 $parsedFrame['description']  = $frame_description;
    11181108                                $parsedFrame['data']         = $frame_text;
    11191109                                if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
     
    14081398                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    14091399                                }
    1410                                 $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    1411                                 if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    1412                                         // if description only contains a BOM or terminator then make it blank
    1413                                         $frame_description = '';
     1400                                $parsedFrame['description']   = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     1401                                $parsedFrame['description']   = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
     1402                                $parsedFrame['encodingid']    = $frame_textencoding;
     1403                                $parsedFrame['encoding']      = $this->TextEncodingNameLookup($frame_textencoding);
     1404
     1405                                if ($id3v2_majorversion == 2) {
     1406                                        $parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null;
     1407                                } else {
     1408                                        $parsedFrame['mime']      = isset($frame_mimetype) ? $frame_mimetype : null;
    14141409                                }
    1415                                 $parsedFrame['encodingid']       = $frame_textencoding;
    1416                                 $parsedFrame['encoding']         = $this->TextEncodingNameLookup($frame_textencoding);
    1417 
    1418                                 if ($id3v2_majorversion == 2) {
    1419                                         $parsedFrame['imagetype']    = $frame_imagetype;
    1420                                 } else {
    1421                                         $parsedFrame['mime']         = $frame_mimetype;
    1422                                 }
    1423                                 $parsedFrame['picturetypeid']    = $frame_picturetype;
    1424                                 $parsedFrame['picturetype']      = $this->APICPictureTypeLookup($frame_picturetype);
    1425                                 $parsedFrame['description']      = $frame_description;
    1426                                 $parsedFrame['data']             = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    1427                                 $parsedFrame['datalength']       = strlen($parsedFrame['data']);
    1428 
    1429                                 $parsedFrame['image_mime'] = '';
     1410                                $parsedFrame['picturetypeid'] = $frame_picturetype;
     1411                                $parsedFrame['picturetype']   = $this->APICPictureTypeLookup($frame_picturetype);
     1412                                $parsedFrame['data']          = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
     1413                                $parsedFrame['datalength']    = strlen($parsedFrame['data']);
     1414
     1415                                $parsedFrame['image_mime']    = '';
    14301416                                $imageinfo = array();
    14311417                                if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
    14321418                                        if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
    1433                                                 $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
     1419                                                $parsedFrame['image_mime']       = image_type_to_mime_type($imagechunkcheck[2]);
    14341420                                                if ($imagechunkcheck[0]) {
    14351421                                                        $parsedFrame['image_width']  = $imagechunkcheck[0];
     
    14471433                                                break;
    14481434                                        }
     1435                                        $dir = '';
    14491436                                        if ($this->getid3->option_save_attachments === true) {
    14501437                                                // great
     
    15341521                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    15351522                        }
    1536                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    1537                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    1538                                 // if description only contains a BOM or terminator then make it blank
    1539                                 $frame_description = '';
    1540                         }
     1523                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     1524                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    15411525                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
    15421526
     
    15471531                        $parsedFrame['mime']        = $frame_mimetype;
    15481532                        $parsedFrame['filename']    = $frame_filename;
    1549                         $parsedFrame['description'] = $frame_description;
    15501533                        unset($parsedFrame['data']);
    15511534
     
    16171600
    16181601                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
    1619                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    1620                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    1621                                 // if description only contains a BOM or terminator then make it blank
    1622                                 $frame_description = '';
    1623                         }
     1602                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     1603                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    16241604                        $frame_offset = $frame_terminatorpos + strlen("\x00");
    16251605
    16261606                        $parsedFrame['ownerid']     = $frame_ownerid;
    16271607                        $parsedFrame['data']        = (string) substr($parsedFrame['data'], $frame_offset);
    1628                         $parsedFrame['description'] = $frame_description;
    16291608                        unset($parsedFrame['data']);
    16301609
     
    17221701                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
    17231702
    1724                         $parsedFrame['data']         = (string) substr($parsedFrame['data'], $frame_offset);
     1703                        $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
     1704                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
    17251705                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
    17261706                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
     
    17601740
    17611741                        $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
     1742                        $parsedFrame['seller'] = $this->RemoveStringTerminator($parsedFrame['seller'], $this->TextEncodingTerminatorLookup($frame_textencoding));
    17621743                        unset($parsedFrame['data']);
    17631744
     
    18181799                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    18191800                        }
    1820                         $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
    1821                         if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
    1822                                 // if description only contains a BOM or terminator then make it blank
    1823                                 $frame_description = '';
    1824                         }
     1801                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
     1802                        $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
    18251803                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
    18261804
     
    18391817                        $parsedFrame['receivedas']        = $this->COMRReceivedAsLookup($frame_receivedasid);
    18401818                        $parsedFrame['sellername']        = $frame_sellername;
    1841                         $parsedFrame['description']       = $frame_description;
    18421819                        $parsedFrame['mime']              = $frame_mimetype;
    18431820                        $parsedFrame['logo']              = $frame_sellerlogo;
     
    20031980                        // Start time      $xx xx xx xx
    20041981                        // End time        $xx xx xx xx
    2005             // Start offset    $xx xx xx xx
    2006             // End offset      $xx xx xx xx
    2007             // <Optional embedded sub-frames>
     1982                        // Start offset    $xx xx xx xx
     1983                        // End offset      $xx xx xx xx
     1984                        // <Optional embedded sub-frames>
    20081985
    20091986                        $frame_offset = 0;
     
    20382015                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
    20392016                                                $this->warning('CHAP subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
     2017                                                break;
     2018                                        }
     2019                                        $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
     2020                                        $frame_offset += $subframe['size'];
     2021
     2022                                        $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
     2023                                        $subframe['text']       =     substr($subframe_rawdata, 1);
     2024                                        $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
     2025                                        $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));
     2026                                        switch (substr($encoding_converted_text, 0, 2)) {
     2027                                                case "\xFF\xFE":
     2028                                                case "\xFE\xFF":
     2029                                                        switch (strtoupper($info['id3v2']['encoding'])) {
     2030                                                                case 'ISO-8859-1':
     2031                                                                case 'UTF-8':
     2032                                                                        $encoding_converted_text = substr($encoding_converted_text, 2);
     2033                                                                        // remove unwanted byte-order-marks
     2034                                                                        break;
     2035                                                                default:
     2036                                                                        // ignore
     2037                                                                        break;
     2038                                                        }
     2039                                                        break;
     2040                                                default:
     2041                                                        // do not remove BOM
     2042                                                        break;
     2043                                        }
     2044
     2045                                        switch ($subframe['name']) {
     2046                                                case 'TIT2':
     2047                                                        $parsedFrame['chapter_name']        = $encoding_converted_text;
     2048                                                        $parsedFrame['subframes'][] = $subframe;
     2049                                                        break;
     2050                                                case 'TIT3':
     2051                                                        $parsedFrame['chapter_description'] = $encoding_converted_text;
     2052                                                        $parsedFrame['subframes'][] = $subframe;
     2053                                                        break;
     2054                                                case 'WXXX':
     2055                                                        list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2);
     2056                                                        $parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url'];
     2057                                                        $parsedFrame['subframes'][] = $subframe;
     2058                                                        break;
     2059                                                case 'APIC':
     2060                                                        if (preg_match('#^([^\\x00]+)*\\x00(.)([^\\x00]+)*\\x00(.+)$#s', $subframe['text'], $matches)) {
     2061                                                                list($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata) = $matches;
     2062                                                                $subframe['image_mime']   = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_mime));
     2063                                                                $subframe['picture_type'] = $this->APICPictureTypeLookup($subframe_apic_picturetype);
     2064                                                                $subframe['description']  = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_description));
     2065                                                                if (strlen($this->TextEncodingTerminatorLookup($subframe['encoding'])) == 2) {
     2066                                                                        // the null terminator between "description" and "picture data" could be either 1 byte (ISO-8859-1, UTF-8) or two bytes (UTF-16)
     2067                                                                        // the above regex assumes one byte, if it's actually two then strip the second one here
     2068                                                                        $subframe_apic_picturedata = substr($subframe_apic_picturedata, 1);
     2069                                                                }
     2070                                                                $subframe['data'] = $subframe_apic_picturedata;
     2071                                                                unset($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata);
     2072                                                                unset($subframe['text'], $parsedFrame['text']);
     2073                                                                $parsedFrame['subframes'][] = $subframe;
     2074                                                                $parsedFrame['picture_present'] = true;
     2075                                                        } else {
     2076                                                                $this->warning('ID3v2.CHAP subframe #'.(count($parsedFrame['subframes']) + 1).' "'.$subframe['name'].'" not in expected format');
     2077                                                        }
     2078                                                        break;
     2079                                                default:
     2080                                                        $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (supported: TIT2, TIT3, WXXX, APIC)');
     2081                                                        break;
     2082                                        }
     2083                                }
     2084                                unset($subframe_rawdata, $subframe, $encoding_converted_text);
     2085                                unset($parsedFrame['data']); // debatable whether this this be here, without it the returned structure may contain a large amount of duplicate data if chapters contain APIC
     2086                        }
     2087
     2088                        $id3v2_chapter_entry = array();
     2089                        foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description', 'chapter_url', 'picture_present') as $id3v2_chapter_key) {
     2090                                if (isset($parsedFrame[$id3v2_chapter_key])) {
     2091                                        $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
     2092                                }
     2093                        }
     2094                        if (!isset($info['id3v2']['chapters'])) {
     2095                                $info['id3v2']['chapters'] = array();
     2096                        }
     2097                        $info['id3v2']['chapters'][] = $id3v2_chapter_entry;
     2098                        unset($id3v2_chapter_entry, $id3v2_chapter_key);
     2099
     2100
     2101                } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CTOC')) { // CTOC Chapters Table Of Contents frame (ID3v2.3+ only)
     2102                        // http://id3.org/id3v2-chapters-1.0
     2103                        // <ID3v2.3 or ID3v2.4 frame header, ID: "CTOC">           (10 bytes)
     2104                        // Element ID      <text string> $00
     2105                        // CTOC flags        %xx
     2106                        // Entry count       $xx
     2107                        // Child Element ID  <string>$00   /* zero or more child CHAP or CTOC entries */
     2108                        // <Optional embedded sub-frames>
     2109
     2110                        $frame_offset = 0;
     2111                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
     2112                        $frame_offset += strlen($parsedFrame['element_id']."\x00");
     2113                        $ctoc_flags_raw = ord(substr($parsedFrame['data'], $frame_offset, 1));
     2114                        $frame_offset += 1;
     2115                        $parsedFrame['entry_count'] = ord(substr($parsedFrame['data'], $frame_offset, 1));
     2116                        $frame_offset += 1;
     2117
     2118                        $terminator_position = null;
     2119                        for ($i = 0; $i < $parsedFrame['entry_count']; $i++) {
     2120                                $terminator_position = strpos($parsedFrame['data'], "\x00", $frame_offset);
     2121                                $parsedFrame['child_element_ids'][$i] = substr($parsedFrame['data'], $frame_offset, $terminator_position - $frame_offset);
     2122                                $frame_offset = $terminator_position + 1;
     2123                        }
     2124
     2125                        $parsedFrame['ctoc_flags']['ordered']   = (bool) ($ctoc_flags_raw & 0x01);
     2126                        $parsedFrame['ctoc_flags']['top_level'] = (bool) ($ctoc_flags_raw & 0x03);
     2127
     2128                        unset($ctoc_flags_raw, $terminator_position);
     2129
     2130                        if ($frame_offset < strlen($parsedFrame['data'])) {
     2131                                $parsedFrame['subframes'] = array();
     2132                                while ($frame_offset < strlen($parsedFrame['data'])) {
     2133                                        // <Optional embedded sub-frames>
     2134                                        $subframe = array();
     2135                                        $subframe['name']      =                           substr($parsedFrame['data'], $frame_offset, 4);
     2136                                        $frame_offset += 4;
     2137                                        $subframe['size']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     2138                                        $frame_offset += 4;
     2139                                        $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
     2140                                        $frame_offset += 2;
     2141                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
     2142                                                $this->warning('CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
    20402143                                                break;
    20412144                                        }
     
    20682171                                        if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
    20692172                                                if ($subframe['name'] == 'TIT2') {
    2070                                                         $parsedFrame['chapter_name']        = $encoding_converted_text;
    2071                                                 } elseif ($subframe['name'] == 'TIT3') {
    2072                                                         $parsedFrame['chapter_description'] = $encoding_converted_text;
    2073                                                 }
    2074                                                 $parsedFrame['subframes'][] = $subframe;
    2075                                         } else {
    2076                                                 $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
    2077                                         }
    2078                                 }
    2079                                 unset($subframe_rawdata, $subframe, $encoding_converted_text);
    2080                         }
    2081 
    2082                         $id3v2_chapter_entry = array();
    2083                         foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description') as $id3v2_chapter_key) {
    2084                                 if (isset($parsedFrame[$id3v2_chapter_key])) {
    2085                                         $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
    2086                                 }
    2087                         }
    2088                         if (!isset($info['id3v2']['chapters'])) {
    2089                                 $info['id3v2']['chapters'] = array();
    2090                         }
    2091                         $info['id3v2']['chapters'][] = $id3v2_chapter_entry;
    2092                         unset($id3v2_chapter_entry, $id3v2_chapter_key);
    2093 
    2094 
    2095                 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CTOC')) { // CTOC Chapters Table Of Contents frame (ID3v2.3+ only)
    2096                         // http://id3.org/id3v2-chapters-1.0
    2097                         // <ID3v2.3 or ID3v2.4 frame header, ID: "CTOC">           (10 bytes)
    2098                         // Element ID      <text string> $00
    2099                         // CTOC flags        %xx
    2100                         // Entry count       $xx
    2101                         // Child Element ID  <string>$00   /* zero or more child CHAP or CTOC entries */
    2102             // <Optional embedded sub-frames>
    2103 
    2104                         $frame_offset = 0;
    2105                         @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
    2106                         $frame_offset += strlen($parsedFrame['element_id']."\x00");
    2107                         $ctoc_flags_raw = ord(substr($parsedFrame['data'], $frame_offset, 1));
    2108                         $frame_offset += 1;
    2109                         $parsedFrame['entry_count'] = ord(substr($parsedFrame['data'], $frame_offset, 1));
    2110                         $frame_offset += 1;
    2111 
    2112                         $terminator_position = null;
    2113                         for ($i = 0; $i < $parsedFrame['entry_count']; $i++) {
    2114                                 $terminator_position = strpos($parsedFrame['data'], "\x00", $frame_offset);
    2115                                 $parsedFrame['child_element_ids'][$i] = substr($parsedFrame['data'], $frame_offset, $terminator_position - $frame_offset);
    2116                                 $frame_offset = $terminator_position + 1;
    2117                         }
    2118 
    2119                         $parsedFrame['ctoc_flags']['ordered']   = (bool) ($ctoc_flags_raw & 0x01);
    2120                         $parsedFrame['ctoc_flags']['top_level'] = (bool) ($ctoc_flags_raw & 0x03);
    2121 
    2122                         unset($ctoc_flags_raw, $terminator_position);
    2123 
    2124                         if ($frame_offset < strlen($parsedFrame['data'])) {
    2125                                 $parsedFrame['subframes'] = array();
    2126                                 while ($frame_offset < strlen($parsedFrame['data'])) {
    2127                                         // <Optional embedded sub-frames>
    2128                                         $subframe = array();
    2129                                         $subframe['name']      =                           substr($parsedFrame['data'], $frame_offset, 4);
    2130                                         $frame_offset += 4;
    2131                                         $subframe['size']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
    2132                                         $frame_offset += 4;
    2133                                         $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
    2134                                         $frame_offset += 2;
    2135                                         if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
    2136                                                 $this->warning('CTOS subframe "'.$subframe['name'].'" at frame offset '.$frame_offset.' claims to be "'.$subframe['size'].'" bytes, which is more than the available data ('.(strlen($parsedFrame['data']) - $frame_offset).' bytes)');
    2137                                                 break;
    2138                                         }
    2139                                         $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
    2140                                         $frame_offset += $subframe['size'];
    2141 
    2142                                         $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
    2143                                         $subframe['text']       =     substr($subframe_rawdata, 1);
    2144                                         $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
    2145                                         $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
    2146                                         switch (substr($encoding_converted_text, 0, 2)) {
    2147                                                 case "\xFF\xFE":
    2148                                                 case "\xFE\xFF":
    2149                                                         switch (strtoupper($info['id3v2']['encoding'])) {
    2150                                                                 case 'ISO-8859-1':
    2151                                                                 case 'UTF-8':
    2152                                                                         $encoding_converted_text = substr($encoding_converted_text, 2);
    2153                                                                         // remove unwanted byte-order-marks
    2154                                                                         break;
    2155                                                                 default:
    2156                                                                         // ignore
    2157                                                                         break;
    2158                                                         }
    2159                                                         break;
    2160                                                 default:
    2161                                                         // do not remove BOM
    2162                                                         break;
    2163                                         }
    2164 
    2165                                         if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
    2166                                                 if ($subframe['name'] == 'TIT2') {
    21672173                                                        $parsedFrame['toc_name']        = $encoding_converted_text;
    21682174                                                } elseif ($subframe['name'] == 'TIT3') {
     
    21822188        }
    21832189
    2184 
     2190        /**
     2191         * @param string $data
     2192         *
     2193         * @return string
     2194         */
    21852195        public function DeUnsynchronise($data) {
    21862196                return str_replace("\xFF\x00", "\xFF", $data);
    21872197        }
    21882198
     2199        /**
     2200         * @param int $index
     2201         *
     2202         * @return string
     2203         */
    21892204        public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
    21902205                static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
     
    21972212        }
    21982213
     2214        /**
     2215         * @param int $index
     2216         *
     2217         * @return string
     2218         */
    21992219        public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
    22002220                static $LookupExtendedHeaderRestrictionsTextEncodings = array(
     
    22052225        }
    22062226
     2227        /**
     2228         * @param int $index
     2229         *
     2230         * @return string
     2231         */
    22072232        public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
    22082233                static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
     
    22152240        }
    22162241
     2242        /**
     2243         * @param int $index
     2244         *
     2245         * @return string
     2246         */
    22172247        public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
    22182248                static $LookupExtendedHeaderRestrictionsImageEncoding = array(
     
    22232253        }
    22242254
     2255        /**
     2256         * @param int $index
     2257         *
     2258         * @return string
     2259         */
    22252260        public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
    22262261                static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
     
    22332268        }
    22342269
     2270        /**
     2271         * @param string $currencyid
     2272         *
     2273         * @return string
     2274         */
    22352275        public function LookupCurrencyUnits($currencyid) {
    22362276
     
    24292469        }
    24302470
    2431 
     2471        /**
     2472         * @param string $currencyid
     2473         *
     2474         * @return string
     2475         */
    24322476        public function LookupCurrencyCountry($currencyid) {
    24332477
     
    26252669        }
    26262670
    2627 
    2628 
     2671        /**
     2672         * @param string $languagecode
     2673         * @param bool   $casesensitive
     2674         *
     2675         * @return string
     2676         */
    26292677        public static function LanguageLookup($languagecode, $casesensitive=false) {
    26302678
     
    30823130        }
    30833131
    3084 
     3132        /**
     3133         * @param int $index
     3134         *
     3135         * @return string
     3136         */
    30853137        public static function ETCOEventLookup($index) {
    30863138                if (($index >= 0x17) && ($index <= 0xDF)) {
     
    31263178        }
    31273179
     3180        /**
     3181         * @param int $index
     3182         *
     3183         * @return string
     3184         */
    31283185        public static function SYTLContentTypeLookup($index) {
    31293186                static $SYTLContentTypeLookup = array(
     
    31423199        }
    31433200
     3201        /**
     3202         * @param int   $index
     3203         * @param bool $returnarray
     3204         *
     3205         * @return array|string
     3206         */
    31443207        public static function APICPictureTypeLookup($index, $returnarray=false) {
    31453208                static $APICPictureTypeLookup = array(
     
    31723235        }
    31733236
     3237        /**
     3238         * @param int $index
     3239         *
     3240         * @return string
     3241         */
    31743242        public static function COMRReceivedAsLookup($index) {
    31753243                static $COMRReceivedAsLookup = array(
     
    31883256        }
    31893257
     3258        /**
     3259         * @param int $index
     3260         *
     3261         * @return string
     3262         */
    31903263        public static function RVA2ChannelTypeLookup($index) {
    31913264                static $RVA2ChannelTypeLookup = array(
     
    32043277        }
    32053278
     3279        /**
     3280         * @param string $framename
     3281         *
     3282         * @return string
     3283         */
    32063284        public static function FrameNameLongLookup($framename) {
    32073285
     
    33553433                        UFI     Unique file identifier
    33563434                        UFID    Unique file identifier
    3357                         ULT     Unsychronised lyric/text transcription
     3435                        ULT     Unsynchronised lyric/text transcription
    33583436                        USER    Terms of use
    33593437                        USLT    Unsynchronised lyric/text transcription
     
    33873465        }
    33883466
    3389 
     3467        /**
     3468         * @param string $framename
     3469         *
     3470         * @return string
     3471         */
    33903472        public static function FrameNameShortLookup($framename) {
    33913473
     
    35393621                        UFI     unique_file_identifier
    35403622                        UFID    unique_file_identifier
    3541                         ULT     unsychronised_lyric
     3623                        ULT     unsynchronised_lyric
    35423624                        USER    terms_of_use
    35433625                        USLT    unsynchronised_lyric
     
    35673649        }
    35683650
     3651        /**
     3652         * @param string $encoding
     3653         *
     3654         * @return string
     3655         */
    35693656        public static function TextEncodingTerminatorLookup($encoding) {
    35703657                // http://www.id3.org/id3v2.4.0-structure.txt
     
    35803667        }
    35813668
     3669        /**
     3670         * @param int $encoding
     3671         *
     3672         * @return string
     3673         */
    35823674        public static function TextEncodingNameLookup($encoding) {
    35833675                // http://www.id3.org/id3v2.4.0-structure.txt
     
    35933685        }
    35943686
     3687        /**
     3688         * @param string $string
     3689         * @param string $terminator
     3690         *
     3691         * @return string
     3692         */
     3693        public static function RemoveStringTerminator($string, $terminator) {
     3694                // Null terminator at end of comment string is somewhat ambiguous in the specification, may or may not be implemented by various taggers. Remove terminator only if present.
     3695                // https://github.com/JamesHeinrich/getID3/issues/121
     3696                // https://community.mp3tag.de/t/x-trailing-nulls-in-id3v2-comments/19227
     3697                if (substr($string, -strlen($terminator), strlen($terminator)) === $terminator) {
     3698                        $string = substr($string, 0, -strlen($terminator));
     3699                }
     3700                return $string;
     3701        }
     3702
     3703        /**
     3704         * @param string $string
     3705         *
     3706         * @return string
     3707         */
     3708        public static function MakeUTF16emptyStringEmpty($string) {
     3709                if (in_array($string, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
     3710                        // if string only contains a BOM or terminator then make it actually an empty string
     3711                        $string = '';
     3712                }
     3713                return $string;
     3714        }
     3715
     3716        /**
     3717         * @param string $framename
     3718         * @param int    $id3v2majorversion
     3719         *
     3720         * @return bool|int
     3721         */
    35953722        public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
    35963723                switch ($id3v2majorversion) {
     
    36073734        }
    36083735
     3736        /**
     3737         * @param string $numberstring
     3738         * @param bool   $allowdecimal
     3739         * @param bool   $allownegative
     3740         *
     3741         * @return bool
     3742         */
    36093743        public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
    36103744                for ($i = 0; $i < strlen($numberstring); $i++) {
    3611                         if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
    3612                                 if (($numberstring{$i} == '.') && $allowdecimal) {
     3745                        if ((chr($numberstring[$i]) < chr('0')) || (chr($numberstring[$i]) > chr('9'))) {
     3746                                if (($numberstring[$i] == '.') && $allowdecimal) {
    36133747                                        // allowed
    3614                                 } elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) {
     3748                                } elseif (($numberstring[$i] == '-') && $allownegative && ($i == 0)) {
    36153749                                        // allowed
    36163750                                } else {
     
    36223756        }
    36233757
     3758        /**
     3759         * @param string $datestamp
     3760         *
     3761         * @return bool
     3762         */
    36243763        public static function IsValidDateStampString($datestamp) {
    36253764                if (strlen($datestamp) != 8) {
     
    36503789        }
    36513790
     3791        /**
     3792         * @param int $majorversion
     3793         *
     3794         * @return int
     3795         */
    36523796        public static function ID3v2HeaderLength($majorversion) {
    36533797                return (($majorversion == 2) ? 6 : 10);
    36543798        }
    36553799
     3800        /**
     3801         * @param string $frame_name
     3802         *
     3803         * @return string|false
     3804         */
    36563805        public static function ID3v22iTunesBrokenFrameName($frame_name) {
    36573806                // iTunes (multiple versions) has been known to write ID3v2.3 style frames
     
    37403889
    37413890}
     3891
Note: See TracChangeset for help on using the changeset viewer.