Changeset 92616 in spip-zone


Ignore:
Timestamp:
Nov 2, 2015, 1:27:35 PM (4 years ago)
Author:
brunobergot@…
Message:

version 2.10.25 : maj de la lib getID3 en version 1.9.10

Ne faudrait-il pas ajouter cette lib aux crédits du plugins ainsi que mejs ?

Location:
_core_/plugins/medias
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • _core_/plugins/medias/lib/getid3/extension.cache.mysql.php

    r85814 r92616  
    135135
    136136        // public: analyze file
    137         public function analyze($filename) {
     137        public function analyze($filename, $filesize=null, $original_filename='') {
    138138
    139139                if (file_exists($filename)) {
     
    158158
    159159                // Miss
    160                 $analysis = parent::analyze($filename);
     160                $analysis = parent::analyze($filename, $filesize, $original_filename);
    161161
    162162                // Save result
     
    179179
    180180                $SQLquery  = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` (';
    181                 $SQLquery .=   '`filename` VARCHAR(255) NOT NULL DEFAULT \'\'';
     181                $SQLquery .=   '`filename` VARCHAR(500) NOT NULL DEFAULT \'\'';
    182182                $SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
    183183                $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
    184184                $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
    185                 $SQLquery .= ', `value` TEXT NOT NULL';
     185                $SQLquery .= ', `value` LONGTEXT NOT NULL';
    186186                $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`)) ENGINE=MyISAM';
    187187                $this->cursor = mysql_query($SQLquery, $this->connection);
  • _core_/plugins/medias/lib/getid3/extension.cache.sqlite3.php

    r85814 r92616  
    5050*   sqlite3             table='getid3_cache', hide=false        (PHP5)
    5151*
    52 
    53 ***  database file will be stored in the same directory as this script,
    54 ***  webserver must have write access to that directory!
    55 ***  set $hide to TRUE to prefix db file with .ht to pervent access from web client
    56 ***  this is a default setting in the Apache configuration:
    57 
    58 # The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
    59 
    60 <Files ~ "^\.ht">
    61     Order allow,deny
    62     Deny from all
    63     Satisfy all
    64 </Files>
    65 
     52*
     53* ***  database file will be stored in the same directory as this script,
     54* ***  webserver must have write access to that directory!
     55* ***  set $hide to TRUE to prefix db file with .ht to pervent access from web client
     56* ***  this is a default setting in the Apache configuration:
     57*
     58* The following lines prevent .htaccess and .htpasswd files from being viewed by Web clients.
     59*
     60* <Files ~ "^\.ht">
     61*     Order allow,deny
     62*     Deny from all
     63*     Satisfy all
     64* </Files>
     65*
    6666********************************************************************************
    6767*
     
    160160        * @return boolean
    161161        */
    162         public function analyze($filename) {
     162        public function analyze($filename, $filesize=null, $original_filename='') {
    163163                if (!file_exists($filename)) {
    164164                        return false;
     
    183183                }
    184184                // if it hasn't been analyzed before, then do it now
    185                 $analysis = parent::analyze($filename);
     185                $analysis = parent::analyze($filename, $filesize=null, $original_filename='');
    186186                // Save result
    187187                $sql = $this->cache_file;
     
    254254                                break;
    255255                        case 'make_table':
    256                                 return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
     256                                //return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))";
     257                                return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
    257258                                break;
    258259                        case 'get_cached_dir':
  • _core_/plugins/medias/lib/getid3/getid3.lib.php

    r85814 r92616  
    415415        }
    416416
     417        public static function flipped_array_merge_noclobber($array1, $array2) {
     418                if (!is_array($array1) || !is_array($array2)) {
     419                        return false;
     420                }
     421                # naturally, this only works non-recursively
     422                $newarray = array_flip($array1);
     423                foreach (array_flip($array2) as $key => $val) {
     424                        if (!isset($newarray[$key])) {
     425                                $newarray[$key] = count($newarray);
     426                        }
     427                }
     428                return array_flip($newarray);
     429        }
     430
    417431
    418432        public static function ksort_recursive(&$theArray) {
     
    520534
    521535        public static function XML2array($XMLstring) {
    522                 if (function_exists('simplexml_load_string')) {
    523                         if (function_exists('get_object_vars')) {
    524                                 if (function_exists('libxml_disable_entity_loader')) { // (PHP 5 >= 5.2.11)
    525                                         // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
    526                                         libxml_disable_entity_loader(true);
    527                                 }
    528                                 $XMLobject = simplexml_load_string($XMLstring);
    529                                 return self::SimpleXMLelement2array($XMLobject);
    530                         }
     536                if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
     537                        // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
     538                        // https://core.trac.wordpress.org/changeset/29378
     539                        $loader = libxml_disable_entity_loader(true);
     540                        $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
     541                        $return = self::SimpleXMLelement2array($XMLobject);
     542                        libxml_disable_entity_loader($loader);
     543                        return $return;
    531544                }
    532545                return false;
     
    11671180                                fclose($tmp);
    11681181                                $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
     1182                                if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
     1183                                        return false;
     1184                                }
     1185                                $GetDataImageSize['height'] = $GetDataImageSize[0];
     1186                                $GetDataImageSize['width']  = $GetDataImageSize[1];
    11691187                        }
    11701188                        unlink($tempfilename);
  • _core_/plugins/medias/lib/getid3/getid3.php

    r85814 r92616  
    2929        $temp_dir = '';
    3030}
    31 if (!$temp_dir) {
     31if (!$temp_dir && function_exists('sys_get_temp_dir')) { // sys_get_temp_dir added in PHP v5.2.1
    3232        // sys_get_temp_dir() may give inaccessible temp dir, e.g. with open_basedir on virtual hosts
    3333        $temp_dir = sys_get_temp_dir();
     
    110110        protected $startup_warning = '';
    111111
    112         const VERSION           = '1.9.8-20140511';
     112        const VERSION           = '1.9.10-20150914';
    113113        const FREAD_BUFFER_SIZE = 32768;
    114114
     
    244244
    245245
    246         public function openfile($filename) {
     246        public function openfile($filename, $filesize=null) {
    247247                try {
    248248                        if (!empty($this->startup_error)) {
     
    257257                        $this->info = array();
    258258                        $this->info['GETID3_VERSION']   = $this->version();
    259                         $this->info['php_memory_limit'] = $this->memory_limit;
     259                        $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
    260260
    261261                        // remote files not supported
     
    288288                        }
    289289
    290                         $this->info['filesize'] = filesize($filename);
     290                        $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
    291291                        // set redundant parameters - might be needed in some include file
    292292                        // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
     
    343343
    344344        // public: analyze file
    345         public function analyze($filename) {
     345        public function analyze($filename, $filesize=null, $original_filename='') {
    346346                try {
    347                         if (!$this->openfile($filename)) {
     347                        if (!$this->openfile($filename, $filesize)) {
    348348                                return $this->info;
    349349                        }
     
    390390
    391391                        // determine format
    392                         $determined_format = $this->GetFileFormat($formattest, $filename);
     392                        $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
    393393
    394394                        // unable to determine file format
     
    12361236                                }
    12371237
     1238                                // ID3v1 encoding detection hack start
     1239                                // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
     1240                                // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
     1241                                if ($comment_name == 'id3v1') {
     1242                                        if ($encoding == 'ISO-8859-1') {
     1243                                                if (function_exists('iconv')) {
     1244                                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
     1245                                                                foreach ($valuearray as $key => $value) {
     1246                                                                        if (preg_match('#^[\\x80-\\xFF]+$#', $value)) {
     1247                                                                                foreach (array('windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
     1248                                                                                        if (@iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
     1249                                                                                                $encoding = $id3v1_bad_encoding;
     1250                                                                                                break 3;
     1251                                                                                        }
     1252                                                                                }
     1253                                                                        }
     1254                                                                }
     1255                                                        }
     1256                                                }
     1257                                        }
     1258                                }
     1259                                // ID3v1 encoding detection hack end
     1260
    12381261                                $this->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
    12391262                        }
  • _core_/plugins/medias/lib/getid3/module.archive.gzip.php

    r85814 r92616  
    3737                //+---+---+---+---+---+---+---+---+---+---+
    3838
    39                 if ($info['filesize'] > $info['php_memory_limit']) {
     39                if ($info['php_memory_limit'] && ($info['filesize'] > $info['php_memory_limit'])) {
    4040                        $info['error'][] = 'File is too large ('.number_format($info['filesize']).' bytes) to read into memory (limit: '.number_format($info['php_memory_limit'] / 1048576).'MB)';
    4141                        return false;
     
    5757                                if (!$this->get_os_type(ord($attr['os']))) {
    5858                                        // Merge member with previous if wrong OS type
    59                                         $arr_members[$i - 1] .= $buf;
     59                                        $arr_members[($i - 1)] .= $buf;
    6060                                        $arr_members[$i] = '';
    6161                                        $is_wrong_members = true;
  • _core_/plugins/medias/lib/getid3/module.audio-video.flv.php

    r85814 r92616  
    542542                        default:
    543543                                $value = '(unknown or unsupported data type)';
    544                         break;
     544                                break;
    545545                }
    546546
  • _core_/plugins/medias/lib/getid3/module.audio-video.matroska.php

    r85814 r92616  
    458458                                                        default:
    459459                                                                $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
     460                                                                break;
    460461                                                }
    461462
     
    525526                                                        default:
    526527                                                                $this->unhandledElement('header', __LINE__, $element_data);
     528                                                                break;
    527529                                                }
    528530
     
    563565                                                                                                        default:
    564566                                                                                                                $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry);                                                                                            }
     567                                                                                                                break;
    565568                                                                                        }
    566569
     
    572575                                                                                default:
    573576                                                                                        $this->unhandledElement('seekhead', __LINE__, $seek_entry);
     577                                                                                        break;
    574578                                                                        }
    575579                                                                }
     
    654658                                                                                                                                default:
    655659                                                                                                                                        $this->unhandledElement('track.video', __LINE__, $sub_subelement);
     660                                                                                                                                        break;
    656661                                                                                                                        }
    657662                                                                                                                }
     
    679684                                                                                                                                default:
    680685                                                                                                                                        $this->unhandledElement('track.audio', __LINE__, $sub_subelement);
     686                                                                                                                                        break;
    681687                                                                                                                        }
    682688                                                                                                                }
     
    714720                                                                                                                                                                                default:
    715721                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     722                                                                                                                                                                                        break;
    716723                                                                                                                                                                        }
    717724                                                                                                                                                                }
     
    737744                                                                                                                                                                                default:
    738745                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     746                                                                                                                                                                                        break;
    739747                                                                                                                                                                        }
    740748                                                                                                                                                                }
     
    743751                                                                                                                                                        default:
    744752                                                                                                                                                                $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
     753                                                                                                                                                                break;
    745754                                                                                                                                                }
    746755                                                                                                                                        }
     
    749758                                                                                                                                default:
    750759                                                                                                                                        $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
     760                                                                                                                                        break;
    751761                                                                                                                        }
    752762                                                                                                                }
     
    755765                                                                                                        default:
    756766                                                                                                                $this->unhandledElement('track', __LINE__, $subelement);
     767                                                                                                                break;
    757768                                                                                                }
    758769                                                                                        }
     
    763774                                                                                default:
    764775                                                                                        $this->unhandledElement('tracks', __LINE__, $track_entry);
     776                                                                                        break;
    765777                                                                        }
    766778                                                                }
     
    826838                                                                                                        default:
    827839                                                                                                                $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
     840                                                                                                                break;
    828841                                                                                                }
    829842                                                                                        }
     
    833846                                                                                default:
    834847                                                                                        $this->unhandledElement('info', __LINE__, $subelement);
     848                                                                                        break;
    835849                                                                        }
    836850                                                                }
     
    869883                                                                                                                                default:
    870884                                                                                                                                        $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
     885                                                                                                                                        break;
    871886                                                                                                                        }
    872887                                                                                                                }
     
    880895                                                                                                        default:
    881896                                                                                                                $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
     897                                                                                                                break;
    882898                                                                                                }
    883899                                                                                        }
     
    887903                                                                                default:
    888904                                                                                        $this->unhandledElement('cues', __LINE__, $subelement);
     905                                                                                        break;
    889906                                                                        }
    890907                                                                }
     
    928945                                                                                                                                default:
    929946                                                                                                                                        $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
     947                                                                                                                                        break;
    930948                                                                                                                        }
    931949                                                                                                                }
     
    939957                                                                                                        default:
    940958                                                                                                                $this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
     959                                                                                                                break;
    941960                                                                                                }
    942961                                                                                        }
     
    946965                                                                                default:
    947966                                                                                        $this->unhandledElement('tags', __LINE__, $subelement);
     967                                                                                        break;
    948968                                                                        }
    949969                                                                }
     
    9861006                                                                                                        default:
    9871007                                                                                                                $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
     1008                                                                                                                break;
    9881009                                                                                                }
    9891010                                                                                        }
     
    9931014                                                                                default:
    9941015                                                                                        $this->unhandledElement('attachments', __LINE__, $subelement);
     1016                                                                                        break;
    9951017                                                                        }
    9961018                                                                }
     
    10521074                                                                                                                                                        default:
    10531075                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
     1076                                                                                                                                                                break;
    10541077                                                                                                                                                }
    10551078                                                                                                                                        }
     
    10711094                                                                                                                                                        default:
    10721095                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
     1096                                                                                                                                                                break;
    10731097                                                                                                                                                }
    10741098                                                                                                                                        }
     
    10781102                                                                                                                                default:
    10791103                                                                                                                                        $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
     1104                                                                                                                                        break;
    10801105                                                                                                                        }
    10811106                                                                                                                }
     
    10851110                                                                                                        default:
    10861111                                                                                                                $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
     1112                                                                                                                break;
    10871113                                                                                                }
    10881114                                                                                        }
     
    10921118                                                                                default:
    10931119                                                                                        $this->unhandledElement('chapters', __LINE__, $subelement);
     1120                                                                                        break;
    10941121                                                                        }
    10951122                                                                }
     
    11201147                                                                                                        default:
    11211148                                                                                                                $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
     1149                                                                                                                break;
    11221150                                                                                                }
    11231151                                                                                        }
     
    11501178                                                                                                        default:
    11511179                                                                                                                $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
     1180                                                                                                                break;
    11521181                                                                                                }
    11531182                                                                                        }
     
    11611190                                                                                default:
    11621191                                                                                        $this->unhandledElement('cluster', __LINE__, $subelement);
     1192                                                                                        break;
    11631193                                                                        }
    11641194                                                                        $this->current_offset = $subelement['end'];
     
    11821212                                                        default:
    11831213                                                                $this->unhandledElement('segment', __LINE__, $element_data);
     1214                                                                break;
    11841215                                                }
    11851216                                        }
     
    11881219                                default:
    11891220                                        $this->unhandledElement('root', __LINE__, $top_element);
     1221                                        break;
    11901222                        }
    11911223                }
     
    13401372                                default:
    13411373                                        $this->unhandledElement('tag.simpletag', __LINE__, $element);
     1374                                        break;
    13421375                        }
    13431376                }
  • _core_/plugins/medias/lib/getid3/module.audio-video.quicktime.php

    r85814 r92616  
    3636                $offset      = 0;
    3737                $atomcounter = 0;
    38 
     38                $atom_data_read_buffer_size = ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 2) : $this->getid3->option_fread_buffer_size * 1024); // allow [default: 32MB] if PHP configured with no memory_limit
    3939                while ($offset < $info['avdataend']) {
    4040                        if (!getid3_lib::intValueSupported($offset)) {
     
    6969                        }
    7070                        $atomHierarchy = array();
    71                         $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, round($this->getid3->memory_limit / 2))), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
     71                        $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
    7272
    7373                        $offset += $atomsize;
     
    121121        public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
    122122                // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
     123                // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
    123124
    124125                $info = &$this->getid3->info;
     
    223224
    224225
     226                        case "\xA9".'alb': // ALBum
     227                        case "\xA9".'ART': //
     228                        case "\xA9".'art': // ARTist
     229                        case "\xA9".'aut': //
     230                        case "\xA9".'cmt': // CoMmenT
     231                        case "\xA9".'com': // COMposer
     232                        case "\xA9".'cpy': //
     233                        case "\xA9".'day': // content created year
     234                        case "\xA9".'dir': //
     235                        case "\xA9".'ed1': //
     236                        case "\xA9".'ed2': //
     237                        case "\xA9".'ed3': //
     238                        case "\xA9".'ed4': //
     239                        case "\xA9".'ed5': //
     240                        case "\xA9".'ed6': //
     241                        case "\xA9".'ed7': //
     242                        case "\xA9".'ed8': //
     243                        case "\xA9".'ed9': //
     244                        case "\xA9".'enc': //
     245                        case "\xA9".'fmt': //
     246                        case "\xA9".'gen': // GENre
     247                        case "\xA9".'grp': // GRouPing
     248                        case "\xA9".'hst': //
     249                        case "\xA9".'inf': //
     250                        case "\xA9".'lyr': // LYRics
     251                        case "\xA9".'mak': //
     252                        case "\xA9".'mod': //
     253                        case "\xA9".'nam': // full NAMe
     254                        case "\xA9".'ope': //
     255                        case "\xA9".'PRD': //
     256                        case "\xA9".'prf': //
     257                        case "\xA9".'req': //
     258                        case "\xA9".'src': //
     259                        case "\xA9".'swr': //
     260                        case "\xA9".'too': // encoder
     261                        case "\xA9".'trk': // TRacK
     262                        case "\xA9".'url': //
     263                        case "\xA9".'wrn': //
     264                        case "\xA9".'wrt': // WRiTer
     265                        case '----': // itunes specific
    225266                        case 'aART': // Album ARTist
     267                        case 'akID': // iTunes store account type
     268                        case 'apID': // Purchase Account
     269                        case 'atID': //
    226270                        case 'catg': // CaTeGory
     271                        case 'cmID': //
     272                        case 'cnID': //
    227273                        case 'covr': // COVeR artwork
    228274                        case 'cpil': // ComPILation
     
    231277                        case 'disk': // DISK number
    232278                        case 'egid': // Episode Global ID
     279                        case 'geID': //
    233280                        case 'gnre': // GeNRE
     281                        case 'hdvd': // HD ViDeo
    234282                        case 'keyw': // KEYWord
    235                         case 'ldes':
     283                        case 'ldes': // Long DEScription
    236284                        case 'pcst': // PodCaST
    237285                        case 'pgap': // GAPless Playback
     286                        case 'plID': //
    238287                        case 'purd': // PURchase Date
    239288                        case 'purl': // Podcast URL
    240                         case 'rati':
    241                         case 'rndu':
    242                         case 'rpdu':
     289                        case 'rati': //
     290                        case 'rndu': //
     291                        case 'rpdu': //
    243292                        case 'rtng': // RaTiNG
    244                         case 'stik':
     293                        case 'sfID': // iTunes store country
     294                        case 'soaa': // SOrt Album Artist
     295                        case 'soal': // SOrt ALbum
     296                        case 'soar': // SOrt ARtist
     297                        case 'soco': // SOrt COmposer
     298                        case 'sonm': // SOrt NaMe
     299                        case 'sosn': // SOrt Show Name
     300                        case 'stik': //
    245301                        case 'tmpo': // TeMPO (BPM)
    246302                        case 'trkn': // TRacK Number
     303                        case 'tven': // tvEpisodeID
    247304                        case 'tves': // TV EpiSode
    248305                        case 'tvnn': // TV Network Name
    249306                        case 'tvsh': // TV SHow Name
    250307                        case 'tvsn': // TV SeasoN
    251                         case 'akID': // iTunes store account type
    252                         case 'apID':
    253                         case 'atID':
    254                         case 'cmID':
    255                         case 'cnID':
    256                         case 'geID':
    257                         case 'plID':
    258                         case 'sfID': // iTunes store country
    259                         case "\xA9".'alb': // ALBum
    260                         case "\xA9".'art': // ARTist
    261                         case "\xA9".'ART':
    262                         case "\xA9".'aut':
    263                         case "\xA9".'cmt': // CoMmenT
    264                         case "\xA9".'com': // COMposer
    265                         case "\xA9".'cpy':
    266                         case "\xA9".'day': // content created year
    267                         case "\xA9".'dir':
    268                         case "\xA9".'ed1':
    269                         case "\xA9".'ed2':
    270                         case "\xA9".'ed3':
    271                         case "\xA9".'ed4':
    272                         case "\xA9".'ed5':
    273                         case "\xA9".'ed6':
    274                         case "\xA9".'ed7':
    275                         case "\xA9".'ed8':
    276                         case "\xA9".'ed9':
    277                         case "\xA9".'enc':
    278                         case "\xA9".'fmt':
    279                         case "\xA9".'gen': // GENre
    280                         case "\xA9".'grp': // GRouPing
    281                         case "\xA9".'hst':
    282                         case "\xA9".'inf':
    283                         case "\xA9".'lyr': // LYRics
    284                         case "\xA9".'mak':
    285                         case "\xA9".'mod':
    286                         case "\xA9".'nam': // full NAMe
    287                         case "\xA9".'ope':
    288                         case "\xA9".'PRD':
    289                         case "\xA9".'prd':
    290                         case "\xA9".'prf':
    291                         case "\xA9".'req':
    292                         case "\xA9".'src':
    293                         case "\xA9".'swr':
    294                         case "\xA9".'too': // encoder
    295                         case "\xA9".'trk': // TRacK
    296                         case "\xA9".'url':
    297                         case "\xA9".'wrn':
    298                         case "\xA9".'wrt': // WRiTer
    299                         case '----': // itunes specific
    300308                                if ($atom_parent == 'udta') {
    301309                                        // User data atom handler
     
    362370                                                                                        switch ($atomname) {
    363371                                                                                                case 'cpil':
     372                                                                                                case 'hdvd':
    364373                                                                                                case 'pcst':
    365374                                                                                                case 'pgap':
     375                                                                                                        // 8-bit integer (boolean)
    366376                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    367377                                                                                                        break;
    368378
    369379                                                                                                case 'tmpo':
     380                                                                                                        // 16-bit integer
    370381                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
    371382                                                                                                        break;
     
    373384                                                                                                case 'disk':
    374385                                                                                                case 'trkn':
     386                                                                                                        // binary
    375387                                                                                                        $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
    376388                                                                                                        $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
     
    380392
    381393                                                                                                case 'gnre':
     394                                                                                                        // enum
    382395                                                                                                        $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    383396                                                                                                        $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
     
    385398
    386399                                                                                                case 'rtng':
     400                                                                                                        // 8-bit integer
    387401                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    388402                                                                                                        $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
     
    390404
    391405                                                                                                case 'stik':
     406                                                                                                        // 8-bit integer (enum)
    392407                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    393408                                                                                                        $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
     
    395410
    396411                                                                                                case 'sfID':
     412                                                                                                        // 32-bit integer
    397413                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    398414                                                                                                        $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
     
    404420                                                                                                        break;
    405421
     422                                                                                                case 'plID':
     423                                                                                                        // 64-bit integer
     424                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
     425
     426                                                                                                case 'atID':
     427                                                                                                case 'cnID':
     428                                                                                                case 'geID':
     429                                                                                                case 'tves':
     430                                                                                                case 'tvsn':
    406431                                                                                                default:
     432                                                                                                        // 32-bit integer
    407433                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    408434                                                                                        }
     
    800826                                $frames_count = 0;
    801827
    802                                 $max_stts_entries_to_scan = min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']);
     828                                $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
    803829                                if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
    804                                         $info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($this->getid3->memory_limit / 1048576).'MB).';
     830                                        $info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).';
    805831                                }
    806832                                for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
     
    14001426                        case 'meta': // METAdata atom
    14011427                                // some kind of metacontainer, may contain a big data dump such as:
    1402                                 // mdta keys mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst
    1403   data DEApple 0 (data DE2011-05-11T17:54:04+0200 2 *data DE+52.4936+013.3897+040.247/
    1404   data DE4.3.1 data DEiPhone 4
     1428                                // 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
    14051429                                // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
    14061430
     
    21142138                static $handyatomtranslatorarray = array();
    21152139                if (empty($handyatomtranslatorarray)) {
     2140                        // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
     2141                        // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
     2142                        // http://atomicparsley.sourceforge.net/mpeg-4files.html
     2143                        // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
     2144                        $handyatomtranslatorarray["\xA9".'alb'] = 'album';               // iTunes 4.0
     2145                        $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
     2146                        $handyatomtranslatorarray["\xA9".'art'] = 'artist';              // iTunes 4.0
     2147                        $handyatomtranslatorarray["\xA9".'aut'] = 'author';
     2148                        $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';             // iTunes 4.0
     2149                        $handyatomtranslatorarray["\xA9".'com'] = 'comment';
    21162150                        $handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
    2117                         $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';    // iTunes 4.0
     2151                        $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';       // iTunes 4.0
    21182152                        $handyatomtranslatorarray["\xA9".'dir'] = 'director';
    21192153                        $handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
     
    21262160                        $handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
    21272161                        $handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
     2162                        $handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by';
    21282163                        $handyatomtranslatorarray["\xA9".'fmt'] = 'format';
     2164                        $handyatomtranslatorarray["\xA9".'gen'] = 'genre';               // iTunes 4.0
     2165                        $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';            // iTunes 4.2
     2166                        $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
    21292167                        $handyatomtranslatorarray["\xA9".'inf'] = 'information';
     2168                        $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';              // iTunes 5.0
     2169                        $handyatomtranslatorarray["\xA9".'mak'] = 'make';
     2170                        $handyatomtranslatorarray["\xA9".'mod'] = 'model';
     2171                        $handyatomtranslatorarray["\xA9".'nam'] = 'title';               // iTunes 4.0
     2172                        $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
    21302173                        $handyatomtranslatorarray["\xA9".'prd'] = 'producer';
     2174                        $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
    21312175                        $handyatomtranslatorarray["\xA9".'prf'] = 'performers';
    21322176                        $handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
    21332177                        $handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
    2134                         $handyatomtranslatorarray["\xA9".'wrt'] = 'writer';
    2135 
    2136                         // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
    2137                         $handyatomtranslatorarray["\xA9".'nam'] = 'title';           // iTunes 4.0
    2138                         $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';         // iTunes 4.0
     2178                        $handyatomtranslatorarray["\xA9".'swr'] = 'software';
     2179                        $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
     2180                        $handyatomtranslatorarray["\xA9".'trk'] = 'track';
     2181                        $handyatomtranslatorarray["\xA9".'url'] = 'url';
    21392182                        $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
    2140                         $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
    2141                         $handyatomtranslatorarray["\xA9".'mak'] = 'make';
    2142                         $handyatomtranslatorarray["\xA9".'mod'] = 'model';
    2143                         $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
    2144                         $handyatomtranslatorarray["\xA9".'swr'] = 'software';
    2145                         $handyatomtranslatorarray["\xA9".'aut'] = 'author';
    2146                         $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
    2147                         $handyatomtranslatorarray["\xA9".'trk'] = 'track';
    2148                         $handyatomtranslatorarray["\xA9".'alb'] = 'album';           // iTunes 4.0
    2149                         $handyatomtranslatorarray["\xA9".'com'] = 'comment';
    2150                         $handyatomtranslatorarray["\xA9".'gen'] = 'genre';           // iTunes 4.0
    2151                         $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
    2152                         $handyatomtranslatorarray["\xA9".'url'] = 'url';
    2153                         $handyatomtranslatorarray["\xA9".'enc'] = 'encoder';
    2154 
    2155                         // http://atomicparsley.sourceforge.net/mpeg-4files.html
    2156                         $handyatomtranslatorarray["\xA9".'art'] = 'artist';           // iTunes 4.0
     2183                        $handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
    21572184                        $handyatomtranslatorarray['aART'] = 'album_artist';
    2158                         $handyatomtranslatorarray['trkn'] = 'track_number';     // iTunes 4.0
    2159                         $handyatomtranslatorarray['disk'] = 'disc_number';      // iTunes 4.0
    2160                         $handyatomtranslatorarray['gnre'] = 'genre';            // iTunes 4.0
    2161                         $handyatomtranslatorarray["\xA9".'too'] = 'encoder';          // iTunes 4.0
    2162                         $handyatomtranslatorarray['tmpo'] = 'bpm';              // iTunes 4.0
    2163                         $handyatomtranslatorarray['cprt'] = 'copyright';        // iTunes 4.0?
    2164                         $handyatomtranslatorarray['cpil'] = 'compilation';      // iTunes 4.0
    2165                         $handyatomtranslatorarray['covr'] = 'picture';          // iTunes 4.0
    2166                         $handyatomtranslatorarray['rtng'] = 'rating';           // iTunes 4.0
    2167                         $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';         // iTunes 4.2
    2168                         $handyatomtranslatorarray['stik'] = 'stik';             // iTunes 4.9
    2169                         $handyatomtranslatorarray['pcst'] = 'podcast';          // iTunes 4.9
    2170                         $handyatomtranslatorarray['catg'] = 'category';         // iTunes 4.9
    2171                         $handyatomtranslatorarray['keyw'] = 'keyword';          // iTunes 4.9
    2172                         $handyatomtranslatorarray['purl'] = 'podcast_url';      // iTunes 4.9
    2173                         $handyatomtranslatorarray['egid'] = 'episode_guid';     // iTunes 4.9
    2174                         $handyatomtranslatorarray['desc'] = 'description';      // iTunes 5.0
    2175                         $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';           // iTunes 5.0
    2176                         $handyatomtranslatorarray['tvnn'] = 'tv_network_name';  // iTunes 6.0
    2177                         $handyatomtranslatorarray['tvsh'] = 'tv_show_name';     // iTunes 6.0
    2178                         $handyatomtranslatorarray['tvsn'] = 'tv_season';        // iTunes 6.0
    2179                         $handyatomtranslatorarray['tves'] = 'tv_episode';       // iTunes 6.0
    2180                         $handyatomtranslatorarray['purd'] = 'purchase_date';    // iTunes 6.0.2
    2181                         $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
    2182 
    2183                         // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
    2184 
    2185 
     2185                        $handyatomtranslatorarray['apID'] = 'purchase_account';
     2186                        $handyatomtranslatorarray['catg'] = 'category';            // iTunes 4.9
     2187                        $handyatomtranslatorarray['covr'] = 'picture';             // iTunes 4.0
     2188                        $handyatomtranslatorarray['cpil'] = 'compilation';         // iTunes 4.0
     2189                        $handyatomtranslatorarray['cprt'] = 'copyright';           // iTunes 4.0?
     2190                        $handyatomtranslatorarray['desc'] = 'description';         // iTunes 5.0
     2191                        $handyatomtranslatorarray['disk'] = 'disc_number';         // iTunes 4.0
     2192                        $handyatomtranslatorarray['egid'] = 'episode_guid';        // iTunes 4.9
     2193                        $handyatomtranslatorarray['gnre'] = 'genre';               // iTunes 4.0
     2194                        $handyatomtranslatorarray['hdvd'] = 'hd_video';            // iTunes 4.0
     2195                        $handyatomtranslatorarray['ldes'] = 'description_long';    //
     2196                        $handyatomtranslatorarray['keyw'] = 'keyword';             // iTunes 4.9
     2197                        $handyatomtranslatorarray['pcst'] = 'podcast';             // iTunes 4.9
     2198                        $handyatomtranslatorarray['pgap'] = 'gapless_playback';    // iTunes 7.0
     2199                        $handyatomtranslatorarray['purd'] = 'purchase_date';       // iTunes 6.0.2
     2200                        $handyatomtranslatorarray['purl'] = 'podcast_url';         // iTunes 4.9
     2201                        $handyatomtranslatorarray['rtng'] = 'rating';              // iTunes 4.0
     2202                        $handyatomtranslatorarray['soaa'] = 'sort_album_artist';   //
     2203                        $handyatomtranslatorarray['soal'] = 'sort_album';          //
     2204                        $handyatomtranslatorarray['soar'] = 'sort_artist';         //
     2205                        $handyatomtranslatorarray['soco'] = 'sort_composer';       //
     2206                        $handyatomtranslatorarray['sonm'] = 'sort_title';          //
     2207                        $handyatomtranslatorarray['sosn'] = 'sort_show';           //
     2208                        $handyatomtranslatorarray['stik'] = 'stik';                // iTunes 4.9
     2209                        $handyatomtranslatorarray['tmpo'] = 'bpm';                 // iTunes 4.0
     2210                        $handyatomtranslatorarray['trkn'] = 'track_number';        // iTunes 4.0
     2211                        $handyatomtranslatorarray['tven'] = 'tv_episode_id';       //
     2212                        $handyatomtranslatorarray['tves'] = 'tv_episode';          // iTunes 6.0
     2213                        $handyatomtranslatorarray['tvnn'] = 'tv_network_name';     // iTunes 6.0
     2214                        $handyatomtranslatorarray['tvsh'] = 'tv_show_name';        // iTunes 6.0
     2215                        $handyatomtranslatorarray['tvsn'] = 'tv_season';           // iTunes 6.0
    21862216
    21872217                        // boxnames:
  • _core_/plugins/medias/lib/getid3/module.audio.flac.php

    r85814 r92616  
    136136                        foreach ($info['flac']['PICTURE'] as $entry) {
    137137                                if (!empty($entry['data'])) {
    138                                         $info['flac']['comments']['picture'][] = array('image_mime'=>$entry['image_mime'], 'data'=>$entry['data']);
     138                                        if (!isset($info['flac']['comments']['picture'])) {
     139                                                $info['flac']['comments']['picture'] = array();
     140                                        }
     141                                        $comments_picture_data = array();
     142                                        foreach (array('data', 'image_mime', 'image_width', 'image_height', 'imagetype', 'picturetype', 'description', 'datalength') as $picture_key) {
     143                                                if (isset($entry[$picture_key])) {
     144                                                        $comments_picture_data[$picture_key] = $entry[$picture_key];
     145                                                }
     146                                        }
     147                                        $info['flac']['comments']['picture'][] = $comments_picture_data;
     148                                        unset($comments_picture_data);
    139149                                }
    140150                        }
     
    344354
    345355                $picture['typeid']         = getid3_lib::BigEndian2Int($this->fread(4));
    346                 $picture['type']           = self::pictureTypeLookup($picture['typeid']);
     356                $picture['picturetype']    = self::pictureTypeLookup($picture['typeid']);
    347357                $picture['image_mime']     = $this->fread(getid3_lib::BigEndian2Int($this->fread(4)));
    348358                $descr_length              = getid3_lib::BigEndian2Int($this->fread(4));
     
    350360                        $picture['description'] = $this->fread($descr_length);
    351361                }
    352                 $picture['width']          = getid3_lib::BigEndian2Int($this->fread(4));
    353                 $picture['height']         = getid3_lib::BigEndian2Int($this->fread(4));
     362                $picture['image_width']    = getid3_lib::BigEndian2Int($this->fread(4));
     363                $picture['image_height']   = getid3_lib::BigEndian2Int($this->fread(4));
    354364                $picture['color_depth']    = getid3_lib::BigEndian2Int($this->fread(4));
    355365                $picture['colors_indexed'] = getid3_lib::BigEndian2Int($this->fread(4));
    356                 $data_length               = getid3_lib::BigEndian2Int($this->fread(4));
     366                $picture['datalength']     = getid3_lib::BigEndian2Int($this->fread(4));
    357367
    358368                if ($picture['image_mime'] == '-->') {
    359                         $picture['data'] = $this->fread($data_length);
     369                        $picture['data'] = $this->fread($picture['datalength']);
    360370                } else {
    361371                        $picture['data'] = $this->saveAttachment(
    362                                 str_replace('/', '_', $picture['type']).'_'.$this->ftell(),
     372                                str_replace('/', '_', $picture['picturetype']).'_'.$this->ftell(),
    363373                                $this->ftell(),
    364                                 $data_length,
     374                                $picture['datalength'],
    365375                                $picture['image_mime']);
    366376                }
  • _core_/plugins/medias/lib/getid3/module.audio.mp3.php

    r85814 r92616  
    438438
    439439                $head4 = substr($headerstring, 0, 4);
    440 
    441440                static $MPEGaudioHeaderDecodeCache = array();
    442441                if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
     
    649648
    650649                                //if (($thisfile_mpeg_audio['bitrate'] == 'free') && !empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
    651                                 if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
    652 
    653                                         $framelengthfloat = $thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames'];
     650                                //if (!empty($thisfile_mpeg_audio['VBR_frames']) && !empty($thisfile_mpeg_audio['VBR_bytes'])) {
     651                                if (!empty($thisfile_mpeg_audio['VBR_frames'])) {
     652                                        $used_filesize  = 0;
     653                                        if (!empty($thisfile_mpeg_audio['VBR_bytes'])) {
     654                                                $used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
     655                                        } elseif (!empty($info['filesize'])) {
     656                                                $used_filesize  = $info['filesize'];
     657                                                $used_filesize -= intval(@$info['id3v2']['headerlength']);
     658                                                $used_filesize -= (isset($info['id3v1']) ? 128 : 0);
     659                                                $used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
     660                                                $info['warning'][] = 'MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes';
     661                                        }
     662
     663                                        $framelengthfloat = $used_filesize / $thisfile_mpeg_audio['VBR_frames'];
    654664
    655665                                        if ($thisfile_mpeg_audio['layer'] == '1') {
     
    949959                                        $thisfile_mpeg_audio['VBR_bitrate'] = (isset($thisfile_mpeg_audio['VBR_bytes']) ? (($thisfile_mpeg_audio['VBR_bytes'] / $thisfile_mpeg_audio['VBR_frames']) * 8) * ($info['audio']['sample_rate'] / $bytes_per_frame) : 0);
    950960                                        if ($thisfile_mpeg_audio['VBR_bitrate'] > 0) {
    951                                                 $info['audio']['bitrate']         = $thisfile_mpeg_audio['VBR_bitrate'];
     961                                                $info['audio']['bitrate']       = $thisfile_mpeg_audio['VBR_bitrate'];
    952962                                                $thisfile_mpeg_audio['bitrate'] = $thisfile_mpeg_audio['VBR_bitrate']; // to avoid confusion
    953963                                        }
  • _core_/plugins/medias/lib/getid3/module.audio.ogg.php

    r85814 r92616  
    6363
    6464                        $this->ParseVorbisPageHeader($filedata, $filedataoffset, $oggpageinfo);
     65
     66                } elseif (substr($filedata, 0, 8) == 'OpusHead') {
     67
     68                        if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) {
     69                                return false;
     70                        }
    6571
    6672                } elseif (substr($filedata, 0, 8) == 'Speex   ') {
     
    256262                } else {
    257263
    258                         $info['error'][] = 'Expecting either "Speex   " or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"';
     264                        $info['error'][] = 'Expecting either "Speex   ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"';
    259265                        unset($info['ogg']);
    260266                        unset($info['mime_type']);
     
    289295                                $this->ParseVorbisComments();
    290296                                break;
    291                 }
    292 
     297
     298                        case 'opus':
     299                                $filedata = $this->fread($info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['page_length']);
     300                                $info['ogg']['pageheader'][$oggpageinfo['page_seqno']]['stream_type'] = substr($filedata, 0, 8); // hard-coded to 'OpusTags'
     301                                if(substr($filedata, 0, 8)  != 'OpusTags') {
     302                                        $info['error'][] = 'Expected "OpusTags" as header but got "'.substr($filedata, 0, 8).'"';
     303                                        return false;
     304                                }
     305
     306                                $this->ParseVorbisComments();
     307                                break;
     308
     309                }
    293310
    294311                // Last Page - Number of Samples
     
    409426                return true;
    410427        }
     428
     429        // http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
     430        public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
     431                $info = &$this->getid3->info;
     432                $info['audio']['dataformat']   = 'opus';
     433                $info['mime_type']             = 'audio/ogg; codecs=opus';
     434
     435                /** @todo find a usable way to detect abr (vbr that is padded to be abr) */
     436                $info['audio']['bitrate_mode'] = 'vbr';
     437
     438                $info['audio']['lossless']     = false;
     439
     440                $info['ogg']['pageheader']['opus']['opus_magic'] = substr($filedata, $filedataoffset, 8); // hard-coded to 'OpusHead'
     441                $filedataoffset += 8;
     442                $info['ogg']['pageheader']['opus']['version']    = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
     443                $filedataoffset += 1;
     444
     445                if ($info['ogg']['pageheader']['opus']['version'] < 1 || $info['ogg']['pageheader']['opus']['version'] > 15) {
     446                        $info['error'][] = 'Unknown opus version number (only accepting 1-15)';
     447                        return false;
     448                }
     449
     450                $info['ogg']['pageheader']['opus']['out_channel_count'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
     451                $filedataoffset += 1;
     452
     453                if ($info['ogg']['pageheader']['opus']['out_channel_count'] == 0) {
     454                        $info['error'][] = 'Invalid channel count in opus header (must not be zero)';
     455                        return false;
     456                }
     457
     458                $info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
     459                $filedataoffset += 2;
     460
     461                $info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
     462                $filedataoffset += 4;
     463
     464                //$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
     465                //$filedataoffset += 2;
     466
     467                //$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
     468                //$filedataoffset += 1;
     469
     470                $info['opus']['opus_version']      = $info['ogg']['pageheader']['opus']['version'];
     471                $info['opus']['sample_rate']       = $info['ogg']['pageheader']['opus']['sample_rate'];
     472                $info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
     473
     474                $info['audio']['channels']      = $info['opus']['out_channel_count'];
     475                $info['audio']['sample_rate']   = $info['opus']['sample_rate'];
     476                return true;
     477        }
     478
    411479
    412480        public function ParseOggPageHeader() {
     
    472540                        case 'vorbis':
    473541                        case 'speex':
     542                        case 'opus':
    474543                                $CommentStartOffset = $info['ogg']['pageheader'][$VorbisCommentPage]['page_start_offset'];  // Second Ogg page, after header block
    475544                                $this->fseek($CommentStartOffset);
     
    480549                                        $commentdataoffset += (strlen('vorbis') + 1);
    481550                                }
     551                                else if ($info['audio']['dataformat'] == 'opus') {
     552                                        $commentdataoffset += strlen('OpusTags');
     553                                }
     554
    482555                                break;
    483556
     
    490563                        default:
    491564                                return false;
     565                                break;
    492566                }
    493567
     
    505579                $ThisFileInfo_ogg_comments_raw = &$info['ogg']['comments_raw'];
    506580                for ($i = 0; $i < $CommentsCount; $i++) {
     581
     582                        if ($i >= 10000) {
     583                                // https://github.com/owncloud/music/issues/212#issuecomment-43082336
     584                                $info['warning'][] = 'Unexpectedly large number ('.$CommentsCount.') of Ogg comments - breaking after reading '.$i.' comments';
     585                                break;
     586                        }
    507587
    508588                        $ThisFileInfo_ogg_comments_raw[$i]['dataoffset'] = $CommentStartOffset + $commentdataoffset;
     
    616696                                        $ogg->setStringMode($data);
    617697                                        $info['ogg']['comments']['picture'][] = array(
    618                                                 'image_mime' => $imageinfo['mime'],
    619                                                 'data'       => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']),
     698                                                'image_mime'   => $imageinfo['mime'],
     699                                                'datalength'   => strlen($data),
     700                                                'picturetype'  => 'cover art',
     701                                                'image_height' => $imageinfo['height'],
     702                                                'image_width'  => $imageinfo['width'],
     703                                                'data'         => $ogg->saveAttachment('coverart', 0, strlen($data), $imageinfo['mime']),
    620704                                        );
    621705                                        unset($ogg);
  • _core_/plugins/medias/lib/getid3/module.tag.apetag.php

    r85814 r92616  
    139139                        switch ($thisfile_ape_items_current['flags']['item_contents_raw']) {
    140140                                case 0: // UTF-8
    141                                 case 3: // Locator (URL, filename, etc), UTF-8 encoded
    142                                         $thisfile_ape_items_current['data'] = explode("\x00", trim($thisfile_ape_items_current['data']));
    143                                         break;
    144 
    145                                 default: // binary data
     141                                case 2: // Locator (URL, filename, etc), UTF-8 encoded
     142                                        $thisfile_ape_items_current['data'] = explode("\x00", $thisfile_ape_items_current['data']);
     143                                        break;
     144
     145                                case 1:  // binary data
     146                                default:
    146147                                        break;
    147148                        }
    148149
    149150                        switch (strtolower($item_key)) {
     151                                // http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
    150152                                case 'replaygain_track_gain':
    151                                         $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
    152                                         $thisfile_replaygain['track']['originator'] = 'unspecified';
     153                                        if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
     154                                                $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
     155                                                $thisfile_replaygain['track']['originator'] = 'unspecified';
     156                                        } else {
     157                                                $info['warning'][] = 'MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
     158                                        }
    153159                                        break;
    154160
    155161                                case 'replaygain_track_peak':
    156                                         $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
    157                                         $thisfile_replaygain['track']['originator'] = 'unspecified';
    158                                         if ($thisfile_replaygain['track']['peak'] <= 0) {
    159                                                 $info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
     162                                        if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
     163                                                $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
     164                                                $thisfile_replaygain['track']['originator'] = 'unspecified';
     165                                                if ($thisfile_replaygain['track']['peak'] <= 0) {
     166                                                        $info['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
     167                                                }
     168                                        } else {
     169                                                $info['warning'][] = 'MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
    160170                                        }
    161171                                        break;
    162172
    163173                                case 'replaygain_album_gain':
    164                                         $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
    165                                         $thisfile_replaygain['album']['originator'] = 'unspecified';
     174                                        if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
     175                                                $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
     176                                                $thisfile_replaygain['album']['originator'] = 'unspecified';
     177                                        } else {
     178                                                $info['warning'][] = 'MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
     179                                        }
    166180                                        break;
    167181
    168182                                case 'replaygain_album_peak':
    169                                         $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
    170                                         $thisfile_replaygain['album']['originator'] = 'unspecified';
    171                                         if ($thisfile_replaygain['album']['peak'] <= 0) {
    172                                                 $info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
     183                                        if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
     184                                                $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
     185                                                $thisfile_replaygain['album']['originator'] = 'unspecified';
     186                                                if ($thisfile_replaygain['album']['peak'] <= 0) {
     187                                                        $info['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
     188                                                }
     189                                        } else {
     190                                                $info['warning'][] = 'MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
    173191                                        }
    174192                                        break;
    175193
    176194                                case 'mp3gain_undo':
    177                                         list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]);
    178                                         $thisfile_replaygain['mp3gain']['undo_left']  = intval($mp3gain_undo_left);
    179                                         $thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
    180                                         $thisfile_replaygain['mp3gain']['undo_wrap']  = (($mp3gain_undo_wrap == 'Y') ? true : false);
     195                                        if (preg_match('#^[\\-\\+][0-9]{3},[\\-\\+][0-9]{3},[NW]$#', $thisfile_ape_items_current['data'][0])) {
     196                                                list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]);
     197                                                $thisfile_replaygain['mp3gain']['undo_left']  = intval($mp3gain_undo_left);
     198                                                $thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
     199                                                $thisfile_replaygain['mp3gain']['undo_wrap']  = (($mp3gain_undo_wrap == 'Y') ? true : false);
     200                                        } else {
     201                                                $info['warning'][] = 'MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
     202                                        }
    181203                                        break;
    182204
    183205                                case 'mp3gain_minmax':
    184                                         list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]);
    185                                         $thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
    186                                         $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
     206                                        if (preg_match('#^[0-9]{3},[0-9]{3}$#', $thisfile_ape_items_current['data'][0])) {
     207                                                list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]);
     208                                                $thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
     209                                                $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
     210                                        } else {
     211                                                $info['warning'][] = 'MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
     212                                        }
    187213                                        break;
    188214
    189215                                case 'mp3gain_album_minmax':
    190                                         list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]);
    191                                         $thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
    192                                         $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
     216                                        if (preg_match('#^[0-9]{3},[0-9]{3}$#', $thisfile_ape_items_current['data'][0])) {
     217                                                list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]);
     218                                                $thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
     219                                                $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
     220                                        } else {
     221                                                $info['warning'][] = 'MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"';
     222                                        }
    193223                                        break;
    194224
     
    223253                                case 'cover art (studio)':
    224254                                        // list of possible cover arts from http://taglib-sharp.sourcearchive.com/documentation/2.0.3.0-2/Ape_2Tag_8cs-source.html
     255                                        if (is_array($thisfile_ape_items_current['data'])) {
     256                                                $info['warning'][] = 'APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8';
     257                                                $thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']);
     258                                        }
    225259                                        list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2);
    226260                                        $thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00");
    227261                                        $thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']);
    228262
    229                                         $thisfile_ape_items_current['image_mime'] = '';
    230                                         $imageinfo = array();
    231                                         $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
    232                                         $thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
    233 
    234263                                        do {
     264                                                $thisfile_ape_items_current['image_mime'] = '';
     265                                                $imageinfo = array();
     266                                                $imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
     267                                                if (($imagechunkcheck === false) || !isset($imagechunkcheck[2])) {
     268                                                        $info['warning'][] = 'APEtag "'.$item_key.'" contains invalid image data';
     269                                                        break;
     270                                                }
     271                                                $thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
     272
    235273                                                if ($this->inline_attachments === false) {
    236274                                                        // skip entirely
     
    270308                                                                $info['ape']['comments']['picture'] = array();
    271309                                                        }
    272                                                         $info['ape']['comments']['picture'][] = array('data'=>$thisfile_ape_items_current['data'], 'image_mime'=>$thisfile_ape_items_current['image_mime']);
     310                                                        $comments_picture_data = array();
     311                                                        foreach (array('data', 'image_mime', 'image_width', 'image_height', 'imagetype', 'picturetype', 'description', 'datalength') as $picture_key) {
     312                                                                if (isset($thisfile_ape_items_current[$picture_key])) {
     313                                                                        $comments_picture_data[$picture_key] = $thisfile_ape_items_current[$picture_key];
     314                                                                }
     315                                                        }
     316                                                        $info['ape']['comments']['picture'][] = $comments_picture_data;
     317                                                        unset($comments_picture_data);
    273318                                                }
    274319                                        } while (false);
     
    318363                // "Note: APE Tags 1.0 do not use any of the APE Tag flags.
    319364                // All are set to zero on creation and ignored on reading."
    320                 // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html
     365                // http://wiki.hydrogenaud.io/index.php?title=Ape_Tags_Flags
    321366                $flags['header']            = (bool) ($rawflagint & 0x80000000);
    322367                $flags['footer']            = (bool) ($rawflagint & 0x40000000);
  • _core_/plugins/medias/lib/getid3/module.tag.id3v2.php

    r85814 r92616  
    443443
    444444                if (isset($thisfile_id3v2['comments']['genre'])) {
     445                        $genres = array();
    445446                        foreach ($thisfile_id3v2['comments']['genre'] as $key => $value) {
    446                                 unset($thisfile_id3v2['comments']['genre'][$key]);
    447                                 $thisfile_id3v2['comments'] = getid3_lib::array_merge_noclobber($thisfile_id3v2['comments'], array('genre'=>$this->ParseID3v2GenreString($value)));
    448                         }
     447                                foreach ($this->ParseID3v2GenreString($value) as $genre) {
     448                                        $genres[] = $genre;
     449                                }
     450                        }
     451                        $thisfile_id3v2['comments']['genre'] = array_unique($genres);
     452                        unset($key, $value, $genres, $genre);
    449453                }
    450454
     
    504508                        $genrestring = preg_replace('#\(([0-9]{1,3})\)#', '$1'."\x00", $genrestring);
    505509                }
     510
     511                // note: MusicBrainz Picard incorrectly stores plaintext genres separated by "/" when writing in ID3v2.3 mode, hack-fix here:
     512                // replace / with NULL, then replace back the two ID3v1 genres that legitimately have "/" as part of the single genre name
     513                $genrestring = str_replace('/', "\x00", $genrestring);
     514                $genrestring = str_replace('Pop'."\x00".'Funk', 'Pop/Funk', $genrestring);
     515                $genrestring = str_replace('Rock'."\x00".'Rock', 'Folk/Rock', $genrestring);
     516
    506517                $genre_elements = explode("\x00", $genrestring);
    507518                foreach ($genre_elements as $element) {
     
    626637                        $frame_offset = 0;
    627638                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
    628 
     639                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    629640                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    630641                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
    631                         }
    632                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    633                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     642                                $frame_textencoding_terminator = "\x00";
     643                        }
     644                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     645                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    634646                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    635647                        }
     
    641653                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
    642654
    643                         $parsedFrame['description'] = $frame_description;
    644                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
     655                        $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $frame_description));
     656                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    645657                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
    646658                                $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
     
    718730                        $frame_offset = 0;
    719731                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     732                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    720733                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    721734                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
    722                         }
    723                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    724                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     735                                $frame_textencoding_terminator = "\x00";
     736                        }
     737                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     738                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    725739                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    726740                        }
     
    730744                                $frame_description = '';
    731745                        }
    732                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
    733 
    734                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
    735                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     746                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
     747
     748                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator);
     749                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    736750                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    737751                        }
     
    957971                        $frame_offset = 0;
    958972                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     973                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    959974                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    960975                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     976                                $frame_textencoding_terminator = "\x00";
    961977                        }
    962978                        $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
    963979                        $frame_offset += 3;
    964                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    965                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     980                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     981                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    966982                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    967983                        }
     
    970986                                $frame_description = '';
    971987                        }
    972                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
     988                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    973989
    974990                        $parsedFrame['encodingid']   = $frame_textencoding;
    975991                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
    976992
    977                         $parsedFrame['data']         = $parsedFrame['data'];
    978993                        $parsedFrame['language']     = $frame_language;
    979994                        $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
     
    10031018                        $frame_offset = 0;
    10041019                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     1020                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    10051021                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    10061022                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     1023                                $frame_textencoding_terminator = "\x00";
    10071024                        }
    10081025                        $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
     
    10211038                        while (strlen($frame_remainingdata)) {
    10221039                                $frame_offset = 0;
    1023                                 $frame_terminatorpos = strpos($frame_remainingdata, $this->TextEncodingTerminatorLookup($frame_textencoding));
     1040                                $frame_terminatorpos = strpos($frame_remainingdata, $frame_textencoding_terminator);
    10241041                                if ($frame_terminatorpos === false) {
    10251042                                        $frame_remainingdata = '';
    10261043                                } else {
    1027                                         if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1044                                        if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    10281045                                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    10291046                                        }
    10301047                                        $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
    10311048
    1032                                         $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
     1049                                        $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
    10331050                                        if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
    10341051                                                // timestamp probably omitted for first data item
     
    10611078                                $frame_offset = 0;
    10621079                                $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     1080                                $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    10631081                                if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    10641082                                        $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     1083                                        $frame_textencoding_terminator = "\x00";
    10651084                                }
    10661085                                $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
    10671086                                $frame_offset += 3;
    1068                                 $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1069                                 if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1087                                $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1088                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    10701089                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    10711090                                }
     
    10741093                                        $frame_description = '';
    10751094                                }
    1076                                 $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
     1095                                $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    10771096
    10781097                                $parsedFrame['encodingid']   = $frame_textencoding;
     
    13311350                        $frame_offset = 0;
    13321351                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     1352                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    13331353                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    13341354                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     1355                                $frame_textencoding_terminator = "\x00";
    13351356                        }
    13361357
     
    13681389                                $info['warning'][] = 'data portion of APIC frame is missing at offset '.($parsedFrame['dataoffset'] + 8 + $frame_offset);
    13691390                        } else {
    1370                                 $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1371                                 if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1391                                $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1392                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    13721393                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    13731394                                }
     
    13871408                                $parsedFrame['picturetype']      = $this->APICPictureTypeLookup($frame_picturetype);
    13881409                                $parsedFrame['description']      = $frame_description;
    1389                                 $parsedFrame['data']             = substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)));
     1410                                $parsedFrame['data']             = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
    13901411                                $parsedFrame['datalength']       = strlen($parsedFrame['data']);
    13911412
    13921413                                $parsedFrame['image_mime'] = '';
    13931414                                $imageinfo = array();
    1394                                 $imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo);
    1395                                 if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
    1396                                         $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
    1397                                         if ($imagechunkcheck[0]) {
    1398                                                 $parsedFrame['image_width']  = $imagechunkcheck[0];
    1399                                         }
    1400                                         if ($imagechunkcheck[1]) {
    1401                                                 $parsedFrame['image_height'] = $imagechunkcheck[1];
     1415                                if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
     1416                                        if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
     1417                                                $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
     1418                                                if ($imagechunkcheck[0]) {
     1419                                                        $parsedFrame['image_width']  = $imagechunkcheck[0];
     1420                                                }
     1421                                                if ($imagechunkcheck[1]) {
     1422                                                        $parsedFrame['image_height'] = $imagechunkcheck[1];
     1423                                                }
    14021424                                        }
    14031425                                }
     
    14441466                                                                $info['id3v2']['comments']['picture'] = array();
    14451467                                                        }
    1446                                                         $info['id3v2']['comments']['picture'][] = array('data'=>$parsedFrame['data'], 'image_mime'=>$parsedFrame['image_mime']);
     1468                                                        $comments_picture_data = array();
     1469                                                        foreach (array('data', 'image_mime', 'image_width', 'image_height', 'imagetype', 'picturetype', 'description', 'datalength') as $picture_key) {
     1470                                                                if (isset($parsedFrame[$picture_key])) {
     1471                                                                        $comments_picture_data[$picture_key] = $parsedFrame[$picture_key];
     1472                                                                }
     1473                                                        }
     1474                                                        $info['id3v2']['comments']['picture'][] = $comments_picture_data;
     1475                                                        unset($comments_picture_data);
    14471476                                                }
    14481477                                        }
     
    14631492                        $frame_offset = 0;
    14641493                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     1494                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    14651495                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    14661496                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     1497                                $frame_textencoding_terminator = "\x00";
    14671498                        }
    14681499                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
     
    14731504                        $frame_offset = $frame_terminatorpos + strlen("\x00");
    14741505
    1475                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1476                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1506                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1507                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    14771508                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    14781509                        }
     
    14811512                                $frame_filename = '';
    14821513                        }
    1483                         $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
    1484 
    1485                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1486                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1514                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
     1515
     1516                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1517                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    14871518                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    14881519                        }
     
    14911522                                $frame_description = '';
    14921523                        }
    1493                         $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
     1524                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
    14941525
    14951526                        $parsedFrame['objectdata']  = (string) substr($parsedFrame['data'], $frame_offset);
     
    16081639
    16091640                } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'LINK')) || // 4.20  LINK Linked information
    1610                                 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'LNK'))) {     // 4.22  LNK  Linked information
     1641                                (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'LNK'))) {    // 4.22  LNK  Linked information
    16111642                        //   There may be more than one 'LINK' frame in a tag,
    16121643                        //   but only one with the same contents
     
    16361667                        $parsedFrame['additionaldata'] = (string) substr($parsedFrame['data'], $frame_offset);
    16371668                        if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
    1638                                 $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = utf8_encode($parsedFrame['url']);
     1669                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback_iso88591_utf8($parsedFrame['url']);
    16391670                        }
    16401671                        unset($parsedFrame['data']);
     
    17301761                        $frame_offset = 0;
    17311762                        $frame_textencoding = ord(substr($parsedFrame['data'], $frame_offset++, 1));
     1763                        $frame_textencoding_terminator = $this->TextEncodingTerminatorLookup($frame_textencoding);
    17321764                        if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
    17331765                                $info['warning'][] = 'Invalid text encoding byte ('.$frame_textencoding.') in frame "'.$parsedFrame['frame_name'].'" - defaulting to ISO-8859-1 encoding';
     1766                                $frame_textencoding_terminator = "\x00";
    17341767                        }
    17351768
     
    17531786                        $frame_receivedasid = ord(substr($parsedFrame['data'], $frame_offset++, 1));
    17541787
    1755                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1756                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1788                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1789                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    17571790                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    17581791                        }
     
    17611794                                $frame_sellername = '';
    17621795                        }
    1763                         $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
    1764 
    1765                         $frame_terminatorpos = strpos($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding), $frame_offset);
    1766                         if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding)), 1)) === 0) {
     1796                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
     1797
     1798                        $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator, $frame_offset);
     1799                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
    17671800                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
    17681801                        }
     
    17711804                                $frame_description = '';
    17721805                        }
    1773                         $frame_offset = $frame_terminatorpos + strlen($this->TextEncodingTerminatorLookup($frame_textencoding));
     1806                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
    17741807
    17751808                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
     
    19441977
    19451978                        unset($parsedFrame['data']);
     1979
     1980                } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CHAP')) { // CHAP Chapters frame (ID3v2.3+ only)
     1981                        // http://id3.org/id3v2-chapters-1.0
     1982                        // <ID3v2.3 or ID3v2.4 frame header, ID: "CHAP">           (10 bytes)
     1983                        // Element ID      <text string> $00
     1984                        // Start time      $xx xx xx xx
     1985                        // End time        $xx xx xx xx
     1986            // Start offset    $xx xx xx xx
     1987            // End offset      $xx xx xx xx
     1988            // <Optional embedded sub-frames>
     1989
     1990                        $frame_offset = 0;
     1991                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
     1992                        $frame_offset += strlen($parsedFrame['element_id']."\x00");
     1993                        $parsedFrame['time_begin'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     1994                        $frame_offset += 4;
     1995                        $parsedFrame['time_end']   = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     1996                        $frame_offset += 4;
     1997                        if (substr($parsedFrame['data'], $frame_offset, 4) != "\xFF\xFF\xFF\xFF") {
     1998                                // "If these bytes are all set to 0xFF then the value should be ignored and the start time value should be utilized."
     1999                                $parsedFrame['offset_begin'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     2000                        }
     2001                        $frame_offset += 4;
     2002                        if (substr($parsedFrame['data'], $frame_offset, 4) != "\xFF\xFF\xFF\xFF") {
     2003                                // "If these bytes are all set to 0xFF then the value should be ignored and the start time value should be utilized."
     2004                                $parsedFrame['offset_end']   = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     2005                        }
     2006                        $frame_offset += 4;
     2007
     2008                        if ($frame_offset < strlen($parsedFrame['data'])) {
     2009                                $parsedFrame['subframes'] = array();
     2010                                while ($frame_offset < strlen($parsedFrame['data'])) {
     2011                                        // <Optional embedded sub-frames>
     2012                                        $subframe = array();
     2013                                        $subframe['name']      =                           substr($parsedFrame['data'], $frame_offset, 4);
     2014                                        $frame_offset += 4;
     2015                                        $subframe['size']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     2016                                        $frame_offset += 4;
     2017                                        $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
     2018                                        $frame_offset += 2;
     2019                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
     2020                                                $info['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)';
     2021                                                break;
     2022                                        }
     2023                                        $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
     2024                                        $frame_offset += $subframe['size'];
     2025
     2026                                        $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
     2027                                        $subframe['text']       =     substr($subframe_rawdata, 1);
     2028                                        $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
     2029                                        $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
     2030                                        switch (substr($encoding_converted_text, 0, 2)) {
     2031                                                case "\xFF\xFE":
     2032                                                case "\xFE\xFF":
     2033                                                        switch (strtoupper($info['id3v2']['encoding'])) {
     2034                                                                case 'ISO-8859-1':
     2035                                                                case 'UTF-8':
     2036                                                                        $encoding_converted_text = substr($encoding_converted_text, 2);
     2037                                                                        // remove unwanted byte-order-marks
     2038                                                                        break;
     2039                                                                default:
     2040                                                                        // ignore
     2041                                                                        break;
     2042                                                        }
     2043                                                        break;
     2044                                                default:
     2045                                                        // do not remove BOM
     2046                                                        break;
     2047                                        }
     2048
     2049                                        if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
     2050                                                if ($subframe['name'] == 'TIT2') {
     2051                                                        $parsedFrame['chapter_name']        = $encoding_converted_text;
     2052                                                } elseif ($subframe['name'] == 'TIT3') {
     2053                                                        $parsedFrame['chapter_description'] = $encoding_converted_text;
     2054                                                }
     2055                                                $parsedFrame['subframes'][] = $subframe;
     2056                                        } else {
     2057                                                $info['warning'][] = 'ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)';
     2058                                        }
     2059                                }
     2060                                unset($subframe_rawdata, $subframe, $encoding_converted_text);
     2061                        }
     2062
     2063                        $id3v2_chapter_entry = array();
     2064                        foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description') as $id3v2_chapter_key) {
     2065                                if (isset($parsedFrame[$id3v2_chapter_key])) {
     2066                                        $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
     2067                                }
     2068                        }
     2069                        if (!isset($info['id3v2']['chapters'])) {
     2070                                $info['id3v2']['chapters'] = array();
     2071                        }
     2072                        $info['id3v2']['chapters'][] = $id3v2_chapter_entry;
     2073                        unset($id3v2_chapter_entry, $id3v2_chapter_key);
     2074
     2075
     2076                } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CTOC')) { // CTOC Chapters Table Of Contents frame (ID3v2.3+ only)
     2077                        // http://id3.org/id3v2-chapters-1.0
     2078                        // <ID3v2.3 or ID3v2.4 frame header, ID: "CTOC">           (10 bytes)
     2079                        // Element ID      <text string> $00
     2080                        // CTOC flags        %xx
     2081                        // Entry count       $xx
     2082                        // Child Element ID  <string>$00   /* zero or more child CHAP or CTOC entries */
     2083            // <Optional embedded sub-frames>
     2084
     2085                        $frame_offset = 0;
     2086                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
     2087                        $frame_offset += strlen($parsedFrame['element_id']."\x00");
     2088                        $ctoc_flags_raw = ord(substr($parsedFrame['data'], $frame_offset, 1));
     2089                        $frame_offset += 1;
     2090                        $parsedFrame['entry_count'] = ord(substr($parsedFrame['data'], $frame_offset, 1));
     2091                        $frame_offset += 1;
     2092
     2093                        $terminator_position = null;
     2094                        for ($i = 0; $i < $parsedFrame['entry_count']; $i++) {
     2095                                $terminator_position = strpos($parsedFrame['data'], "\x00", $frame_offset);
     2096                                $parsedFrame['child_element_ids'][$i] = substr($parsedFrame['data'], $frame_offset, $terminator_position - $frame_offset);
     2097                                $frame_offset = $terminator_position + 1;
     2098                        }
     2099
     2100                        $parsedFrame['ctoc_flags']['ordered']   = (bool) ($ctoc_flags_raw & 0x01);
     2101                        $parsedFrame['ctoc_flags']['top_level'] = (bool) ($ctoc_flags_raw & 0x03);
     2102
     2103                        unset($ctoc_flags_raw, $terminator_position);
     2104
     2105                        if ($frame_offset < strlen($parsedFrame['data'])) {
     2106                                $parsedFrame['subframes'] = array();
     2107                                while ($frame_offset < strlen($parsedFrame['data'])) {
     2108                                        // <Optional embedded sub-frames>
     2109                                        $subframe = array();
     2110                                        $subframe['name']      =                           substr($parsedFrame['data'], $frame_offset, 4);
     2111                                        $frame_offset += 4;
     2112                                        $subframe['size']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 4));
     2113                                        $frame_offset += 4;
     2114                                        $subframe['flags_raw'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], $frame_offset, 2));
     2115                                        $frame_offset += 2;
     2116                                        if ($subframe['size'] > (strlen($parsedFrame['data']) - $frame_offset)) {
     2117                                                $info['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)';
     2118                                                break;
     2119                                        }
     2120                                        $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
     2121                                        $frame_offset += $subframe['size'];
     2122
     2123                                        $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
     2124                                        $subframe['text']       =     substr($subframe_rawdata, 1);
     2125                                        $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
     2126                                        $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
     2127                                        switch (substr($encoding_converted_text, 0, 2)) {
     2128                                                case "\xFF\xFE":
     2129                                                case "\xFE\xFF":
     2130                                                        switch (strtoupper($info['id3v2']['encoding'])) {
     2131                                                                case 'ISO-8859-1':
     2132                                                                case 'UTF-8':
     2133                                                                        $encoding_converted_text = substr($encoding_converted_text, 2);
     2134                                                                        // remove unwanted byte-order-marks
     2135                                                                        break;
     2136                                                                default:
     2137                                                                        // ignore
     2138                                                                        break;
     2139                                                        }
     2140                                                        break;
     2141                                                default:
     2142                                                        // do not remove BOM
     2143                                                        break;
     2144                                        }
     2145
     2146                                        if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
     2147                                                if ($subframe['name'] == 'TIT2') {
     2148                                                        $parsedFrame['toc_name']        = $encoding_converted_text;
     2149                                                } elseif ($subframe['name'] == 'TIT3') {
     2150                                                        $parsedFrame['toc_description'] = $encoding_converted_text;
     2151                                                }
     2152                                                $parsedFrame['subframes'][] = $subframe;
     2153                                        } else {
     2154                                                $info['warning'][] = 'ID3v2.CTOC subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)';
     2155                                        }
     2156                                }
     2157                                unset($subframe_rawdata, $subframe, $encoding_converted_text);
     2158                        }
    19462159
    19472160                }
     
    33453558                        255 => "\x00\x00"
    33463559                );
    3347                 return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : '');
     3560                return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00");
    33483561        }
    33493562
  • _core_/plugins/medias/lib/getid3/module.tag.lyrics3.php

    r85814 r92616  
    102102
    103103                        if (!isset($info['ape'])) {
    104                                 $GETID3_ERRORARRAY = &$info['warning'];
    105                                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
    106                                 $getid3_temp = new getID3();
    107                                 $getid3_temp->openfile($this->getid3->filename);
    108                                 $getid3_apetag = new getid3_apetag($getid3_temp);
    109                                 $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
    110                                 $getid3_apetag->Analyze();
    111                                 if (!empty($getid3_temp->info['ape'])) {
    112                                         $info['ape'] = $getid3_temp->info['ape'];
    113                                 }
    114                                 if (!empty($getid3_temp->info['replay_gain'])) {
    115                                         $info['replay_gain'] = $getid3_temp->info['replay_gain'];
    116                                 }
    117                                 unset($getid3_temp, $getid3_apetag);
     104                                if (isset($info['lyrics3']['tag_offset_start'])) {
     105                                        $GETID3_ERRORARRAY = &$info['warning'];
     106                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
     107                                        $getid3_temp = new getID3();
     108                                        $getid3_temp->openfile($this->getid3->filename);
     109                                        $getid3_apetag = new getid3_apetag($getid3_temp);
     110                                        $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
     111                                        $getid3_apetag->Analyze();
     112                                        if (!empty($getid3_temp->info['ape'])) {
     113                                                $info['ape'] = $getid3_temp->info['ape'];
     114                                        }
     115                                        if (!empty($getid3_temp->info['replay_gain'])) {
     116                                                $info['replay_gain'] = $getid3_temp->info['replay_gain'];
     117                                        }
     118                                        unset($getid3_temp, $getid3_apetag);
     119                                } else {
     120                                        $info['warning'][] = 'Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)';
     121                                }
    118122                        }
    119123
  • _core_/plugins/medias/lib/getid3/write.id3v2.php

    r85814 r92616  
    15441544                                                $frame_data = false;
    15451545                                                if ($this->ID3v2FrameIsAllowed($frame_name, $source_data_array)) {
     1546                                                        if(array_key_exists('description', $source_data_array) && array_key_exists('encodingid', $source_data_array) && array_key_exists('encoding', $this->tag_data)) {
     1547                                                                $source_data_array['description'] = getid3_lib::iconv_fallback($this->tag_data['encoding'], $source_data_array['encoding'], $source_data_array['description']);
     1548                                                        }
    15461549                                                        if ($frame_data = $this->GenerateID3v2FrameData($frame_name, $source_data_array)) {
    15471550                                                                $FrameUnsynchronisation = false;
     
    19221925                        $ID3v2ShortFrameNameLookup[2]['isrc']                                             = 'TRC';
    19231926                        $ID3v2ShortFrameNameLookup[2]['tracknumber']                                      = 'TRK';
     1927                        $ID3v2ShortFrameNameLookup[2]['track_number']                                     = 'TRK';
    19241928                        $ID3v2ShortFrameNameLookup[2]['size']                                             = 'TSI';
    19251929                        $ID3v2ShortFrameNameLookup[2]['encoder_settings']                                 = 'TSS';
     
    19421946                        $ID3v2ShortFrameNameLookup[3]['audio_encryption']                                 = 'AENC';
    19431947                        $ID3v2ShortFrameNameLookup[3]['attached_picture']                                 = 'APIC';
     1948                        $ID3v2ShortFrameNameLookup[3]['picture']                                          = 'APIC';
    19441949                        $ID3v2ShortFrameNameLookup[3]['comment']                                          = 'COMM';
    19451950                        $ID3v2ShortFrameNameLookup[3]['commercial']                                       = 'COMR';
     
    19891994                        $ID3v2ShortFrameNameLookup[3]['publisher']                                        = 'TPUB';
    19901995                        $ID3v2ShortFrameNameLookup[3]['tracknumber']                                      = 'TRCK';
     1996                        $ID3v2ShortFrameNameLookup[3]['track_number']                                     = 'TRCK';
    19911997                        $ID3v2ShortFrameNameLookup[3]['internet_radio_station_name']                      = 'TRSN';
    19921998                        $ID3v2ShortFrameNameLookup[3]['internet_radio_station_owner']                     = 'TRSO';
  • _core_/plugins/medias/paquet.xml

    r91085 r92616  
    22        prefix="medias"
    33        categorie="multimedia"
    4         version="2.10.24"
     4        version="2.10.25"
    55        etat="stable"
    66        compatibilite="[3.0.0;3.1.*]"
Note: See TracChangeset for help on using the changeset viewer.