WordPress.org

Make WordPress Core

Ticket #41496: 41496.diff

File 41496.diff, 269.2 KB (added by wonderboymusic, 3 years ago)
  • src/wp-includes/ID3/getid3.lib.php

    diff --git a/src/wp-includes/ID3/getid3.lib.php b/src/wp-includes/ID3/getid3.lib.php
    index 76e2854..1931bb3 100644
    a b class getid3_lib 
    293293                return self::BigEndian2Int(strrev($byteword), false, $signed);
    294294        }
    295295
     296        public static function LittleEndian2Bin($byteword) {
     297                return self::BigEndian2Bin(strrev($byteword));
     298        }
    296299
    297300        public static function BigEndian2Bin($byteword) {
    298301                $binvalue = '';
    class getid3_lib 
    414417                return $newarray;
    415418        }
    416419
     420        public static function flipped_array_merge_noclobber($array1, $array2) {
     421                if (!is_array($array1) || !is_array($array2)) {
     422                        return false;
     423                }
     424                # naturally, this only works non-recursively
     425                $newarray = array_flip($array1);
     426                foreach (array_flip($array2) as $key => $val) {
     427                        if (!isset($newarray[$key])) {
     428                                $newarray[$key] = count($newarray);
     429                        }
     430                }
     431                return array_flip($newarray);
     432        }
     433
    417434
    418435        public static function ksort_recursive(&$theArray) {
    419436                ksort($theArray);
    class getid3_lib 
    946963                        return $string;
    947964                }
    948965
     966                // mb_convert_encoding() availble
     967                if (function_exists('mb_convert_encoding')) {
     968                        if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
     969                                switch ($out_charset) {
     970                                        case 'ISO-8859-1':
     971                                                $converted_string = rtrim($converted_string, "\x00");
     972                                                break;
     973                                }
     974                                return $converted_string;
     975                        }
     976                        return $string;
     977                }
    949978                // iconv() availble
    950                 if (function_exists('iconv')) {
     979                else if (function_exists('iconv')) {
    951980                        if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
    952981                                switch ($out_charset) {
    953982                                        case 'ISO-8859-1':
    class getid3_lib 
    963992                }
    964993
    965994
    966                 // iconv() not available
     995                // neither mb_convert_encoding or iconv() is available
    967996                static $ConversionFunctionList = array();
    968997                if (empty($ConversionFunctionList)) {
    969998                        $ConversionFunctionList['ISO-8859-1']['UTF-8']    = 'iconv_fallback_iso88591_utf8';
    class getid3_lib 
    9851014                        $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
    9861015                        return self::$ConversionFunction($string);
    9871016                }
    988                 throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
     1017                throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
    9891018        }
    9901019
    9911020        public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
    class getid3_lib 
    10061035                $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
    10071036                $HTMLstring = '';
    10081037
    1009                 switch ($charset) {
     1038                switch (strtolower($charset)) {
    10101039                        case '1251':
    10111040                        case '1252':
    10121041                        case '866':
    10131042                        case '932':
    10141043                        case '936':
    10151044                        case '950':
    1016                         case 'BIG5':
    1017                         case 'BIG5-HKSCS':
     1045                        case 'big5':
     1046                        case 'big5-hkscs':
    10181047                        case 'cp1251':
    10191048                        case 'cp1252':
    10201049                        case 'cp866':
    1021                         case 'EUC-JP':
    1022                         case 'EUCJP':
    1023                         case 'GB2312':
     1050                        case 'euc-jp':
     1051                        case 'eucjp':
     1052                        case 'gb2312':
    10241053                        case 'ibm866':
    1025                         case 'ISO-8859-1':
    1026                         case 'ISO-8859-15':
    1027                         case 'ISO8859-1':
    1028                         case 'ISO8859-15':
    1029                         case 'KOI8-R':
     1054                        case 'iso-8859-1':
     1055                        case 'iso-8859-15':
     1056                        case 'iso8859-1':
     1057                        case 'iso8859-15':
     1058                        case 'koi8-r':
    10301059                        case 'koi8-ru':
    10311060                        case 'koi8r':
    1032                         case 'Shift_JIS':
    1033                         case 'SJIS':
     1061                        case 'shift_jis':
     1062                        case 'sjis':
    10341063                        case 'win-1251':
    1035                         case 'Windows-1251':
    1036                         case 'Windows-1252':
     1064                        case 'windows-1251':
     1065                        case 'windows-1252':
    10371066                                $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
    10381067                                break;
    10391068
    1040                         case 'UTF-8':
     1069                        case 'utf-8':
    10411070                                $strlen = strlen($string);
    10421071                                for ($i = 0; $i < $strlen; $i++) {
    10431072                                        $char_ord_val = ord($string{$i});
    class getid3_lib 
    10651094                                }
    10661095                                break;
    10671096
    1068                         case 'UTF-16LE':
     1097                        case 'utf-16le':
    10691098                                for ($i = 0; $i < strlen($string); $i += 2) {
    10701099                                        $charval = self::LittleEndian2Int(substr($string, $i, 2));
    10711100                                        if (($charval >= 32) && ($charval <= 127)) {
    class getid3_lib 
    10761105                                }
    10771106                                break;
    10781107
    1079                         case 'UTF-16BE':
     1108                        case 'utf-16be':
    10801109                                for ($i = 0; $i < strlen($string); $i += 2) {
    10811110                                        $charval = self::BigEndian2Int(substr($string, $i, 2));
    10821111                                        if (($charval >= 32) && ($charval <= 127)) {
    class getid3_lib 
    11531182        public static function GetDataImageSize($imgData, &$imageinfo=array()) {
    11541183                static $tempdir = '';
    11551184                if (empty($tempdir)) {
     1185                        if (function_exists('sys_get_temp_dir')) {
     1186                                $tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
     1187                        }
     1188
    11561189                        // yes this is ugly, feel free to suggest a better way
    1157                         require_once(dirname(__FILE__).'/getid3.php');
    1158                         $getid3_temp = new getID3();
    1159                         $tempdir = $getid3_temp->tempdir;
    1160                         unset($getid3_temp);
     1190                        if (include_once(dirname(__FILE__).'/getid3.php')) {
     1191                                if ($getid3_temp = new getID3()) {
     1192                                        if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
     1193                                                $tempdir = $getid3_temp_tempdir;
     1194                                        }
     1195                                        unset($getid3_temp, $getid3_temp_tempdir);
     1196                                }
     1197                        }
    11611198                }
    11621199                $GetDataImageSize = false;
    11631200                if ($tempfilename = tempnam($tempdir, 'gI3')) {
    class getid3_lib 
    11651202                                fwrite($tmp, $imgData);
    11661203                                fclose($tmp);
    11671204                                $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
     1205                                if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[1])) {
     1206                                        return false;
     1207                                }
    11681208                                $GetDataImageSize['height'] = $GetDataImageSize[0];
    11691209                                $GetDataImageSize['width']  = $GetDataImageSize[1];
    11701210                        }
    class getid3_lib 
    12371277                                                        }
    12381278                                                        if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
    12391279                                                                $value = (is_string($value) ? trim($value) : $value);
    1240                                                                 if (!is_numeric($key)) {
     1280                                                                if (!is_int($key) && !ctype_digit($key)) {
    12411281                                                                        $ThisFileInfo['comments'][$tagname][$key] = $value;
    12421282                                                                } else {
    1243                                                                         $ThisFileInfo['comments'][$tagname][]     = $value;
     1283                                                                        if (isset($ThisFileInfo['comments'][$tagname])) {
     1284                                                                                $ThisFileInfo['comments'][$tagname] = array($value);
     1285                                                                        } else {
     1286                                                                                $ThisFileInfo['comments'][$tagname][] = $value;
     1287                                                                        }
    12441288                                                                }
    12451289                                                        }
    12461290                                                }
    class getid3_lib 
    12481292                                }
    12491293                        }
    12501294
     1295                        // attempt to standardize spelling of returned keys
     1296                        $StandardizeFieldNames = array(
     1297                                'tracknumber' => 'track_number',
     1298                                'track'       => 'track_number',
     1299                        );
     1300                        foreach ($StandardizeFieldNames as $badkey => $goodkey) {
     1301                                if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
     1302                                        $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
     1303                                        unset($ThisFileInfo['comments'][$badkey]);
     1304                                }
     1305                        }
     1306
    12511307                        // Copy to ['comments_html']
    12521308                        if (!empty($ThisFileInfo['comments'])) {
    12531309                                foreach ($ThisFileInfo['comments'] as $field => $values) {
  • src/wp-includes/ID3/getid3.php

    diff --git a/src/wp-includes/ID3/getid3.php b/src/wp-includes/ID3/getid3.php
    index 714fb02..7732c19 100644
    a b if (!defined('GETID3_INCLUDEPATH')) { 
    2222if (!defined('IMG_JPG') && defined('IMAGETYPE_JPEG')) {
    2323        define('IMG_JPG', IMAGETYPE_JPEG);
    2424}
     25if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUBSTITUTE
     26        define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
     27}
    2528
    2629// attempt to define temp dir as something flexible but reliable
    2730$temp_dir = ini_get('upload_tmp_dir');
    class getID3 
    109112        protected $startup_error   = '';
    110113        protected $startup_warning = '';
    111114
    112         const VERSION           = '1.9.9-20141121';
     115        const VERSION           = '1.9.14-201706111222';
    113116        const FREAD_BUFFER_SIZE = 32768;
    114117
    115118        const ATTACHMENTS_NONE   = false;
    class getID3 
    120123
    121124                // Check memory
    122125                $this->memory_limit = ini_get('memory_limit');
    123                 if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) {
     126                if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
    124127                        // could be stored as "16M" rather than 16777216 for example
    125128                        $this->memory_limit = $matches[1] * 1048576;
    126                 } elseif (preg_match('#([0-9]+)G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
     129                } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
    127130                        // could be stored as "2G" rather than 2147483648 for example
    128131                        $this->memory_limit = $matches[1] * 1073741824;
    129132                }
    130133                if ($this->memory_limit <= 0) {
    131134                        // memory limits probably disabled
    132135                } elseif ($this->memory_limit <= 4194304) {
    133                         $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini';
     136                        $this->startup_error .= 'PHP has less than 4MB available memory and will very likely run out. Increase memory_limit in php.ini'."\n";
    134137                } elseif ($this->memory_limit <= 12582912) {
    135                         $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini';
     138                        $this->startup_warning .= 'PHP has less than 12MB available memory and might run out if all modules are loaded. Increase memory_limit in php.ini'."\n";
    136139                }
    137140
    138141                // Check safe_mode off
    class getID3 
    140143                        $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
    141144                }
    142145
    143                 if (intval(ini_get('mbstring.func_overload')) > 0) {
    144                         $this->warning('WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", this may break things.');
     146                if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
     147                        // http://php.net/manual/en/mbstring.overload.php
     148                        // "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
     149                        // getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
     150                        $this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
    145151                }
    146152
    147153                // Check for magic_quotes_runtime
    148154                if (function_exists('get_magic_quotes_runtime')) {
    149155                        if (get_magic_quotes_runtime()) {
    150                                 return $this->startup_error('magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).');
     156                                $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
    151157                        }
    152158                }
    153159
    154160                // Check for magic_quotes_gpc
    155161                if (function_exists('magic_quotes_gpc')) {
    156162                        if (get_magic_quotes_gpc()) {
    157                                 return $this->startup_error('magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).');
     163                                $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
    158164                        }
    159165                }
    160166
    161167                // Load support library
    162168                if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
    163                         $this->startup_error .= 'getid3.lib.php is missing or corrupt';
     169                        $this->startup_error .= 'getid3.lib.php is missing or corrupt'."\n";
    164170                }
    165171
    166172                if ($this->option_max_2gb_check === null) {
    class getID3 
    179185                        $helperappsdir = GETID3_INCLUDEPATH.'..'.DIRECTORY_SEPARATOR.'helperapps'; // must not have any space in this path
    180186
    181187                        if (!is_dir($helperappsdir)) {
    182                                 $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist';
     188                                $this->startup_warning .= '"'.$helperappsdir.'" cannot be defined as GETID3_HELPERAPPSDIR because it does not exist'."\n";
    183189                        } elseif (strpos(realpath($helperappsdir), ' ') !== false) {
    184190                                $DirPieces = explode(DIRECTORY_SEPARATOR, realpath($helperappsdir));
    185191                                $path_so_far = array();
    class getID3 
    199205                                                                }
    200206                                                        }
    201207                                                } else {
    202                                                         $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.';
     208                                                        $this->startup_warning .= 'GETID3_HELPERAPPSDIR must not have any spaces in it - use 8dot3 naming convention if neccesary. You can run "dir /x" from the commandline to see the correct 8.3-style names.'."\n";
    203209                                                }
    204210                                        }
    205211                                        $path_so_far[] = $value;
    class getID3 
    209215                        define('GETID3_HELPERAPPSDIR', $helperappsdir.DIRECTORY_SEPARATOR);
    210216                }
    211217
     218                if (!empty($this->startup_error)) {
     219                        echo $this->startup_error;
     220                        throw new getid3_exception($this->startup_error);
     221                }
     222
    212223                return true;
    213224        }
    214225
    class getID3 
    236247        }
    237248
    238249
    239         public function openfile($filename) {
     250        public function openfile($filename, $filesize=null) {
    240251                try {
    241252                        if (!empty($this->startup_error)) {
    242253                                throw new getid3_exception($this->startup_error);
    243254                        }
    244255                        if (!empty($this->startup_warning)) {
    245                                 $this->warning($this->startup_warning);
     256                                foreach (explode("\n", $this->startup_warning) as $startup_warning) {
     257                                        $this->warning($startup_warning);
     258                                }
    246259                        }
    247260
    248261                        // init result array and set parameters
    class getID3 
    252265                        $this->info['php_memory_limit'] = (($this->memory_limit > 0) ? $this->memory_limit : false);
    253266
    254267                        // remote files not supported
    255                         if (preg_match('/^(ht|f)tp:\/\//', $filename)) {
     268                        if (preg_match('#^(ht|f)tp://#', $filename)) {
    256269                                throw new getid3_exception('Remote files are not supported - please copy the file locally first');
    257270                        }
    258271
    259272                        $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
    260                         $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename);
     273                        $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
    261274
    262275                        // open local file
    263276                        //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
    class getID3 
    280293                                throw new getid3_exception('Could not open "'.$filename.'" ('.implode('; ', $errormessagelist).')');
    281294                        }
    282295
    283                         $this->info['filesize'] = filesize($filename);
     296                        $this->info['filesize'] = (!is_null($filesize) ? $filesize : filesize($filename));
    284297                        // set redundant parameters - might be needed in some include file
    285298                        // filenames / filepaths in getID3 are always expressed with forward slashes (unix-style) for both Windows and other to try and minimize confusion
    286299                        $filename = str_replace('\\', '/', $filename);
    class getID3 
    288301                        $this->info['filename']     = getid3_lib::mb_basename($filename);
    289302                        $this->info['filenamepath'] = $this->info['filepath'].'/'.$this->info['filename'];
    290303
     304                        // set more parameters
     305                        $this->info['avdataoffset']        = 0;
     306                        $this->info['avdataend']           = $this->info['filesize'];
     307                        $this->info['fileformat']          = '';                // filled in later
     308                        $this->info['audio']['dataformat'] = '';                // filled in later, unset if not used
     309                        $this->info['video']['dataformat'] = '';                // filled in later, unset if not used
     310                        $this->info['tags']                = array();           // filled in later, unset if not used
     311                        $this->info['error']               = array();           // filled in later, unset if not used
     312                        $this->info['warning']             = array();           // filled in later, unset if not used
     313                        $this->info['comments']            = array();           // filled in later, unset if not used
     314                        $this->info['encoding']            = $this->encoding;   // required by id3v2 and iso modules - can be unset at the end if desired
    291315
    292316                        // option_max_2gb_check
    293317                        if ($this->option_max_2gb_check) {
    class getID3 
    314338                                }
    315339                        }
    316340
    317                         // set more parameters
    318                         $this->info['avdataoffset']        = 0;
    319                         $this->info['avdataend']           = $this->info['filesize'];
    320                         $this->info['fileformat']          = '';                // filled in later
    321                         $this->info['audio']['dataformat'] = '';                // filled in later, unset if not used
    322                         $this->info['video']['dataformat'] = '';                // filled in later, unset if not used
    323                         $this->info['tags']                = array();           // filled in later, unset if not used
    324                         $this->info['error']               = array();           // filled in later, unset if not used
    325                         $this->info['warning']             = array();           // filled in later, unset if not used
    326                         $this->info['comments']            = array();           // filled in later, unset if not used
    327                         $this->info['encoding']            = $this->encoding;   // required by id3v2 and iso modules - can be unset at the end if desired
    328 
    329341                        return true;
    330342
    331343                } catch (Exception $e) {
    class getID3 
    335347        }
    336348
    337349        // public: analyze file
    338         public function analyze($filename) {
     350        public function analyze($filename, $filesize=null, $original_filename='') {
    339351                try {
    340                         if (!$this->openfile($filename)) {
     352                        if (!$this->openfile($filename, $filesize)) {
    341353                                return $this->info;
    342354                        }
    343355
    class getID3 
    382394                        $formattest = fread($this->fp, 32774);
    383395
    384396                        // determine format
    385                         $determined_format = $this->GetFileFormat($formattest, $filename);
     397                        $determined_format = $this->GetFileFormat($formattest, ($original_filename ? $original_filename : $filename));
    386398
    387399                        // unable to determine file format
    388400                        if (!$determined_format) {
    class getID3 
    419431                                return $this->error('Format not supported, module "'.$determined_format['include'].'" was removed.');
    420432                        }
    421433
    422                         // module requires iconv support
     434                        // module requires mb_convert_encoding/iconv support
    423435                        // Check encoding/iconv support
    424                         if (!empty($determined_format['iconv_req']) && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
    425                                 $errormessage = 'iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
     436                        if (!empty($determined_format['iconv_req']) && !function_exists('mb_convert_encoding') && !function_exists('iconv') && !in_array($this->encoding, array('ISO-8859-1', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'UTF-16'))) {
     437                                $errormessage = 'mb_convert_encoding() or iconv() support is required for this module ('.$determined_format['include'].') for encodings other than ISO-8859-1, UTF-8, UTF-16LE, UTF16-BE, UTF-16. ';
    426438                                if (GETID3_OS_ISWINDOWS) {
    427                                         $errormessage .= 'PHP does not have iconv() support. Please enable php_iconv.dll in php.ini, and copy iconv.dll from c:/php/dlls to c:/windows/system32';
     439                                        $errormessage .= 'PHP does not have mb_convert_encoding() or iconv() support. Please enable php_mbstring.dll / php_iconv.dll in php.ini, and copy php_mbstring.dll / iconv.dll from c:/php/dlls to c:/windows/system32';
    428440                                } else {
    429                                         $errormessage .= 'PHP is not compiled with iconv() support. Please recompile with the --with-iconv switch';
     441                                        $errormessage .= 'PHP is not compiled with mb_convert_encoding() or iconv() support. Please recompile with the --enable-mbstring / --with-iconv switch';
    430442                                }
    431443                                return $this->error($errormessage);
    432444                        }
    class getID3 
    561573
    562574                                // AC-3   - audio      - Dolby AC-3 / Dolby Digital
    563575                                'ac3'  => array(
    564                                                         'pattern'   => '^\x0B\x77',
     576                                                        'pattern'   => '^\\x0B\\x77',
    565577                                                        'group'     => 'audio',
    566578                                                        'module'    => 'ac3',
    567579                                                        'mime_type' => 'audio/ac3',
    class getID3 
    579591/*
    580592                                // AA   - audio       - Audible Audiobook
    581593                                'aa'   => array(
    582                                                         'pattern'   => '^.{4}\x57\x90\x75\x36',
     594                                                        'pattern'   => '^.{4}\\x57\\x90\\x75\\x36',
    583595                                                        'group'     => 'audio',
    584596                                                        'module'    => 'aa',
    585597                                                        'mime_type' => 'audio/audible',
    class getID3 
    587599*/
    588600                                // AAC  - audio       - Advanced Audio Coding (AAC) - ADTS format (very similar to MP3)
    589601                                'adts' => array(
    590                                                         'pattern'   => '^\xFF[\xF0-\xF1\xF8-\xF9]',
     602                                                        'pattern'   => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
    591603                                                        'group'     => 'audio',
    592604                                                        'module'    => 'aac',
    593605                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    597609
    598610                                // AU   - audio       - NeXT/Sun AUdio (AU)
    599611                                'au'   => array(
    600                                                         'pattern'   => '^\.snd',
     612                                                        'pattern'   => '^\\.snd',
    601613                                                        'group'     => 'audio',
    602614                                                        'module'    => 'au',
    603615                                                        'mime_type' => 'audio/basic',
    class getID3 
    605617
    606618                                // AMR  - audio       - Adaptive Multi Rate
    607619                                'amr'  => array(
    608                                                         'pattern'   => '^\x23\x21AMR\x0A', // #!AMR[0A]
     620                                                        'pattern'   => '^\\x23\\x21AMR\\x0A', // #!AMR[0A]
    609621                                                        'group'     => 'audio',
    610622                                                        'module'    => 'amr',
    611623                                                        'mime_type' => 'audio/amr',
    class getID3 
    621633
    622634                                // BONK - audio       - Bonk v0.9+
    623635                                'bonk' => array(
    624                                                         'pattern'   => '^\x00(BONK|INFO|META| ID3)',
     636                                                        'pattern'   => '^\\x00(BONK|INFO|META| ID3)',
    625637                                                        'group'     => 'audio',
    626638                                                        'module'    => 'bonk',
    627639                                                        'mime_type' => 'audio/xmms-bonk',
    628640                                                ),
    629641
     642                                // DSF  - audio       - Direct Stream Digital (DSD) Storage Facility files (DSF) - https://en.wikipedia.org/wiki/Direct_Stream_Digital
     643                                'dsf'  => array(
     644                                                        'pattern'   => '^DSD ',  // including trailing space: 44 53 44 20
     645                                                        'group'     => 'audio',
     646                                                        'module'    => 'dsf',
     647                                                        'mime_type' => 'audio/dsd',
     648                                                ),
     649
    630650                                // DSS  - audio       - Digital Speech Standard
    631651                                'dss'  => array(
    632                                                         'pattern'   => '^[\x02-\x03]ds[s2]',
     652                                                        'pattern'   => '^[\\x02-\\x06]ds[s2]',
    633653                                                        'group'     => 'audio',
    634654                                                        'module'    => 'dss',
    635655                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    637657
    638658                                // DTS  - audio       - Dolby Theatre System
    639659                                'dts'  => array(
    640                                                         'pattern'   => '^\x7F\xFE\x80\x01',
     660                                                        'pattern'   => '^\\x7F\\xFE\\x80\\x01',
    641661                                                        'group'     => 'audio',
    642662                                                        'module'    => 'dts',
    643663                                                        'mime_type' => 'audio/dts',
    class getID3 
    722742
    723743                                // MPC  - audio       - Musepack / MPEGplus
    724744                                'mpc'  => array(
    725                                                         'pattern'   => '^(MPCK|MP\+|[\x00\x01\x10\x11\x40\x41\x50\x51\x80\x81\x90\x91\xC0\xC1\xD0\xD1][\x20-37][\x00\x20\x40\x60\x80\xA0\xC0\xE0])',
     745                                                        'pattern'   => '^(MPCK|MP\\+|[\\x00\\x01\\x10\\x11\\x40\\x41\\x50\\x51\\x80\\x81\\x90\\x91\\xC0\\xC1\\xD0\\xD1][\\x20-\\x37][\\x00\\x20\\x40\\x60\\x80\\xA0\\xC0\\xE0])',
    726746                                                        'group'     => 'audio',
    727747                                                        'module'    => 'mpc',
    728748                                                        'mime_type' => 'audio/x-musepack',
    class getID3 
    730750
    731751                                // MP3  - audio       - MPEG-audio Layer 3 (very similar to AAC-ADTS)
    732752                                'mp3'  => array(
    733                                                         'pattern'   => '^\xFF[\xE2-\xE7\xF2-\xF7\xFA-\xFF][\x00-\x0B\x10-\x1B\x20-\x2B\x30-\x3B\x40-\x4B\x50-\x5B\x60-\x6B\x70-\x7B\x80-\x8B\x90-\x9B\xA0-\xAB\xB0-\xBB\xC0-\xCB\xD0-\xDB\xE0-\xEB\xF0-\xFB]',
     753                                                        'pattern'   => '^\\xFF[\\xE2-\\xE7\\xF2-\\xF7\\xFA-\\xFF][\\x00-\\x0B\\x10-\\x1B\\x20-\\x2B\\x30-\\x3B\\x40-\\x4B\\x50-\\x5B\\x60-\\x6B\\x70-\\x7B\\x80-\\x8B\\x90-\\x9B\\xA0-\\xAB\\xB0-\\xBB\\xC0-\\xCB\\xD0-\\xDB\\xE0-\\xEB\\xF0-\\xFB]',
    734754                                                        'group'     => 'audio',
    735755                                                        'module'    => 'mp3',
    736756                                                        'mime_type' => 'audio/mpeg',
    class getID3 
    738758
    739759                                // OFR  - audio       - OptimFROG
    740760                                'ofr'  => array(
    741                                                         'pattern'   => '^(\*RIFF|OFR)',
     761                                                        'pattern'   => '^(\\*RIFF|OFR)',
    742762                                                        'group'     => 'audio',
    743763                                                        'module'    => 'optimfrog',
    744764                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    764784
    765785                                // TTA  - audio       - TTA Lossless Audio Compressor (http://tta.corecodec.org)
    766786                                'tta'  => array(
    767                                                         'pattern'   => '^TTA',  // could also be '^TTA(\x01|\x02|\x03|2|1)'
     787                                                        'pattern'   => '^TTA',  // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
    768788                                                        'group'     => 'audio',
    769789                                                        'module'    => 'tta',
    770790                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    799819
    800820                                // ASF  - audio/video - Advanced Streaming Format, Windows Media Video, Windows Media Audio
    801821                                'asf'  => array(
    802                                                         'pattern'   => '^\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C',
     822                                                        'pattern'   => '^\\x30\\x26\\xB2\\x75\\x8E\\x66\\xCF\\x11\\xA6\\xD9\\x00\\xAA\\x00\\x62\\xCE\\x6C',
    803823                                                        'group'     => 'audio-video',
    804824                                                        'module'    => 'asf',
    805825                                                        'mime_type' => 'video/x-ms-asf',
    class getID3 
    816836
    817837                                // FLV  - audio/video - FLash Video
    818838                                'flv' => array(
    819                                                         'pattern'   => '^FLV\x01',
     839                                                        'pattern'   => '^FLV[\\x01]',
    820840                                                        'group'     => 'audio-video',
    821841                                                        'module'    => 'flv',
    822842                                                        'mime_type' => 'video/x-flv',
    class getID3 
    824844
    825845                                // MKAV - audio/video - Mastroka
    826846                                'matroska' => array(
    827                                                         'pattern'   => '^\x1A\x45\xDF\xA3',
     847                                                        'pattern'   => '^\\x1A\\x45\\xDF\\xA3',
    828848                                                        'group'     => 'audio-video',
    829849                                                        'module'    => 'matroska',
    830850                                                        'mime_type' => 'video/x-matroska', // may also be audio/x-matroska
    class getID3 
    832852
    833853                                // MPEG - audio/video - MPEG (Moving Pictures Experts Group)
    834854                                'mpeg' => array(
    835                                                         'pattern'   => '^\x00\x00\x01(\xBA|\xB3)',
     855                                                        'pattern'   => '^\\x00\\x00\\x01[\\xB3\\xBA]',
    836856                                                        'group'     => 'audio-video',
    837857                                                        'module'    => 'mpeg',
    838858                                                        'mime_type' => 'video/mpeg',
    class getID3 
    869889                                                        'pattern'   => '^(RIFF|SDSS|FORM)',
    870890                                                        'group'     => 'audio-video',
    871891                                                        'module'    => 'riff',
    872                                                         'mime_type' => 'audio/x-wave',
     892                                                        'mime_type' => 'audio/x-wav',
    873893                                                        'fail_ape'  => 'WARNING',
    874894                                                ),
    875895
    876896                                // Real - audio/video - RealAudio, RealVideo
    877897                                'real' => array(
    878                                                         'pattern'   => '^(\\.RMF|\\.ra)',
     898                                                        'pattern'   => '^\\.(RMF|ra)',
    879899                                                        'group'     => 'audio-video',
    880900                                                        'module'    => 'real',
    881901                                                        'mime_type' => 'audio/x-realaudio',
    class getID3 
    891911
    892912                                // TS - audio/video - MPEG-2 Transport Stream
    893913                                'ts' => array(
    894                                                         'pattern'   => '^(\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G".  Check for at least 10 packets matching this pattern
     914                                                        'pattern'   => '^(\\x47.{187}){10,}', // packets are 188 bytes long and start with 0x47 "G".  Check for at least 10 packets matching this pattern
    895915                                                        'group'     => 'audio-video',
    896916                                                        'module'    => 'ts',
    897917                                                        'mime_type' => 'video/MP2T',
    class getID3 
    922942
    923943                                // JPEG - still image - Joint Photographic Experts Group (JPEG)
    924944                                'jpg'  => array(
    925                                                         'pattern'   => '^\xFF\xD8\xFF',
     945                                                        'pattern'   => '^\\xFF\\xD8\\xFF',
    926946                                                        'group'     => 'graphic',
    927947                                                        'module'    => 'jpg',
    928948                                                        'mime_type' => 'image/jpeg',
    class getID3 
    932952
    933953                                // PCD  - still image - Kodak Photo CD
    934954                                'pcd'  => array(
    935                                                         'pattern'   => '^.{2048}PCD_IPI\x00',
     955                                                        'pattern'   => '^.{2048}PCD_IPI\\x00',
    936956                                                        'group'     => 'graphic',
    937957                                                        'module'    => 'pcd',
    938958                                                        'mime_type' => 'image/x-photo-cd',
    class getID3 
    943963
    944964                                // PNG  - still image - Portable Network Graphics (PNG)
    945965                                'png'  => array(
    946                                                         'pattern'   => '^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A',
     966                                                        'pattern'   => '^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A',
    947967                                                        'group'     => 'graphic',
    948968                                                        'module'    => 'png',
    949969                                                        'mime_type' => 'image/png',
    class getID3 
    954974
    955975                                // SVG  - still image - Scalable Vector Graphics (SVG)
    956976                                'svg'  => array(
    957                                                         'pattern'   => '(<!DOCTYPE svg PUBLIC |xmlns="http:\/\/www\.w3\.org\/2000\/svg")',
     977                                                        'pattern'   => '(<!DOCTYPE svg PUBLIC |xmlns="http://www\\.w3\\.org/2000/svg")',
    958978                                                        'group'     => 'graphic',
    959979                                                        'module'    => 'svg',
    960980                                                        'mime_type' => 'image/svg+xml',
    class getID3 
    965985
    966986                                // TIFF - still image - Tagged Information File Format (TIFF)
    967987                                'tiff' => array(
    968                                                         'pattern'   => '^(II\x2A\x00|MM\x00\x2A)',
     988                                                        'pattern'   => '^(II\\x2A\\x00|MM\\x00\\x2A)',
    969989                                                        'group'     => 'graphic',
    970990                                                        'module'    => 'tiff',
    971991                                                        'mime_type' => 'image/tiff',
    class getID3 
    976996
    977997                                // EFAX - still image - eFax (TIFF derivative)
    978998                                'efax'  => array(
    979                                                         'pattern'   => '^\xDC\xFE',
     999                                                        'pattern'   => '^\\xDC\\xFE',
    9801000                                                        'group'     => 'graphic',
    9811001                                                        'module'    => 'efax',
    9821002                                                        'mime_type' => 'image/efax',
    class getID3 
    10001020
    10011021                                // RAR  - data        - RAR compressed data
    10021022                                'rar'  => array(
    1003                                                         'pattern'   => '^Rar\!',
     1023                                                        'pattern'   => '^Rar\\!',
    10041024                                                        'group'     => 'archive',
    10051025                                                        'module'    => 'rar',
    10061026                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    10101030
    10111031                                // SZIP - audio/data  - SZIP compressed data
    10121032                                'szip' => array(
    1013                                                         'pattern'   => '^SZ\x0A\x04',
     1033                                                        'pattern'   => '^SZ\\x0A\\x04',
    10141034                                                        'group'     => 'archive',
    10151035                                                        'module'    => 'szip',
    10161036                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    10201040
    10211041                                // TAR  - data        - TAR compressed data
    10221042                                'tar'  => array(
    1023                                                         'pattern'   => '^.{100}[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20]{7}\x00[0-9\x20\x00]{12}[0-9\x20\x00]{12}',
     1043                                                        'pattern'   => '^.{100}[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20]{7}\\x00[0-9\\x20\\x00]{12}[0-9\\x20\\x00]{12}',
    10241044                                                        'group'     => 'archive',
    10251045                                                        'module'    => 'tar',
    10261046                                                        'mime_type' => 'application/x-tar',
    class getID3 
    10301050
    10311051                                // GZIP  - data        - GZIP compressed data
    10321052                                'gz'  => array(
    1033                                                         'pattern'   => '^\x1F\x8B\x08',
     1053                                                        'pattern'   => '^\\x1F\\x8B\\x08',
    10341054                                                        'group'     => 'archive',
    10351055                                                        'module'    => 'gzip',
    10361056                                                        'mime_type' => 'application/x-gzip',
    class getID3 
    10401060
    10411061                                // ZIP  - data         - ZIP compressed data
    10421062                                'zip'  => array(
    1043                                                         'pattern'   => '^PK\x03\x04',
     1063                                                        'pattern'   => '^PK\\x03\\x04',
    10441064                                                        'group'     => 'archive',
    10451065                                                        'module'    => 'zip',
    10461066                                                        'mime_type' => 'application/zip',
    class getID3 
    10531073
    10541074                                // PAR2 - data        - Parity Volume Set Specification 2.0
    10551075                                'par2' => array (
    1056                                                         'pattern'   => '^PAR2\x00PKT',
     1076                                                        'pattern'   => '^PAR2\\x00PKT',
    10571077                                                        'group'     => 'misc',
    10581078                                                        'module'    => 'par2',
    10591079                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    10631083
    10641084                                // PDF  - data        - Portable Document Format
    10651085                                'pdf'  => array(
    1066                                                         'pattern'   => '^\x25PDF',
     1086                                                        'pattern'   => '^\\x25PDF',
    10671087                                                        'group'     => 'misc',
    10681088                                                        'module'    => 'pdf',
    10691089                                                        'mime_type' => 'application/pdf',
    class getID3 
    10731093
    10741094                                // MSOFFICE  - data   - ZIP compressed data
    10751095                                'msoffice' => array(
    1076                                                         'pattern'   => '^\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
     1096                                                        'pattern'   => '^\\xD0\\xCF\\x11\\xE0\\xA1\\xB1\\x1A\\xE1', // D0CF11E == DOCFILE == Microsoft Office Document
    10771097                                                        'group'     => 'misc',
    10781098                                                        'module'    => 'msoffice',
    10791099                                                        'mime_type' => 'application/octet-stream',
    class getID3 
    11141134                }
    11151135
    11161136
    1117                 if (preg_match('#\.mp[123a]$#i', $filename)) {
     1137                if (preg_match('#\\.mp[123a]$#i', $filename)) {
    11181138                        // Too many mp3 encoders on the market put gabage in front of mpeg files
    11191139                        // use assume format on these if format detection failed
    11201140                        $GetFileFormatArray = $this->GetFileFormatArray();
    11211141                        $info = $GetFileFormatArray['mp3'];
    11221142                        $info['include'] = 'module.'.$info['group'].'.'.$info['module'].'.php';
    11231143                        return $info;
    1124                 } elseif (preg_match('/\.cue$/i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
     1144                } elseif (preg_match('#\\.cue$#i', $filename) && preg_match('#FILE "[^"]+" (BINARY|MOTOROLA|AIFF|WAVE|MP3)#', $filedata)) {
    11251145                        // there's not really a useful consistent "magic" at the beginning of .cue files to identify them
    11261146                        // so until I think of something better, just go by filename if all other format checks fail
    11271147                        // and verify there's at least one instance of "TRACK xx AUDIO" in the file
    class getID3 
    12221242                                        continue;
    12231243                                }
    12241244
     1245                                $this->CharConvert($this->info['tags'][$tag_name], $this->info[$comment_name]['encoding']);           // only copy gets converted!
     1246
    12251247                                if ($this->option_tags_html) {
    12261248                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
    1227                                                 $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $encoding);
     1249                                                $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
    12281250                                        }
    12291251                                }
    12301252
    1231                                 $this->CharConvert($this->info['tags'][$tag_name], $encoding);           // only copy gets converted!
    12321253                        }
    12331254
    12341255                }
    class getID3 
    13521373
    13531374                                if (!empty($VorbisCommentError)) {
    13541375
    1355                                         $this->info['warning'][]         = 'Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError;
    1356                                         $this->info[$algorithm.'_data']  = false;
     1376                                        $this->warning('Failed making system call to vorbiscomment(.exe) - '.$algorithm.'_data will be incorrect. If vorbiscomment is unavailable, please download from http://www.vorbis.com/download.psp and put in the getID3() directory. Error returned: '.$VorbisCommentError);
     1377                                        $this->info[$algorithm.'_data'] = false;
    13571378
    13581379                                } else {
    13591380
    class getID3 
    15821603                return true;
    15831604        }
    15841605
     1606    public static function is_writable ($filename) {
     1607        $ret = is_writable($filename);
     1608
     1609        if (!$ret) {
     1610            $perms = fileperms($filename);
     1611            $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
     1612        }
     1613
     1614        return $ret;
     1615    }
     1616
    15851617}
    15861618
    15871619
    abstract class getid3_handler { 
    16611693                if (!getid3_lib::intValueSupported($pos)) {
    16621694                        throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') because beyond PHP filesystem limit', 10);
    16631695                }
    1664                 return fread($this->getid3->fp, $bytes);
     1696
     1697                //return fread($this->getid3->fp, $bytes);
     1698                /*
     1699                * http://www.getid3.org/phpBB3/viewtopic.php?t=1930
     1700                * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
     1701                * It seems to assume that fread() would always return as many bytes as were requested.
     1702                * However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
     1703                * The call may return only part of the requested data and a new call is needed to get more."
     1704                */
     1705                $contents = '';
     1706                do {
     1707                        $part = fread($this->getid3->fp, $bytes);
     1708                        $partLength  = strlen($part);
     1709                        $bytes      -= $partLength;
     1710                        $contents   .= $part;
     1711                } while (($bytes > 0) && ($partLength > 0));
     1712                return $contents;
    16651713        }
    16661714
    16671715        protected function fseek($bytes, $whence=SEEK_SET) {
    abstract class getid3_handler { 
    17411789
    17421790                                // set up destination path
    17431791                                $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
    1744                                 if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory
     1792                                if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory
    17451793                                        throw new Exception('supplied path ('.$dir.') does not exist, or is not writable');
    17461794                                }
    17471795                                $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : '');
  • src/wp-includes/ID3/module.audio-video.asf.php

    diff --git a/src/wp-includes/ID3/module.audio-video.asf.php b/src/wp-includes/ID3/module.audio-video.asf.php
    index ee61d7d..23d3a0e 100644
    a b class getid3_asf extends getid3_handler { 
    266266                                        $offset += 16;
    267267                                        $thisfile_asf_headerextensionobject['reserved_1_guid']     = $this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']);
    268268                                        if ($thisfile_asf_headerextensionobject['reserved_1'] != GETID3_ASF_Reserved_1) {
    269                                                 $info['warning'][] = 'header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')';
     269                                                $this->warning('header_extension_object.reserved_1 GUID ('.$this->BytestringToGUID($thisfile_asf_headerextensionobject['reserved_1']).') does not match expected "GETID3_ASF_Reserved_1" GUID ('.$this->BytestringToGUID(GETID3_ASF_Reserved_1).')');
    270270                                                //return false;
    271271                                                break;
    272272                                        }
    273273                                        $thisfile_asf_headerextensionobject['reserved_2']          = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
    274274                                        $offset += 2;
    275275                                        if ($thisfile_asf_headerextensionobject['reserved_2'] != 6) {
    276                                                 $info['warning'][] = 'header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"';
     276                                                $this->warning('header_extension_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_headerextensionobject['reserved_2']).') does not match expected value of "6"');
    277277                                                //return false;
    278278                                                break;
    279279                                        }
    class getid3_asf extends getid3_handler { 
    316316                                        $offset += 16;
    317317                                        $thisfile_asf_codeclistobject['reserved_guid']             = $this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']);
    318318                                        if ($thisfile_asf_codeclistobject['reserved'] != $this->GUIDtoBytestring('86D15241-311D-11D0-A3A4-00A0C90348F6')) {
    319                                                 $info['warning'][] = 'codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}';
     319                                                $this->warning('codec_list_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_codeclistobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {86D15241-311D-11D0-A3A4-00A0C90348F6}');
    320320                                                //return false;
    321321                                                break;
    322322                                        }
    class getid3_asf extends getid3_handler { 
    349349                                                if ($thisfile_asf_codeclistobject_codecentries_current['type_raw'] == 2) { // audio codec
    350350
    351351                                                        if (strpos($thisfile_asf_codeclistobject_codecentries_current['description'], ',') === false) {
    352                                                                 $info['warning'][] = '[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-seperated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"';
     352                                                                $this->warning('[asf][codec_list_object][codec_entries]['.$CodecEntryCounter.'][description] expected to contain comma-separated list of parameters: "'.$thisfile_asf_codeclistobject_codecentries_current['description'].'"');
    353353                                                        } else {
    354354
    355355                                                                list($AudioCodecBitrate, $AudioCodecFrequency, $AudioCodecChannels) = explode(',', $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']));
    class getid3_asf extends getid3_handler { 
    412412                                                                                break;
    413413
    414414                                                                        default:
    415                                                                                 $info['warning'][] = 'unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')';
     415                                                                                $this->warning('unknown frequency: "'.$AudioCodecFrequency.'" ('.$this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['description']).')');
    416416                                                                                break;
    417417                                                                }
    418418
    class getid3_asf extends getid3_handler { 
    458458                                        $offset += 16;
    459459                                        $thisfile_asf_scriptcommandobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']);
    460460                                        if ($thisfile_asf_scriptcommandobject['reserved'] != $this->GUIDtoBytestring('4B1ACBE3-100B-11D0-A39B-00A0C90348F6')) {
    461                                                 $info['warning'][] = 'script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}';
     461                                                $this->warning('script_command_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_scriptcommandobject['reserved']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4B1ACBE3-100B-11D0-A39B-00A0C90348F6}');
    462462                                                //return false;
    463463                                                break;
    464464                                        }
    class getid3_asf extends getid3_handler { 
    517517                                        $offset += 16;
    518518                                        $thisfile_asf_markerobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_markerobject['reserved']);
    519519                                        if ($thisfile_asf_markerobject['reserved'] != $this->GUIDtoBytestring('4CFEDB20-75F6-11CF-9C0F-00A0C90349CB')) {
    520                                                 $info['warning'][] = 'marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}';
     520                                                $this->warning('marker_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_markerobject['reserved_1']).'} does not match expected "GETID3_ASF_Reserved_1" GUID {4CFEDB20-75F6-11CF-9C0F-00A0C90349CB}');
    521521                                                break;
    522522                                        }
    523523                                        $thisfile_asf_markerobject['markers_count'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 4));
    class getid3_asf extends getid3_handler { 
    525525                                        $thisfile_asf_markerobject['reserved_2'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
    526526                                        $offset += 2;
    527527                                        if ($thisfile_asf_markerobject['reserved_2'] != 0) {
    528                                                 $info['warning'][] = 'marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"';
     528                                                $this->warning('marker_object.reserved_2 ('.getid3_lib::PrintHexBytes($thisfile_asf_markerobject['reserved_2']).') does not match expected value of "0"');
    529529                                                break;
    530530                                        }
    531531                                        $thisfile_asf_markerobject['name_length'] = getid3_lib::LittleEndian2Int(substr($ASFHeaderData, $offset, 2));
    class getid3_asf extends getid3_handler { 
    576576                                        $thisfile_asf_bitratemutualexclusionobject['reserved_guid']        = $this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']);
    577577                                        $offset += 16;
    578578                                        if (($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Bitrate) && ($thisfile_asf_bitratemutualexclusionobject['reserved'] != GETID3_ASF_Mutex_Unknown)) {
    579                                                 $info['warning'][] = 'bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or  "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}';
     579                                                $this->warning('bitrate_mutual_exclusion_object.reserved GUID {'.$this->BytestringToGUID($thisfile_asf_bitratemutualexclusionobject['reserved']).'} does not match expected "GETID3_ASF_Mutex_Bitrate" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Bitrate).'} or  "GETID3_ASF_Mutex_Unknown" GUID {'.$this->BytestringToGUID(GETID3_ASF_Mutex_Unknown).'}');
    580580                                                //return false;
    581581                                                break;
    582582                                        }
    class getid3_asf extends getid3_handler { 
    637637                                                        break;
    638638
    639639                                                default:
    640                                                         $info['warning'][] = 'error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or  "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}';
     640                                                        $this->warning('error_correction_object.error_correction_type GUID {'.$this->BytestringToGUID($thisfile_asf_errorcorrectionobject['reserved']).'} does not match expected "GETID3_ASF_No_Error_Correction" GUID {'.$this->BytestringToGUID(GETID3_ASF_No_Error_Correction).'} or  "GETID3_ASF_Audio_Spread" GUID {'.$this->BytestringToGUID(GETID3_ASF_Audio_Spread).'}');
    641641                                                        //return false;
    642642                                                        break;
    643643                                        }
    class getid3_asf extends getid3_handler { 
    761761                                                                break;
    762762
    763763                                                        default:
    764                                                                 $info['warning'][] = 'extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')';
     764                                                                $this->warning('extended_content_description.content_descriptors.'.$ExtendedContentDescriptorsCounter.'.value_type is invalid ('.$thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value_type'].')');
    765765                                                                //return false;
    766766                                                                break;
    767767                                                }
    class getid3_asf extends getid3_handler { 
    962962                                default:
    963963                                        // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
    964964                                        if ($this->GUIDname($NextObjectGUIDtext)) {
    965                                                 $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
     965                                                $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
    966966                                        } else {
    967                                                 $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8);
     967                                                $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF header at offset '.($offset - 16 - 8));
    968968                                        }
    969969                                        $offset += ($NextObjectSize - 16 - 8);
    970970                                        break;
    class getid3_asf extends getid3_handler { 
    11831183                                        $thisfile_asf_dataobject['reserved']           = getid3_lib::LittleEndian2Int(substr($DataObjectData, $offset, 2));
    11841184                                        $offset += 2;
    11851185                                        if ($thisfile_asf_dataobject['reserved'] != 0x0101) {
    1186                                                 $info['warning'][] = 'data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"';
     1186                                                $this->warning('data_object.reserved ('.getid3_lib::PrintHexBytes($thisfile_asf_dataobject['reserved']).') does not match expected value of "0x0101"');
    11871187                                                //return false;
    11881188                                                break;
    11891189                                        }
    class getid3_asf extends getid3_handler { 
    13191319                                default:
    13201320                                        // Implementations shall ignore any standard or non-standard object that they do not know how to handle.
    13211321                                        if ($this->GUIDname($NextObjectGUIDtext)) {
    1322                                                 $info['warning'][] = 'unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8);
     1322                                                $this->warning('unhandled GUID "'.$this->GUIDname($NextObjectGUIDtext).'" {'.$NextObjectGUIDtext.'} in ASF body at offset '.($offset - 16 - 8));
    13231323                                        } else {
    1324                                                 $info['warning'][] = 'unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8);
     1324                                                $this->warning('unknown GUID {'.$NextObjectGUIDtext.'} in ASF body at offset '.($this->ftell() - 16 - 8));
    13251325                                        }
    13261326                                        $this->fseek(($NextObjectSize - 16 - 8), SEEK_CUR);
    13271327                                        break;
    class getid3_asf extends getid3_handler { 
    14051405                                                break;
    14061406
    14071407                                        default:
    1408                                                 $info['warning'][] = 'Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw'];
     1408                                                $this->warning('Unknown streamtype: [codec_list_object][codec_entries]['.$streamnumber.'][type_raw] == '.$streamdata['type_raw']);
    14091409                                                break;
    14101410
    14111411                                }
    class getid3_asf extends getid3_handler { 
    19171917                                default:
    19181918                                        $unhandled_sections++;
    19191919                                        if ($this->GUIDname($thisObject['guid_text'])) {
    1920                                                 $this->getid3->info['warning'][] = 'unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8);
     1920                                                $this->warning('unhandled Header Extension Object GUID "'.$this->GUIDname($thisObject['guid_text']).'" {'.$thisObject['guid_text'].'} at offset '.($offset - 16 - 8));
    19211921                                        } else {
    1922                                                 $this->getid3->info['warning'][] = 'unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8);
     1922                                                $this->warning('unknown Header Extension Object GUID {'.$thisObject['guid_text'].'} in at offset '.($offset - 16 - 8));
    19231923                                        }
    19241924                                        break;
    19251925                        }
  • src/wp-includes/ID3/module.audio-video.flv.php

    diff --git a/src/wp-includes/ID3/module.audio-video.flv.php b/src/wp-includes/ID3/module.audio-video.flv.php
    index c5fbd4b..661c77c 100644
    a b class getid3_flv extends getid3_handler { 
    9393                $TypeFlags                          = getid3_lib::BigEndian2Int(substr($FLVheader, 4, 1));
    9494
    9595                if ($info['flv']['header']['signature'] != self::magic) {
    96                         $info['error'][] = 'Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"';
     96                        $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['flv']['header']['signature']).'"');
    9797                        unset($info['flv'], $info['fileformat']);
    9898                        return false;
    9999                }
    class AMFReader { 
    541541                        // Long string
    542542                        default:
    543543                                $value = '(unknown or unsupported data type)';
    544                         break;
     544                                break;
    545545                }
    546546
    547547                return $value;
  • src/wp-includes/ID3/module.audio-video.matroska.php

    diff --git a/src/wp-includes/ID3/module.audio-video.matroska.php b/src/wp-includes/ID3/module.audio-video.matroska.php
    index f2cc5ac..825a22e 100644
    a b class getid3_matroska extends getid3_handler 
    234234                try {
    235235                        $this->parseEBML($info);
    236236                } catch (Exception $e) {
    237                         $info['error'][] = 'EBML parser: '.$e->getMessage();
     237                        $this->error('EBML parser: '.$e->getMessage());
    238238                }
    239239
    240240                // calculate playtime
    class getid3_matroska extends getid3_handler 
    330330                                                                break;
    331331
    332332                                                        case 'A_AC3':
     333                                                        case 'A_EAC3':
    333334                                                        case 'A_DTS':
    334335                                                        case 'A_MPEG/L3':
    335336                                                        case 'A_MPEG/L2':
    336337                                                        case 'A_FLAC':
    337                                                                 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']).'.php', __FILE__, true);
     338                                                                $module_dataformat = ($track_info['dataformat'] == 'mp2' ? 'mp3' : ($track_info['dataformat'] == 'eac3' ? 'ac3' : $track_info['dataformat']));
     339                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.'.$module_dataformat.'.php', __FILE__, true);
    338340
    339341                                                                if (!isset($info['matroska']['track_data_offsets'][$trackarray['TrackNumber']])) {
    340342                                                                        $this->warning('Unable to parse audio data ['.basename(__FILE__).':'.__LINE__.'] because $info[matroska][track_data_offsets]['.$trackarray['TrackNumber'].'] not set');
    class getid3_matroska extends getid3_handler 
    352354                                                                }
    353355
    354356                                                                // analyze
    355                                                                 $class = 'getid3_'.($track_info['dataformat'] == 'mp2' ? 'mp3' : $track_info['dataformat']);
     357                                                                $class = 'getid3_'.$module_dataformat;
    356358                                                                $header_data_key = $track_info['dataformat'][0] == 'm' ? 'mpeg' : $track_info['dataformat'];
    357359                                                                $getid3_audio = new $class($getid3_temp, __CLASS__);
    358360                                                                if ($track_info['dataformat'] == 'flac') {
    class getid3_matroska extends getid3_handler 
    457459
    458460                                                        default:
    459461                                                                $this->warning('Unhandled audio type "'.(isset($trackarray['CodecID']) ? $trackarray['CodecID'] : '').'"');
     462                                                                break;
    460463                                                }
    461464
    462465                                                $info['audio']['streams'][] = $track_info;
    class getid3_matroska extends getid3_handler 
    524527
    525528                                                        default:
    526529                                                                $this->unhandledElement('header', __LINE__, $element_data);
     530                                                                break;
    527531                                                }
    528532
    529533                                                unset($element_data['offset'], $element_data['end']);
    class getid3_matroska extends getid3_handler 
    562566
    563567                                                                                                        default:
    564568                                                                                                                $this->unhandledElement('seekhead.seek', __LINE__, $sub_seek_entry);                                                                                            }
     569                                                                                                                break;
    565570                                                                                        }
    566 
    567                                                                                         if ($seek_entry['target_id'] != EBML_ID_CLUSTER || !self::$hide_clusters) { // collect clusters only if required
     571                                                                                        if (!isset($seek_entry['target_id'])) {
     572                                                                                                $this->warning('seek_entry[target_id] unexpectedly not set at '.$seek_entry['offset']);
     573                                                                                                break;
     574                                                                                        }
     575                                                                                        if (($seek_entry['target_id'] != EBML_ID_CLUSTER) || !self::$hide_clusters) { // collect clusters only if required
    568576                                                                                                $info['matroska']['seek'][] = $seek_entry;
    569577                                                                                        }
    570578                                                                                        break;
    571579
    572580                                                                                default:
    573581                                                                                        $this->unhandledElement('seekhead', __LINE__, $seek_entry);
     582                                                                                        break;
    574583                                                                        }
    575584                                                                }
    576585                                                                break;
    class getid3_matroska extends getid3_handler 
    653662
    654663                                                                                                                                default:
    655664                                                                                                                                        $this->unhandledElement('track.video', __LINE__, $sub_subelement);
     665                                                                                                                                        break;
    656666                                                                                                                        }
    657667                                                                                                                }
    658668                                                                                                                break;
    class getid3_matroska extends getid3_handler 
    678688
    679689                                                                                                                                default:
    680690                                                                                                                                        $this->unhandledElement('track.audio', __LINE__, $sub_subelement);
     691                                                                                                                                        break;
    681692                                                                                                                        }
    682693                                                                                                                }
    683694                                                                                                                break;
    class getid3_matroska extends getid3_handler 
    713724
    714725                                                                                                                                                                                default:
    715726                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     727                                                                                                                                                                                        break;
    716728                                                                                                                                                                        }
    717729                                                                                                                                                                }
    718730                                                                                                                                                                break;
    class getid3_matroska extends getid3_handler 
    736748
    737749                                                                                                                                                                                default:
    738750                                                                                                                                                                                        $this->unhandledElement('track.contentencodings.contentencoding.contentcompression', __LINE__, $sub_sub_sub_subelement);
     751                                                                                                                                                                                        break;
    739752                                                                                                                                                                        }
    740753                                                                                                                                                                }
    741754                                                                                                                                                                break;
    742755
    743756                                                                                                                                                        default:
    744757                                                                                                                                                                $this->unhandledElement('track.contentencodings.contentencoding', __LINE__, $sub_sub_subelement);
     758                                                                                                                                                                break;
    745759                                                                                                                                                }
    746760                                                                                                                                        }
    747761                                                                                                                                        break;
    748762
    749763                                                                                                                                default:
    750764                                                                                                                                        $this->unhandledElement('track.contentencodings', __LINE__, $sub_subelement);
     765                                                                                                                                        break;
    751766                                                                                                                        }
    752767                                                                                                                }
    753768                                                                                                                break;
    754769
    755770                                                                                                        default:
    756771                                                                                                                $this->unhandledElement('track', __LINE__, $subelement);
     772                                                                                                                break;
    757773                                                                                                }
    758774                                                                                        }
    759775
    class getid3_matroska extends getid3_handler 
    762778
    763779                                                                                default:
    764780                                                                                        $this->unhandledElement('tracks', __LINE__, $track_entry);
     781                                                                                        break;
    765782                                                                        }
    766783                                                                }
    767784                                                                break;
    class getid3_matroska extends getid3_handler 
    825842
    826843                                                                                                        default:
    827844                                                                                                                $this->unhandledElement('info.chaptertranslate', __LINE__, $sub_subelement);
     845                                                                                                                break;
    828846                                                                                                }
    829847                                                                                        }
    830848                                                                                        $info_entry[$subelement['id_name']] = $chaptertranslate_entry;
    class getid3_matroska extends getid3_handler 
    832850
    833851                                                                                default:
    834852                                                                                        $this->unhandledElement('info', __LINE__, $subelement);
     853                                                                                        break;
    835854                                                                        }
    836855                                                                }
    837856                                                                $info['matroska']['info'][] = $info_entry;
    class getid3_matroska extends getid3_handler 
    868887
    869888                                                                                                                                default:
    870889                                                                                                                                        $this->unhandledElement('cues.cuepoint.cuetrackpositions', __LINE__, $sub_sub_subelement);
     890                                                                                                                                        break;
    871891                                                                                                                        }
    872892                                                                                                                }
    873893                                                                                                                $cuepoint_entry[$sub_subelement['id_name']][] = $cuetrackpositions_entry;
    class getid3_matroska extends getid3_handler 
    879899
    880900                                                                                                        default:
    881901                                                                                                                $this->unhandledElement('cues.cuepoint', __LINE__, $sub_subelement);
     902                                                                                                                break;
    882903                                                                                                }
    883904                                                                                        }
    884905                                                                                        $cues_entry[] = $cuepoint_entry;
    class getid3_matroska extends getid3_handler 
    886907
    887908                                                                                default:
    888909                                                                                        $this->unhandledElement('cues', __LINE__, $subelement);
     910                                                                                        break;
    889911                                                                        }
    890912                                                                }
    891913                                                                $info['matroska']['cues'] = $cues_entry;
    class getid3_matroska extends getid3_handler 
    927949
    928950                                                                                                                                default:
    929951                                                                                                                                        $this->unhandledElement('tags.tag.targets', __LINE__, $sub_sub_subelement);
     952                                                                                                                                        break;
    930953                                                                                                                        }
    931954                                                                                                                }
    932955                                                                                                                $tag_entry[$sub_subelement['id_name']] = $targets_entry;
    class getid3_matroska extends getid3_handler 
    938961
    939962                                                                                                        default:
    940963                                                                                                                $this->unhandledElement('tags.tag', __LINE__, $sub_subelement);
     964                                                                                                                break;
    941965                                                                                                }
    942966                                                                                        }
    943967                                                                                        $tags_entry[] = $tag_entry;
    class getid3_matroska extends getid3_handler 
    945969
    946970                                                                                default:
    947971                                                                                        $this->unhandledElement('tags', __LINE__, $subelement);
     972                                                                                        break;
    948973                                                                        }
    949974                                                                }
    950975                                                                $info['matroska']['tags'] = $tags_entry;
    class getid3_matroska extends getid3_handler 
    9851010
    9861011                                                                                                        default:
    9871012                                                                                                                $this->unhandledElement('attachments.attachedfile', __LINE__, $sub_subelement);
     1013                                                                                                                break;
    9881014                                                                                                }
    9891015                                                                                        }
    9901016                                                                                        $info['matroska']['attachments'][] = $attachedfile_entry;
    class getid3_matroska extends getid3_handler 
    9921018
    9931019                                                                                default:
    9941020                                                                                        $this->unhandledElement('attachments', __LINE__, $subelement);
     1021                                                                                        break;
    9951022                                                                        }
    9961023                                                                }
    9971024                                                                break;
    class getid3_matroska extends getid3_handler 
    10511078
    10521079                                                                                                                                                        default:
    10531080                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chaptertrack', __LINE__, $sub_sub_sub_subelement);
     1081                                                                                                                                                                break;
    10541082                                                                                                                                                }
    10551083                                                                                                                                        }
    10561084                                                                                                                                        $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chaptertrack_entry;
    class getid3_matroska extends getid3_handler 
    10701098
    10711099                                                                                                                                                        default:
    10721100                                                                                                                                                                $this->unhandledElement('chapters.editionentry.chapteratom.chapterdisplay', __LINE__, $sub_sub_sub_subelement);
     1101                                                                                                                                                                break;
    10731102                                                                                                                                                }
    10741103                                                                                                                                        }
    10751104                                                                                                                                        $chapteratom_entry[$sub_sub_subelement['id_name']][] = $chapterdisplay_entry;
    class getid3_matroska extends getid3_handler 
    10771106
    10781107                                                                                                                                default:
    10791108                                                                                                                                        $this->unhandledElement('chapters.editionentry.chapteratom', __LINE__, $sub_sub_subelement);
     1109                                                                                                                                        break;
    10801110                                                                                                                        }
    10811111                                                                                                                }
    10821112                                                                                                                $editionentry_entry[$sub_subelement['id_name']][] = $chapteratom_entry;
    class getid3_matroska extends getid3_handler 
    10841114
    10851115                                                                                                        default:
    10861116                                                                                                                $this->unhandledElement('chapters.editionentry', __LINE__, $sub_subelement);
     1117                                                                                                                break;
    10871118                                                                                                }
    10881119                                                                                        }
    10891120                                                                                        $info['matroska']['chapters'][] = $editionentry_entry;
    class getid3_matroska extends getid3_handler 
    10911122
    10921123                                                                                default:
    10931124                                                                                        $this->unhandledElement('chapters', __LINE__, $subelement);
     1125                                                                                        break;
    10941126                                                                        }
    10951127                                                                }
    10961128                                                                break;
    class getid3_matroska extends getid3_handler 
    11191151
    11201152                                                                                                        default:
    11211153                                                                                                                $this->unhandledElement('cluster.silenttracks', __LINE__, $sub_subelement);
     1154                                                                                                                break;
    11221155                                                                                                }
    11231156                                                                                        }
    11241157                                                                                        $cluster_entry[$subelement['id_name']][] = $cluster_silent_tracks;
    class getid3_matroska extends getid3_handler 
    11491182
    11501183                                                                                                        default:
    11511184                                                                                                                $this->unhandledElement('clusters.blockgroup', __LINE__, $sub_subelement);
     1185                                                                                                                break;
    11521186                                                                                                }
    11531187                                                                                        }
    11541188                                                                                        $cluster_entry[$subelement['id_name']][] = $cluster_block_group;
    class getid3_matroska extends getid3_handler 
    11601194
    11611195                                                                                default:
    11621196                                                                                        $this->unhandledElement('cluster', __LINE__, $subelement);
     1197                                                                                        break;
    11631198                                                                        }
    11641199                                                                        $this->current_offset = $subelement['end'];
    11651200                                                                }
    class getid3_matroska extends getid3_handler 
    11811216
    11821217                                                        default:
    11831218                                                                $this->unhandledElement('segment', __LINE__, $element_data);
     1219                                                                break;
    11841220                                                }
    11851221                                        }
    11861222                                        break;
    11871223
    11881224                                default:
    11891225                                        $this->unhandledElement('root', __LINE__, $top_element);
     1226                                        break;
    11901227                        }
    11911228                }
    11921229        }
    class getid3_matroska extends getid3_handler 
    13391376
    13401377                                default:
    13411378                                        $this->unhandledElement('tag.simpletag', __LINE__, $element);
     1379                                        break;
    13421380                        }
    13431381                }
    13441382
    class getid3_matroska extends getid3_handler 
    14901528                        $CodecIDlist['A_AAC']            = 'aac';
    14911529                        $CodecIDlist['A_AAC/MPEG2/LC']   = 'aac';
    14921530                        $CodecIDlist['A_AC3']            = 'ac3';
     1531                        $CodecIDlist['A_EAC3']           = 'eac3';
    14931532                        $CodecIDlist['A_DTS']            = 'dts';
    14941533                        $CodecIDlist['A_FLAC']           = 'flac';
    14951534                        $CodecIDlist['A_MPEG/L1']        = 'mp1';
  • src/wp-includes/ID3/module.audio-video.quicktime.php

    diff --git a/src/wp-includes/ID3/module.audio-video.quicktime.php b/src/wp-includes/ID3/module.audio-video.quicktime.php
    index 482c091..6f29ca4 100644
    a b class getid3_quicktime extends getid3_handler 
    3535
    3636                $offset      = 0;
    3737                $atomcounter = 0;
    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
     38                $atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
    3939                while ($offset < $info['avdataend']) {
    4040                        if (!getid3_lib::intValueSupported($offset)) {
    41                                 $info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';
     41                                $this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions');
    4242                                break;
    4343                        }
    4444                        $this->fseek($offset);
    class getid3_quicktime extends getid3_handler 
    5757                        $info['quicktime'][$atomname]['offset'] = $offset;
    5858
    5959                        if (($offset + $atomsize) > $info['avdataend']) {
    60                                 $info['error'][] = 'Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)';
     60                                $this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
    6161                                return false;
    6262                        }
    6363
    class getid3_quicktime extends getid3_handler 
    8181                        unset($info['avdataend_tmp']);
    8282                }
    8383
     84                if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
     85                        $durations = $this->quicktime_time_to_sample_table($info);
     86                        for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
     87                                $bookmark = array();
     88                                $bookmark['title'] = $info['quicktime']['comments']['chapters'][$i];
     89                                if (isset($durations[$i])) {
     90                                        $bookmark['duration_sample'] = $durations[$i]['sample_duration'];
     91                                        if ($i > 0) {
     92                                                $bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample'];
     93                                        } else {
     94                                                $bookmark['start_sample'] = 0;
     95                                        }
     96                                        if ($time_scale = $this->quicktime_bookmark_time_scale($info)) {
     97                                                $bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale;
     98                                                $bookmark['start_seconds']    = $bookmark['start_sample']    / $time_scale;
     99                                        }
     100                                }
     101                                $info['quicktime']['bookmarks'][] = $bookmark;
     102                        }
     103                }
     104
     105                if (isset($info['quicktime']['temp_meta_key_names'])) {
     106                        unset($info['quicktime']['temp_meta_key_names']);
     107                }
     108
     109                if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
     110                        // https://en.wikipedia.org/wiki/ISO_6709
     111                        foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
     112                                $latitude  = false;
     113                                $longitude = false;
     114                                $altitude  = false;
     115                                if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
     116                                        @list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
     117
     118                                        if (strlen($lat_deg) == 2) {        // [+-]DD.D
     119                                                $latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
     120                                        } elseif (strlen($lat_deg) == 4) {  // [+-]DDMM.M
     121                                                $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
     122                                        } elseif (strlen($lat_deg) == 6) {  // [+-]DDMMSS.S
     123                                                $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
     124                                        }
     125
     126                                        if (strlen($lon_deg) == 3) {        // [+-]DDD.D
     127                                                $longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
     128                                        } elseif (strlen($lon_deg) == 5) {  // [+-]DDDMM.M
     129                                                $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
     130                                        } elseif (strlen($lon_deg) == 7) {  // [+-]DDDMMSS.S
     131                                                $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
     132                                        }
     133
     134                                        if (strlen($alt_deg) == 3) {        // [+-]DDD.D
     135                                                $altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
     136                                        } elseif (strlen($alt_deg) == 5) {  // [+-]DDDMM.M
     137                                                $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
     138                                        } elseif (strlen($alt_deg) == 7) {  // [+-]DDDMMSS.S
     139                                                $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
     140                                        }
     141
     142                                        if ($latitude !== false) {
     143                                                $info['quicktime']['comments']['gps_latitude'][]  = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
     144                                        }
     145                                        if ($longitude !== false) {
     146                                                $info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
     147                                        }
     148                                        if ($altitude !== false) {
     149                                                $info['quicktime']['comments']['gps_altitude'][]  = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
     150                                        }
     151                                }
     152                                if ($latitude === false) {
     153                                        $this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
     154                                }
     155                                break;
     156                        }
     157                }
     158
    84159                if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
    85160                        $info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
    86161                }
    class getid3_quicktime extends getid3_handler 
    98173                                }
    99174                        }
    100175                }
    101                 if (($info['audio']['dataformat'] == 'mp4') && empty($info['video']['resolution_x'])) {
     176                if ($info['audio']['dataformat'] == 'mp4') {
    102177                        $info['fileformat'] = 'mp4';
    103                         $info['mime_type']  = 'audio/mp4';
    104                         unset($info['video']['dataformat']);
     178                        if (empty($info['video']['resolution_x'])) {
     179                                $info['mime_type']  = 'audio/mp4';
     180                                unset($info['video']['dataformat']);
     181                        } else {
     182                                $info['mime_type']  = 'video/mp4';
     183                        }
    105184                }
    106185
    107186                if (!$this->ReturnAtomData) {
    class getid3_quicktime extends getid3_handler 
    120199
    121200        public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
    122201                // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
     202                // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
    123203
    124204                $info = &$this->getid3->info;
    125205
    class getid3_quicktime extends getid3_handler 
    222302                                break;
    223303
    224304
     305                        case "\xA9".'alb': // ALBum
     306                        case "\xA9".'ART': //
     307                        case "\xA9".'art': // ARTist
     308                        case "\xA9".'aut': //
     309                        case "\xA9".'cmt': // CoMmenT
     310                        case "\xA9".'com': // COMposer
     311                        case "\xA9".'cpy': //
     312                        case "\xA9".'day': // content created year
     313                        case "\xA9".'dir': //
     314                        case "\xA9".'ed1': //
     315                        case "\xA9".'ed2': //
     316                        case "\xA9".'ed3': //
     317                        case "\xA9".'ed4': //
     318                        case "\xA9".'ed5': //
     319                        case "\xA9".'ed6': //
     320                        case "\xA9".'ed7': //
     321                        case "\xA9".'ed8': //
     322                        case "\xA9".'ed9': //
     323                        case "\xA9".'enc': //
     324                        case "\xA9".'fmt': //
     325                        case "\xA9".'gen': // GENre
     326                        case "\xA9".'grp': // GRouPing
     327                        case "\xA9".'hst': //
     328                        case "\xA9".'inf': //
     329                        case "\xA9".'lyr': // LYRics
     330                        case "\xA9".'mak': //
     331                        case "\xA9".'mod': //
     332                        case "\xA9".'nam': // full NAMe
     333                        case "\xA9".'ope': //
     334                        case "\xA9".'PRD': //
     335                        case "\xA9".'prf': //
     336                        case "\xA9".'req': //
     337                        case "\xA9".'src': //
     338                        case "\xA9".'swr': //
     339                        case "\xA9".'too': // encoder
     340                        case "\xA9".'trk': // TRacK
     341                        case "\xA9".'url': //
     342                        case "\xA9".'wrn': //
     343                        case "\xA9".'wrt': // WRiTer
     344                        case '----': // itunes specific
    225345                        case 'aART': // Album ARTist
     346                        case 'akID': // iTunes store account type
     347                        case 'apID': // Purchase Account
     348                        case 'atID': //
    226349                        case 'catg': // CaTeGory
     350                        case 'cmID': //
     351                        case 'cnID': //
    227352                        case 'covr': // COVeR artwork
    228353                        case 'cpil': // ComPILation
    229354                        case 'cprt': // CoPyRighT
    230355                        case 'desc': // DESCription
    231356                        case 'disk': // DISK number
    232357                        case 'egid': // Episode Global ID
     358                        case 'geID': //
    233359                        case 'gnre': // GeNRE
     360                        case 'hdvd': // HD ViDeo
    234361                        case 'keyw': // KEYWord
    235                         case 'ldes':
     362                        case 'ldes': // Long DEScription
    236363                        case 'pcst': // PodCaST
    237364                        case 'pgap': // GAPless Playback
     365                        case 'plID': //
    238366                        case 'purd': // PURchase Date
    239367                        case 'purl': // Podcast URL
    240                         case 'rati':
    241                         case 'rndu':
    242                         case 'rpdu':
     368                        case 'rati': //
     369                        case 'rndu': //
     370                        case 'rpdu': //
    243371                        case 'rtng': // RaTiNG
    244                         case 'stik':
     372                        case 'sfID': // iTunes store country
     373                        case 'soaa': // SOrt Album Artist
     374                        case 'soal': // SOrt ALbum
     375                        case 'soar': // SOrt ARtist
     376                        case 'soco': // SOrt COmposer
     377                        case 'sonm': // SOrt NaMe
     378                        case 'sosn': // SOrt Show Name
     379                        case 'stik': //
    245380                        case 'tmpo': // TeMPO (BPM)
    246381                        case 'trkn': // TRacK Number
     382                        case 'tven': // tvEpisodeID
    247383                        case 'tves': // TV EpiSode
    248384                        case 'tvnn': // TV Network Name
    249385                        case 'tvsh': // TV SHow Name
    250386                        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
    300387                                if ($atom_parent == 'udta') {
    301388                                        // User data atom handler
    302389                                        $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
    class getid3_quicktime extends getid3_handler 
    318405                                                        $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
    319406                                                        $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
    320407                                                        if ($boxsmallsize <= 1) {
    321                                                                 $info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
     408                                                                $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
    322409                                                                $atom_structure['data'] = null;
    323410                                                                $atomoffset = strlen($atom_data);
    324411                                                                break;
    class getid3_quicktime extends getid3_handler 
    328415                                                                        $atom_structure['data'] = $boxsmalldata;
    329416                                                                        break;
    330417                                                                default:
    331                                                                         $info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset;
     418                                                                        $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
    332419                                                                        $atom_structure['data'] = $atom_data;
    333420                                                                        break;
    334421                                                        }
    class getid3_quicktime extends getid3_handler 
    340427                                                        $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
    341428                                                        $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
    342429                                                        if ($boxsize <= 1) {
    343                                                                 $info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
     430                                                                $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
    344431                                                                $atom_structure['data'] = null;
    345432                                                                $atomoffset = strlen($atom_data);
    346433                                                                break;
    class getid3_quicktime extends getid3_handler 
    361448                                                                                case 21: // tmpo/cpil flag
    362449                                                                                        switch ($atomname) {
    363450                                                                                                case 'cpil':
     451                                                                                                case 'hdvd':
    364452                                                                                                case 'pcst':
    365453                                                                                                case 'pgap':
     454                                                                                                        // 8-bit integer (boolean)
    366455                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    367456                                                                                                        break;
    368457
    369458                                                                                                case 'tmpo':
     459                                                                                                        // 16-bit integer
    370460                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
    371461                                                                                                        break;
    372462
    373463                                                                                                case 'disk':
    374464                                                                                                case 'trkn':
     465                                                                                                        // binary
    375466                                                                                                        $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
    376467                                                                                                        $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
    377468                                                                                                        $atom_structure['data']  = empty($num) ? '' : $num;
    class getid3_quicktime extends getid3_handler 
    379470                                                                                                        break;
    380471
    381472                                                                                                case 'gnre':
     473                                                                                                        // enum
    382474                                                                                                        $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    383475                                                                                                        $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
    384476                                                                                                        break;
    385477
    386478                                                                                                case 'rtng':
     479                                                                                                        // 8-bit integer
    387480                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    388481                                                                                                        $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
    389482                                                                                                        break;
    390483
    391484                                                                                                case 'stik':
     485                                                                                                        // 8-bit integer (enum)
    392486                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    393487                                                                                                        $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
    394488                                                                                                        break;
    395489
    396490                                                                                                case 'sfID':
     491                                                                                                        // 32-bit integer
    397492                                                                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    398493                                                                                                        $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
    399494                                                                                                        break;
    class getid3_quicktime extends getid3_handler 
    403498                                                                                                        $atom_structure['data'] = substr($boxdata, 8);
    404499                                                                                                        break;
    405500
     501                                                                                                case 'plID':
     502                                                                                                        // 64-bit integer
     503                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
     504                                                                                                        break;
     505
     506                                                                                                case 'covr':
     507                                                                                                        $atom_structure['data'] = substr($boxdata, 8);
     508                                                                                                        // not a foolproof check, but better than nothing
     509                                                                                                        if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
     510                                                                                                                $atom_structure['image_mime'] = 'image/jpeg';
     511                                                                                                        } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
     512                                                                                                                $atom_structure['image_mime'] = 'image/png';
     513                                                                                                        } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
     514                                                                                                                $atom_structure['image_mime'] = 'image/gif';
     515                                                                                                        }
     516                                                                                                        break;
     517
     518                                                                                                case 'atID':
     519                                                                                                case 'cnID':
     520                                                                                                case 'geID':
     521                                                                                                case 'tves':
     522                                                                                                case 'tvsn':
    406523                                                                                                default:
     524                                                                                                        // 32-bit integer
    407525                                                                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    408526                                                                                        }
    409527                                                                                        break;
    class getid3_quicktime extends getid3_handler 
    414532                                                                                        $atom_structure['data'] = substr($boxdata, 8);
    415533                                                                                        if ($atomname == 'covr') {
    416534                                                                                                // not a foolproof check, but better than nothing
    417                                                                                                 if (preg_match('#^\xFF\xD8\xFF#', $atom_structure['data'])) {
     535                                                                                                if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
    418536                                                                                                        $atom_structure['image_mime'] = 'image/jpeg';
    419                                                                                                 } elseif (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) {
     537                                                                                                } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
    420538                                                                                                        $atom_structure['image_mime'] = 'image/png';
    421539                                                                                                } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
    422540                                                                                                        $atom_structure['image_mime'] = 'image/gif';
    class getid3_quicktime extends getid3_handler 
    428546                                                                        break;
    429547
    430548                                                                default:
    431                                                                         $info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset;
     549                                                                        $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
    432550                                                                        $atom_structure['data'] = $atom_data;
    433551
    434552                                                        }
    class getid3_quicktime extends getid3_handler 
    476594                                if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
    477595                                        $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
    478596                                } else {
    479                                         $info['warning'][] = 'Error decompressing compressed MOV atom at offset '.$atom_structure['offset'];
     597                                        $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
    480598                                }
    481599                                break;
    482600
    class getid3_quicktime extends getid3_handler 
    595713                                if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
    596714                                        $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
    597715                                } else {
    598                                         $info['warning'][] = 'unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')';
     716                                        $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
    599717                                }
    600718                                break;
    601719
    class getid3_quicktime extends getid3_handler 
    604722                                $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    605723                                $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    606724                                $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
     725
     726                                // see: https://github.com/JamesHeinrich/getID3/issues/111
     727                                // Some corrupt files have been known to have high bits set in the number_entries field
     728                                // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
     729                                // Workaround: mask off the upper byte and throw a warning if it's nonzero
     730                                if ($atom_structure['number_entries'] > 0x000FFFFF) {
     731                                        if ($atom_structure['number_entries'] > 0x00FFFFFF) {
     732                                                $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF));
     733                                                $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
     734                                        } else {
     735                                                $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111');
     736                                        }
     737                                }
     738
    607739                                $stsdEntriesDataOffset = 8;
    608740                                for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    609741                                        $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    801933
    802934                                $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
    803935                                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($atom_structure['number_entries'] / 1048576).'MB).';
     936                                        $this->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).');
    805937                                }
    806938                                for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
    807939                                        $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    9281060                                for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    9291061                                        $atom_structure['data_references'][$i]['size']                    = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
    9301062                                        $drefDataOffset += 4;
    931                                         $atom_structure['data_references'][$i]['type']                    =               substr($atom_data, $drefDataOffset, 4);
     1063                                        $atom_structure['data_references'][$i]['type']                    =                           substr($atom_data, $drefDataOffset, 4);
    9321064                                        $drefDataOffset += 4;
    9331065                                        $atom_structure['data_references'][$i]['version']                 = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 1));
    9341066                                        $drefDataOffset += 1;
    9351067                                        $atom_structure['data_references'][$i]['flags_raw']               = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 3)); // hardcoded: 0x0000
    9361068                                        $drefDataOffset += 3;
    937                                         $atom_structure['data_references'][$i]['data']                    =               substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
     1069                                        $atom_structure['data_references'][$i]['data']                    =                           substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
    9381070                                        $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
    9391071
    9401072                                        $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    10011133                                $atom_structure['quality']               = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
    10021134
    10031135                                if ($atom_structure['time_scale'] == 0) {
    1004                                         $info['error'][] = 'Corrupt Quicktime file: mdhd.time_scale == zero';
     1136                                        $this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
    10051137                                        return false;
    10061138                                }
    1007                                 $info['quicktime']['time_scale'] = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
     1139                                $info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
    10081140
    10091141                                $atom_structure['creation_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
    10101142                                $atom_structure['modify_time_unix']      = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    10191151                        case 'pnot': // Preview atom
    10201152                                $atom_structure['modification_date']      = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // "standard Macintosh format"
    10211153                                $atom_structure['version_number']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x00
    1022                                 $atom_structure['atom_type']              =               substr($atom_data,  6, 4);        // usually: 'PICT'
     1154                                $atom_structure['atom_type']              =                           substr($atom_data,  6, 4);        // usually: 'PICT'
    10231155                                $atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
    10241156
    10251157                                $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    10291161                        case 'crgn': // Clipping ReGioN atom
    10301162                                $atom_structure['region_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2)); // The Region size, Region boundary box,
    10311163                                $atom_structure['boundary_box']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 8)); // and Clipping region data fields
    1032                                 $atom_structure['clipping_data'] =               substr($atom_data, 10);           // constitute a QuickDraw region.
     1164                                $atom_structure['clipping_data'] =                           substr($atom_data, 10);           // constitute a QuickDraw region.
    10331165                                break;
    10341166
    10351167
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    11151247                                $atom_structure['next_track_id']      =   getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
    11161248
    11171249                                if ($atom_structure['time_scale'] == 0) {
    1118                                         $info['error'][] = 'Corrupt Quicktime file: mvhd.time_scale == zero';
     1250                                        $this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
    11191251                                        return false;
    11201252                                }
    11211253                                $atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
    11221254                                $atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
    1123                                 $info['quicktime']['time_scale']    = (isset($info['quicktime']['time_scale']) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
     1255                                $info['quicktime']['time_scale']    = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
    11241256                                $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
    11251257                                $info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
    11261258                                break;
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    12401372                                }
    12411373
    12421374                                // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
    1243                                 while  (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
     1375                                while (($mdat_offset < (strlen($atom_data) - 8))
     1376                                        && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
    12441377                                        && ($chapter_string_length < 1000)
    12451378                                        && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
    1246                                         && preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
     1379                                        && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
     1380                                                list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
    12471381                                                $mdat_offset += (2 + $chapter_string_length);
    1248                                                 @$info['quicktime']['comments']['chapters'][] = $chapter_matches[0];
    1249                                 }
     1382                                                @$info['quicktime']['comments']['chapters'][] = $chapter_string;
    12501383
     1384                                                // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
     1385                                                if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
     1386                                                        $mdat_offset += 12;
     1387                                                }
     1388                                }
    12511389
    12521390
    12531391                                if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    12651403                                                $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
    12661404                                                if (!empty($getid3_temp->info['warning'])) {
    12671405                                                        foreach ($getid3_temp->info['warning'] as $value) {
    1268                                                                 $info['warning'][] = $value;
     1406                                                                $this->warning($value);
    12691407                                                        }
    12701408                                                }
    12711409                                                if (!empty($getid3_temp->info['mpeg'])) {
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    13681506                                                $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
    13691507                                        }
    13701508                                } else {
    1371                                         $info['warning'][] = 'QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.';
     1509                                        $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
    13721510                                }
    13731511                                break;
    13741512
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    13971535                                break;
    13981536
    13991537                        case "\x00\x00\x00\x00":
    1400                         case 'meta': // METAdata atom
    14011538                                // some kind of metacontainer, may contain a big data dump such as:
    14021539                                // 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
    14031540                                // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
    14041541
    1405                     $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
    1406                     $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
    1407                     $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
     1542                                $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
     1543                                $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
     1544                                $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    14081545                                //$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    14091546                                break;
    14101547
     1548                        case 'meta': // METAdata atom
     1549                                // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
     1550
     1551                                $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
     1552                                $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
     1553                                $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
     1554                                break;
     1555
    14111556                        case 'data': // metaDATA atom
     1557                                static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
    14121558                                // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
    14131559                                $atom_structure['language'] =                           substr($atom_data, 4 + 0, 2);
    14141560                                $atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
    14151561                                $atom_structure['data']     =                           substr($atom_data, 4 + 4);
     1562                                $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
     1563
     1564                                if ($atom_structure['key_name'] && $atom_structure['data']) {
     1565                                        @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
     1566                                }
    14161567                                break;
    14171568
     1569                        case 'keys': // KEYS that may be present in the metadata atom.
     1570                                // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
     1571                                // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
     1572                                // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
     1573                                $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     1574                                $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
     1575                                $atom_structure['entry_count']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
     1576                                $keys_atom_offset = 8;
     1577                                for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
     1578                                        $atom_structure['keys'][$i]['key_size']      = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
     1579                                        $atom_structure['keys'][$i]['key_namespace'] =                           substr($atom_data, $keys_atom_offset + 4, 4);
     1580                                        $atom_structure['keys'][$i]['key_value']     =                           substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
     1581                                        $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
     1582
     1583                                        $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
     1584                                }
     1585                                break;
     1586
     1587                        case 'gps ':
     1588                                // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
     1589                                // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
     1590                                // The first row is version/metadata/notsure, I skip that.
     1591                                // The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file.
     1592
     1593                                $GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size
     1594                                if (strlen($atom_data) > 0) {
     1595                                        if ((strlen($atom_data) % $GPS_rowsize) == 0) {
     1596                                                $atom_structure['gps_toc'] = array();
     1597                                                foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) {
     1598                                                        $atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize));
     1599                                                }
     1600
     1601                                                $atom_structure['gps_entries'] = array();
     1602                                                $previous_offset = $this->ftell();
     1603                                                foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) {
     1604                                                        if ($key == 0) {
     1605                                                                // "The first row is version/metadata/notsure, I skip that."
     1606                                                                continue;
     1607                                                        }
     1608                                                        $this->fseek($gps_pointer['offset']);
     1609                                                        $GPS_free_data = $this->fread($gps_pointer['size']);
     1610
     1611                                                        /*
     1612                                                        // 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead
     1613
     1614                                                        // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
     1615                                                        // The structure of the GPS data atom (the 'free' atoms mentioned above) is following:
     1616                                                        // hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48)
     1617                                                        // For those unfamiliar with python struct:
     1618                                                        // I = int
     1619                                                        // s = is string (size 1, in this case)
     1620                                                        // f = float
     1621
     1622                                                        //$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48));
     1623                                                        */
     1624
     1625                                                        // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
     1626                                                        // $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67
     1627                                                        // $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F
     1628                                                        // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
     1629                                                        if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
     1630                                                                $GPS_this_GPRMC = array();
     1631                                                                list(
     1632                                                                        $GPS_this_GPRMC['raw']['gprmc'],
     1633                                                                        $GPS_this_GPRMC['raw']['timestamp'],
     1634                                                                        $GPS_this_GPRMC['raw']['status'],
     1635                                                                        $GPS_this_GPRMC['raw']['latitude'],
     1636                                                                        $GPS_this_GPRMC['raw']['latitude_direction'],
     1637                                                                        $GPS_this_GPRMC['raw']['longitude'],
     1638                                                                        $GPS_this_GPRMC['raw']['longitude_direction'],
     1639                                                                        $GPS_this_GPRMC['raw']['knots'],
     1640                                                                        $GPS_this_GPRMC['raw']['angle'],
     1641                                                                        $GPS_this_GPRMC['raw']['datestamp'],
     1642                                                                        $GPS_this_GPRMC['raw']['variation'],
     1643                                                                        $GPS_this_GPRMC['raw']['variation_direction'],
     1644                                                                        $dummy,
     1645                                                                        $GPS_this_GPRMC['raw']['checksum'],
     1646                                                                ) = $matches;
     1647
     1648                                                                $hour   = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
     1649                                                                $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
     1650                                                                $second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2);
     1651                                                                $ms     = substr($GPS_this_GPRMC['raw']['timestamp'], 6);    // may contain decimal seconds
     1652                                                                $day   = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
     1653                                                                $month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
     1654                                                                $year  = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
     1655                                                                $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
     1656                                                                $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
     1657
     1658                                                                $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
     1659
     1660                                                                foreach (array('latitude','longitude') as $latlon) {
     1661                                                                        preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches);
     1662                                                                        list($dummy, $deg, $min) = $matches;
     1663                                                                        $GPS_this_GPRMC[$latlon] = $deg + ($min / 60);
     1664                                                                }
     1665                                                                $GPS_this_GPRMC['latitude']  *= (($GPS_this_GPRMC['raw']['latitude_direction']  == 'S') ? -1 : 1);
     1666                                                                $GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1);
     1667
     1668                                                                $GPS_this_GPRMC['heading']    = $GPS_this_GPRMC['raw']['angle'];
     1669                                                                $GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots'];
     1670                                                                $GPS_this_GPRMC['speed_kmh']  = $GPS_this_GPRMC['raw']['knots'] * 1.852;
     1671                                                                if ($GPS_this_GPRMC['raw']['variation']) {
     1672                                                                        $GPS_this_GPRMC['variation']  = $GPS_this_GPRMC['raw']['variation'];
     1673                                                                        $GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1);
     1674                                                                }
     1675
     1676                                                                $atom_structure['gps_entries'][$key] = $GPS_this_GPRMC;
     1677
     1678                                                                @$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array(
     1679                                                                        'latitude'  => $GPS_this_GPRMC['latitude'],
     1680                                                                        'longitude' => $GPS_this_GPRMC['longitude'],
     1681                                                                        'speed_kmh' => $GPS_this_GPRMC['speed_kmh'],
     1682                                                                        'heading'   => $GPS_this_GPRMC['heading'],
     1683                                                                );
     1684
     1685                                                        } else {
     1686                                                                $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
     1687                                                        }
     1688                                                }
     1689                                                $this->fseek($previous_offset);
     1690
     1691                                        } else {
     1692                                                $this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset);
     1693                                        }
     1694                                } else {
     1695                                        $this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset);
     1696                                }
     1697                                break;
     1698
     1699                        case 'loci':// 3GP location (El Loco)
     1700                                $info['quicktime']['comments']['gps_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
     1701                                $info['quicktime']['comments']['gps_lang'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
     1702                                $loffset = 0;
     1703                                $info['quicktime']['comments']['gps_location'] = $this->LociString(substr($atom_data, 6), $loffset);
     1704                                $loci_data=substr($atom_data, 6 + $loffset);
     1705                                $info['quicktime']['comments']['gps_role'] = getid3_lib::BigEndian2Int(substr($loci_data, 0, 1));
     1706                                $info['quicktime']['comments']['gps_longitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4));
     1707                                $info['quicktime']['comments']['gps_latitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4));
     1708                                $info['quicktime']['comments']['gps_altitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4));
     1709                                $info['quicktime']['comments']['gps_body'] = $this->LociString(substr($loci_data, 13), $loffset);
     1710                                $info['quicktime']['comments']['gps_notes'] = $this->LociString(substr($loci_data, 13 + $loffset), $loffset);
     1711                                break;
     1712
    14181713                        default:
    1419                                 $info['warning'][] = 'Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;
     1714                                $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset);
    14201715                                $atom_structure['data'] = $atom_data;
    14211716                                break;
    14221717                }
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    14401735                                // Furthermore, for historical reasons the list of atoms is optionally
    14411736                                // terminated by a 32-bit integer set to 0. If you are writing a program
    14421737                                // to read user data atoms, you should allow for the terminating 0.
     1738                                if (strlen($atom_data) > 12) {
     1739                                        $subatomoffset += 4;
     1740                                        continue;
     1741                                }
    14431742                                return $atom_structure;
    14441743                        }
    14451744
    if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ 
    17532052                static $QuicktimeIODSaudioProfileNameLookup = array();
    17542053                if (empty($QuicktimeIODSaudioProfileNameLookup)) {
    17552054                        $QuicktimeIODSaudioProfileNameLookup = array(
    1756                             0x00 => 'ISO Reserved (0x00)',
    1757                             0x01 => 'Main Audio Profile @ Level 1',
    1758                             0x02 => 'Main Audio Profile @ Level 2',
    1759                             0x03 => 'Main Audio Profile @ Level 3',
    1760                             0x04 => 'Main Audio Profile @ Level 4',
    1761                             0x05 => 'Scalable Audio Profile @ Level 1',
    1762                             0x06 => 'Scalable Audio Profile @ Level 2',
    1763                             0x07 => 'Scalable Audio Profile @ Level 3',
    1764                             0x08 => 'Scalable Audio Profile @ Level 4',
    1765                             0x09 => 'Speech Audio Profile @ Level 1',
    1766                             0x0A => 'Speech Audio Profile @ Level 2',
    1767                             0x0B => 'Synthetic Audio Profile @ Level 1',
    1768                             0x0C => 'Synthetic Audio Profile @ Level 2',
    1769                             0x0D => 'Synthetic Audio Profile @ Level 3',
    1770                             0x0E => 'High Quality Audio Profile @ Level 1',
    1771                             0x0F => 'High Quality Audio Profile @ Level 2',
    1772                             0x10 => 'High Quality Audio Profile @ Level 3',
    1773                             0x11 => 'High Quality Audio Profile @ Level 4',
    1774                             0x12 => 'High Quality Audio Profile @ Level 5',
    1775                             0x13 => 'High Quality Audio Profile @ Level 6',
    1776                             0x14 => 'High Quality Audio Profile @ Level 7',
    1777                             0x15 => 'High Quality Audio Profile @ Level 8',
    1778                             0x16 => 'Low Delay Audio Profile @ Level 1',
    1779                             0x17 => 'Low Delay Audio Profile @ Level 2',
    1780                             0x18 => 'Low Delay Audio Profile @ Level 3',
    1781                             0x19 => 'Low Delay Audio Profile @ Level 4',
    1782                             0x1A => 'Low Delay Audio Profile @ Level 5',
    1783                             0x1B => 'Low Delay Audio Profile @ Level 6',
    1784                             0x1C => 'Low Delay Audio Profile @ Level 7',
    1785                             0x1D => 'Low Delay Audio Profile @ Level 8',
    1786                             0x1E => 'Natural Audio Profile @ Level 1',
    1787                             0x1F => 'Natural Audio Profile @ Level 2',
    1788                             0x20 => 'Natural Audio Profile @ Level 3',
    1789                             0x21 => 'Natural Audio Profile @ Level 4',
    1790                             0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
    1791                             0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
    1792                             0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
    1793                             0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
    1794                             0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
    1795                             0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
    1796                             0x28 => 'AAC Profile @ Level 1',
    1797                             0x29 => 'AAC Profile @ Level 2',
    1798                             0x2A => 'AAC Profile @ Level 4',
    1799                             0x2B => 'AAC Profile @ Level 5',
    1800                             0x2C => 'High Efficiency AAC Profile @ Level 2',
    1801                             0x2D => 'High Efficiency AAC Profile @ Level 3',
    1802                             0x2E => 'High Efficiency AAC Profile @ Level 4',
    1803                             0x2F => 'High Efficiency AAC Profile @ Level 5',
    1804                             0xFE => 'Not part of MPEG-4 audio profiles',
    1805                             0xFF => 'No audio capability required',
     2055                                0x00 => 'ISO Reserved (0x00)',
     2056                                0x01 => 'Main Audio Profile @ Level 1',
     2057                                0x02 => 'Main Audio Profile @ Level 2',
     2058                                0x03 => 'Main Audio Profile @ Level 3',
     2059                                0x04 => 'Main Audio Profile @ Level 4',
     2060                                0x05 => 'Scalable Audio Profile @ Level 1',
     2061                                0x06 => 'Scalable Audio Profile @ Level 2',
     2062                                0x07 => 'Scalable Audio Profile @ Level 3',
     2063                                0x08 => 'Scalable Audio Profile @ Level 4',
     2064                                0x09 => 'Speech Audio Profile @ Level 1',
     2065                                0x0A => 'Speech Audio Profile @ Level 2',
     2066                                0x0B => 'Synthetic Audio Profile @ Level 1',
     2067                                0x0C => 'Synthetic Audio Profile @ Level 2',
     2068                                0x0D => 'Synthetic Audio Profile @ Level 3',
     2069                                0x0E => 'High Quality Audio Profile @ Level 1',
     2070                                0x0F => 'High Quality Audio Profile @ Level 2',
     2071                                0x10 => 'High Quality Audio Profile @ Level 3',
     2072                                0x11 => 'High Quality Audio Profile @ Level 4',
     2073                                0x12 => 'High Quality Audio Profile @ Level 5',
     2074                                0x13 => 'High Quality Audio Profile @ Level 6',
     2075                                0x14 => 'High Quality Audio Profile @ Level 7',
     2076                                0x15 => 'High Quality Audio Profile @ Level 8',
     2077                                0x16 => 'Low Delay Audio Profile @ Level 1',
     2078                                0x17 => 'Low Delay Audio Profile @ Level 2',
     2079                                0x18 => 'Low Delay Audio Profile @ Level 3',
     2080                                0x19 => 'Low Delay Audio Profile @ Level 4',
     2081                                0x1A => 'Low Delay Audio Profile @ Level 5',
     2082                                0x1B => 'Low Delay Audio Profile @ Level 6',
     2083                                0x1C => 'Low Delay Audio Profile @ Level 7',
     2084                                0x1D => 'Low Delay Audio Profile @ Level 8',
     2085                                0x1E => 'Natural Audio Profile @ Level 1',
     2086                                0x1F => 'Natural Audio Profile @ Level 2',
     2087                                0x20 => 'Natural Audio Profile @ Level 3',
     2088                                0x21 => 'Natural Audio Profile @ Level 4',
     2089                                0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
     2090                                0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
     2091                                0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
     2092                                0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
     2093                                0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
     2094                                0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
     2095                                0x28 => 'AAC Profile @ Level 1',
     2096                                0x29 => 'AAC Profile @ Level 2',
     2097                                0x2A => 'AAC Profile @ Level 4',
     2098                                0x2B => 'AAC Profile @ Level 5',
     2099                                0x2C => 'High Efficiency AAC Profile @ Level 2',
     2100                                0x2D => 'High Efficiency AAC Profile @ Level 3',
     2101                                0x2E => 'High Efficiency AAC Profile @ Level 4',
     2102                                0x2F => 'High Efficiency AAC Profile @ Level 5',
     2103                                0xFE => 'Not part of MPEG-4 audio profiles',
     2104                                0xFF => 'No audio capability required',
    18062105                        );
    18072106                }
    18082107                return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
    echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 
    21112410        public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
    21122411                static $handyatomtranslatorarray = array();
    21132412                if (empty($handyatomtranslatorarray)) {
     2413                        // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
     2414                        // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
     2415                        // http://atomicparsley.sourceforge.net/mpeg-4files.html
     2416                        // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
     2417                        $handyatomtranslatorarray["\xA9".'alb'] = 'album';               // iTunes 4.0
     2418                        $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
     2419                        $handyatomtranslatorarray["\xA9".'art'] = 'artist';              // iTunes 4.0
     2420                        $handyatomtranslatorarray["\xA9".'aut'] = 'author';
     2421                        $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';             // iTunes 4.0
     2422                        $handyatomtranslatorarray["\xA9".'com'] = 'comment';
    21142423                        $handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
    2115                         $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';    // iTunes 4.0
     2424                        $handyatomtranslatorarray["\xA9".'day'] = 'creation_date';       // iTunes 4.0
    21162425                        $handyatomtranslatorarray["\xA9".'dir'] = 'director';
    21172426                        $handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
    21182427                        $handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
    echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 
    21232432                        $handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
    21242433                        $handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
    21252434                        $handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
     2435                        $handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by';
    21262436                        $handyatomtranslatorarray["\xA9".'fmt'] = 'format';
     2437                        $handyatomtranslatorarray["\xA9".'gen'] = 'genre';               // iTunes 4.0
     2438                        $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';            // iTunes 4.2
     2439                        $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
    21272440                        $handyatomtranslatorarray["\xA9".'inf'] = 'information';
     2441                        $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';              // iTunes 5.0
     2442                        $handyatomtranslatorarray["\xA9".'mak'] = 'make';
     2443                        $handyatomtranslatorarray["\xA9".'mod'] = 'model';
     2444                        $handyatomtranslatorarray["\xA9".'nam'] = 'title';               // iTunes 4.0
     2445                        $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
    21282446                        $handyatomtranslatorarray["\xA9".'prd'] = 'producer';
     2447                        $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
    21292448                        $handyatomtranslatorarray["\xA9".'prf'] = 'performers';
    21302449                        $handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
    21312450                        $handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
    2132                         $handyatomtranslatorarray["\xA9".'wrt'] = 'writer';
    2133 
    2134                         // http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
    2135                         $handyatomtranslatorarray["\xA9".'nam'] = 'title';           // iTunes 4.0
    2136                         $handyatomtranslatorarray["\xA9".'cmt'] = 'comment';         // iTunes 4.0
    2137                         $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
    2138                         $handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
    2139                         $handyatomtranslatorarray["\xA9".'mak'] = 'make';
    2140                         $handyatomtranslatorarray["\xA9".'mod'] = 'model';
    2141                         $handyatomtranslatorarray["\xA9".'PRD'] = 'product';
    21422451                        $handyatomtranslatorarray["\xA9".'swr'] = 'software';
    2143                         $handyatomtranslatorarray["\xA9".'aut'] = 'author';
    2144                         $handyatomtranslatorarray["\xA9".'ART'] = 'artist';
     2452                        $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
    21452453                        $handyatomtranslatorarray["\xA9".'trk'] = 'track';
    2146                         $handyatomtranslatorarray["\xA9".'alb'] = 'album';           // iTunes 4.0
    2147                         $handyatomtranslatorarray["\xA9".'com'] = 'comment';
    2148                         $handyatomtranslatorarray["\xA9".'gen'] = 'genre';           // iTunes 4.0
    2149                         $handyatomtranslatorarray["\xA9".'ope'] = 'composer';
    21502454                        $handyatomtranslatorarray["\xA9".'url'] = 'url';
    2151                         $handyatomtranslatorarray["\xA9".'enc'] = 'encoder';
    2152 
    2153                         // http://atomicparsley.sourceforge.net/mpeg-4files.html
    2154                         $handyatomtranslatorarray["\xA9".'art'] = 'artist';           // iTunes 4.0
     2455                        $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
     2456                        $handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
    21552457                        $handyatomtranslatorarray['aART'] = 'album_artist';
    2156                         $handyatomtranslatorarray['trkn'] = 'track_number';     // iTunes 4.0
    2157                         $handyatomtranslatorarray['disk'] = 'disc_number';      // iTunes 4.0
    2158                         $handyatomtranslatorarray['gnre'] = 'genre';            // iTunes 4.0
    2159                         $handyatomtranslatorarray["\xA9".'too'] = 'encoder';          // iTunes 4.0
    2160                         $handyatomtranslatorarray['tmpo'] = 'bpm';              // iTunes 4.0
    2161                         $handyatomtranslatorarray['cprt'] = 'copyright';        // iTunes 4.0?
    2162                         $handyatomtranslatorarray['cpil'] = 'compilation';      // iTunes 4.0
    2163                         $handyatomtranslatorarray['covr'] = 'picture';          // iTunes 4.0
    2164                         $handyatomtranslatorarray['rtng'] = 'rating';           // iTunes 4.0
    2165                         $handyatomtranslatorarray["\xA9".'grp'] = 'grouping';         // iTunes 4.2
    2166                         $handyatomtranslatorarray['stik'] = 'stik';             // iTunes 4.9
    2167                         $handyatomtranslatorarray['pcst'] = 'podcast';          // iTunes 4.9
    2168                         $handyatomtranslatorarray['catg'] = 'category';         // iTunes 4.9
    2169                         $handyatomtranslatorarray['keyw'] = 'keyword';          // iTunes 4.9
    2170                         $handyatomtranslatorarray['purl'] = 'podcast_url';      // iTunes 4.9
    2171                         $handyatomtranslatorarray['egid'] = 'episode_guid';     // iTunes 4.9
    2172                         $handyatomtranslatorarray['desc'] = 'description';      // iTunes 5.0
    2173                         $handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';           // iTunes 5.0
    2174                         $handyatomtranslatorarray['tvnn'] = 'tv_network_name';  // iTunes 6.0
    2175                         $handyatomtranslatorarray['tvsh'] = 'tv_show_name';     // iTunes 6.0
    2176                         $handyatomtranslatorarray['tvsn'] = 'tv_season';        // iTunes 6.0
    2177                         $handyatomtranslatorarray['tves'] = 'tv_episode';       // iTunes 6.0
    2178                         $handyatomtranslatorarray['purd'] = 'purchase_date';    // iTunes 6.0.2
    2179                         $handyatomtranslatorarray['pgap'] = 'gapless_playback'; // iTunes 7.0
    2180 
    2181                         // http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
    2182 
    2183 
     2458                        $handyatomtranslatorarray['apID'] = 'purchase_account';
     2459                        $handyatomtranslatorarray['catg'] = 'category';            // iTunes 4.9
     2460                        $handyatomtranslatorarray['covr'] = 'picture';             // iTunes 4.0
     2461                        $handyatomtranslatorarray['cpil'] = 'compilation';         // iTunes 4.0
     2462                        $handyatomtranslatorarray['cprt'] = 'copyright';           // iTunes 4.0?
     2463                        $handyatomtranslatorarray['desc'] = 'description';         // iTunes 5.0
     2464                        $handyatomtranslatorarray['disk'] = 'disc_number';         // iTunes 4.0
     2465                        $handyatomtranslatorarray['egid'] = 'episode_guid';        // iTunes 4.9
     2466                        $handyatomtranslatorarray['gnre'] = 'genre';               // iTunes 4.0
     2467                        $handyatomtranslatorarray['hdvd'] = 'hd_video';            // iTunes 4.0
     2468                        $handyatomtranslatorarray['ldes'] = 'description_long';    //
     2469                        $handyatomtranslatorarray['keyw'] = 'keyword';             // iTunes 4.9
     2470                        $handyatomtranslatorarray['pcst'] = 'podcast';             // iTunes 4.9
     2471                        $handyatomtranslatorarray['pgap'] = 'gapless_playback';    // iTunes 7.0
     2472                        $handyatomtranslatorarray['purd'] = 'purchase_date';       // iTunes 6.0.2
     2473                        $handyatomtranslatorarray['purl'] = 'podcast_url';         // iTunes 4.9
     2474                        $handyatomtranslatorarray['rtng'] = 'rating';              // iTunes 4.0
     2475                        $handyatomtranslatorarray['soaa'] = 'sort_album_artist';   //
     2476                        $handyatomtranslatorarray['soal'] = 'sort_album';          //
     2477                        $handyatomtranslatorarray['soar'] = 'sort_artist';         //
     2478                        $handyatomtranslatorarray['soco'] = 'sort_composer';       //
     2479                        $handyatomtranslatorarray['sonm'] = 'sort_title';          //
     2480                        $handyatomtranslatorarray['sosn'] = 'sort_show';           //
     2481                        $handyatomtranslatorarray['stik'] = 'stik';                // iTunes 4.9
     2482                        $handyatomtranslatorarray['tmpo'] = 'bpm';                 // iTunes 4.0
     2483                        $handyatomtranslatorarray['trkn'] = 'track_number';        // iTunes 4.0
     2484                        $handyatomtranslatorarray['tven'] = 'tv_episode_id';       //
     2485                        $handyatomtranslatorarray['tves'] = 'tv_episode';          // iTunes 6.0
     2486                        $handyatomtranslatorarray['tvnn'] = 'tv_network_name';     // iTunes 6.0
     2487                        $handyatomtranslatorarray['tvsh'] = 'tv_show_name';        // iTunes 6.0
     2488                        $handyatomtranslatorarray['tvsn'] = 'tv_season';           // iTunes 6.0
    21842489
    21852490                        // boxnames:
    21862491                        /*
    echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 
    22252530                                        $data = array('data'=>$data, 'image_mime'=>$image_mime);
    22262531                                }
    22272532                        }
    2228                         $info['quicktime']['comments'][$comment_key][] = $data;
     2533                        $gooddata = array($data);
     2534                        if ($comment_key == 'genre') {
     2535                                // some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
     2536                                $gooddata = explode(';', $data);
     2537                        }
     2538                        foreach ($gooddata as $data) {
     2539                                $info['quicktime']['comments'][$comment_key][] = $data;
     2540                        }
    22292541                }
    22302542                return true;
    22312543        }
    22322544
     2545    public function LociString($lstring, &$count) {
     2546            // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
     2547            // Also need to return the number of bytes the string occupied so additional fields can be extracted
     2548            $len = strlen($lstring);
     2549            if ($len == 0) {
     2550                $count = 0;
     2551                return '';
     2552            }
     2553            if ($lstring[0] == "\x00") {
     2554                $count = 1;
     2555                return '';
     2556            }
     2557            //check for BOM
     2558            if ($len > 2 && (($lstring[0] == "\xFE" && $lstring[1] == "\xFF") || ($lstring[0] == "\xFF" && $lstring[1] == "\xFE"))) {
     2559                //UTF-16
     2560                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
     2561                     $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
     2562                    return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
     2563                } else {
     2564                    return '';
     2565                }
     2566            } else {
     2567                //UTF-8
     2568                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
     2569                    $count = strlen($lmatches[1]) + 1; //account for trailing \x00
     2570                    return $lmatches[1];
     2571                }else {
     2572                    return '';
     2573                }
     2574
     2575            }
     2576        }
     2577
    22332578        public function NoNullString($nullterminatedstring) {
    22342579                // remove the single null terminator on null terminated strings
    22352580                if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
    echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br 
    22432588                return substr($pascalstring, 1);
    22442589        }
    22452590
     2591
     2592        /*
     2593        // helper functions for m4b audiobook chapters
     2594        // code by Steffen Hartmann 2015-Nov-08
     2595        */
     2596        public function search_tag_by_key($info, $tag, $history, &$result) {
     2597                foreach ($info as $key => $value) {
     2598                        $key_history = $history.'/'.$key;
     2599                        if ($key === $tag) {
     2600                                $result[] = array($key_history, $info);
     2601                        } else {
     2602                                if (is_array($value)) {
     2603                                        $this->search_tag_by_key($value, $tag, $key_history, $result);
     2604                                }
     2605                        }
     2606                }
     2607        }
     2608
     2609        public function search_tag_by_pair($info, $k, $v, $history, &$result) {
     2610                foreach ($info as $key => $value) {
     2611                        $key_history = $history.'/'.$key;
     2612                        if (($key === $k) && ($value === $v)) {
     2613                                $result[] = array($key_history, $info);
     2614                        } else {
     2615                                if (is_array($value)) {
     2616                                        $this->search_tag_by_pair($value, $k, $v, $key_history, $result);
     2617                                }
     2618                        }
     2619                }
     2620        }
     2621
     2622        public function quicktime_time_to_sample_table($info) {
     2623                $res = array();
     2624                $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
     2625                foreach ($res as $value) {
     2626                        $stbl_res = array();
     2627                        $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
     2628                        if (count($stbl_res) > 0) {
     2629                                $stts_res = array();
     2630                                $this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res);
     2631                                if (count($stts_res) > 0) {
     2632                                        return $stts_res[0][1]['time_to_sample_table'];
     2633                                }
     2634                        }
     2635                }
     2636                return array();
     2637        }
     2638
     2639        function quicktime_bookmark_time_scale($info) {
     2640                $time_scale = '';
     2641                $ts_prefix_len = 0;
     2642                $res = array();
     2643                $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
     2644                foreach ($res as $value) {
     2645                        $stbl_res = array();
     2646                        $this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
     2647                        if (count($stbl_res) > 0) {
     2648                                $ts_res = array();
     2649                                $this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
     2650                                foreach ($ts_res as $value) {
     2651                                        $prefix = substr($value[0], 0, -12);
     2652                                        if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
     2653                                                $time_scale = $value[1]['time_scale'];
     2654                                                $ts_prefix_len = strlen($prefix);
     2655                                        }
     2656                                }
     2657                        }
     2658                }
     2659                return $time_scale;
     2660        }
     2661        /*
     2662        // END helper functions for m4b audiobook chapters
     2663        */
     2664
     2665
    22462666}
  • src/wp-includes/ID3/module.audio-video.riff.php

    diff --git a/src/wp-includes/ID3/module.audio-video.riff.php b/src/wp-includes/ID3/module.audio-video.riff.php
    index e8ba944..53f9350 100644
    a b class getid3_riff extends getid3_handler { 
    190190                                        $thisfile_riff_audio[$streamindex] = self::parseWAVEFORMATex($thisfile_riff_WAVE['fmt '][0]['data']);
    191191                                        $thisfile_audio['wformattag'] = $thisfile_riff_audio[$streamindex]['raw']['wFormatTag'];
    192192                                        if (!isset($thisfile_riff_audio[$streamindex]['bitrate']) || ($thisfile_riff_audio[$streamindex]['bitrate'] == 0)) {
    193                                                 $info['error'][] = 'Corrupt RIFF file: bitrate_audio == zero';
     193                                                $this->error('Corrupt RIFF file: bitrate_audio == zero');
    194194                                                return false;
    195195                                        }
    196196                                        $thisfile_riff_raw['fmt '] = $thisfile_riff_audio[$streamindex]['raw'];
    class getid3_riff extends getid3_handler { 
    199199
    200200                                        $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
    201201                                        if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
    202                                                 $info['warning'][] = 'Audio codec = '.$thisfile_audio['codec'];
     202                                                $this->warning('Audio codec = '.$thisfile_audio['codec']);
    203203                                        }
    204204                                        $thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
    205205
    class getid3_riff extends getid3_handler { 
    302302                                                        list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
    303303                                                        $thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
    304304                                                } else {
    305                                                         $info['warning'][] = 'RIFF.WAVE.BEXT.origin_time is invalid';
     305                                                        $this->warning('RIFF.WAVE.BEXT.origin_time is invalid');
    306306                                                }
    307307                                        } else {
    308                                                 $info['warning'][] = 'RIFF.WAVE.BEXT.origin_date is invalid';
     308                                                $this->warning('RIFF.WAVE.BEXT.origin_date is invalid');
    309309                                        }
    310310                                        $thisfile_riff['comments']['author'][] = $thisfile_riff_WAVE_bext_0['author'];
    311311                                        $thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_bext_0['title'];
    class getid3_riff extends getid3_handler { 
    385385                                                $SNDM_thisTagOffset += $SNDM_thisTagDataSize;
    386386
    387387                                                if ($SNDM_thisTagSize != (4 + 4 + 2 + 2 + $SNDM_thisTagDataSize)) {
    388                                                         $info['warning'][] = 'RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
     388                                                        $this->warning('RIFF.WAVE.SNDM.data contains tag not expected length (expected: '.$SNDM_thisTagSize.', found: '.(4 + 4 + 2 + 2 + $SNDM_thisTagDataSize).') at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
    389389                                                        break;
    390390                                                } elseif ($SNDM_thisTagSize <= 0) {
    391                                                         $info['warning'][] = 'RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
     391                                                        $this->warning('RIFF.WAVE.SNDM.data contains zero-size tag at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
    392392                                                        break;
    393393                                                }
    394394                                                $SNDM_startoffset += $SNDM_thisTagSize;
    class getid3_riff extends getid3_handler { 
    397397                                                if ($parsedkey = self::waveSNDMtagLookup($SNDM_thisTagKey)) {
    398398                                                        $thisfile_riff_WAVE_SNDM_0['parsed'][$parsedkey] = $SNDM_thisTagDataText;
    399399                                                } else {
    400                                                         $info['warning'][] = 'RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')';
     400                                                        $this->warning('RIFF.WAVE.SNDM contains unknown tag "'.$SNDM_thisTagKey.'" at offset '.$SNDM_startoffset.' (file offset '.($thisfile_riff_WAVE_SNDM_0['offset'] + $SNDM_startoffset).')');
    401401                                                }
    402402                                        }
    403403
    class getid3_riff extends getid3_handler { 
    428428                                                }
    429429                                                if (isset($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO']) && !empty($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) && !empty($thisfile_riff_WAVE['iXML'][0]['timecode_rate'])) {
    430430                                                        $samples_since_midnight = floatval(ltrim($parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_HI'].$parsedXML['SPEED']['TIMESTAMP_SAMPLES_SINCE_MIDNIGHT_LO'], '0'));
    431                                                         $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE'];
     431                                                        $timestamp_sample_rate = (is_array($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) ? max($parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']) : $parsedXML['SPEED']['TIMESTAMP_SAMPLE_RATE']); // XML could possibly contain more than one TIMESTAMP_SAMPLE_RATE tag, returning as array instead of integer [why? does it make sense? perhaps doesn't matter but getID3 needs to deal with it] - see https://github.com/JamesHeinrich/getID3/issues/105
     432                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] = $samples_since_midnight / $timestamp_sample_rate;
    432433                                                        $h = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds']       / 3600);
    433434                                                        $m = floor(($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600))      / 60);
    434435                                                        $s = floor( $thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60));
    435436                                                        $f =       ($thisfile_riff_WAVE['iXML'][0]['timecode_seconds'] - ($h * 3600) - ($m * 60) - $s) * $thisfile_riff_WAVE['iXML'][0]['timecode_rate'];
    436437                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_string']       = sprintf('%02d:%02d:%02d:%05.2f', $h, $m, $s,       $f);
    437438                                                        $thisfile_riff_WAVE['iXML'][0]['timecode_string_round'] = sprintf('%02d:%02d:%02d:%02d',   $h, $m, $s, round($f));
     439                                                        unset($samples_since_midnight, $timestamp_sample_rate, $h, $m, $s, $f);
    438440                                                }
    439441                                                unset($parsedXML);
    440442                                        }
    class getid3_riff extends getid3_handler { 
    570572                                                                // byte, in which case - skip warning
    571573                                                        } else {
    572574                                                                // Short by more than one byte, throw warning
    573                                                                 $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
     575                                                                $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
    574576                                                                $info['avdataend'] = $info['filesize'];
    575577                                                        }
    576578                                                        break;
    class getid3_riff extends getid3_handler { 
    579581                                                        if ((($info['avdataend'] - $info['filesize']) == 1) && (($thisfile_riff[$RIFFsubtype]['data'][0]['size'] % 2) == 0) && ((($info['filesize'] - $info['avdataoffset']) % 2) == 1)) {
    580582                                                                // output file appears to be incorrectly *not* padded to nearest WORD boundary
    581583                                                                // Output less severe warning
    582                                                                 $info['warning'][] = 'File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
     584                                                                $this->warning('File should probably be padded to nearest WORD boundary, but it is not (expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' therefore short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
    583585                                                                $info['avdataend'] = $info['filesize'];
    584586                                                        } else {
    585587                                                                // Short by more than one byte, throw warning
    586                                                                 $info['warning'][] = 'Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)';
     588                                                                $this->warning('Probably truncated file - expecting '.$thisfile_riff[$RIFFsubtype]['data'][0]['size'].' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($thisfile_riff[$RIFFsubtype]['data'][0]['size'] - ($info['filesize'] - $info['avdataoffset'])).' bytes)');
    587589                                                                $info['avdataend'] = $info['filesize'];
    588590                                                        }
    589591                                                        break;
    class getid3_riff extends getid3_handler { 
    592594                                if (!empty($info['mpeg']['audio']['LAME']['audio_bytes'])) {
    593595                                        if ((($info['avdataend'] - $info['avdataoffset']) - $info['mpeg']['audio']['LAME']['audio_bytes']) == 1) {
    594596                                                $info['avdataend']--;
    595                                                 $info['warning'][] = 'Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored';
     597                                                $this->warning('Extra null byte at end of MP3 data assumed to be RIFF padding and therefore ignored');
    596598                                        }
    597599                                }
    598600                                if (isset($thisfile_audio_dataformat) && ($thisfile_audio_dataformat == 'ac3')) {
    class getid3_riff extends getid3_handler { 
    619621                                                $info['avdataend'] = $thisfile_riff['AVI ']['movi']['offset'] + $thisfile_riff['AVI ']['movi']['size'];
    620622                                        }
    621623                                        if ($info['avdataend'] > $info['filesize']) {
    622                                                 $info['warning'][] = 'Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)';
     624                                                $this->warning('Probably truncated file - expecting '.($info['avdataend'] - $info['avdataoffset']).' bytes of data, only found '.($info['filesize'] - $info['avdataoffset']).' (short by '.($info['avdataend'] - $info['filesize']).' bytes)');
    623625                                                $info['avdataend'] = $info['filesize'];
    624626                                        }
    625627                                }
    class getid3_riff extends getid3_handler { 
    660662
    661663                                        $thisfile_riff_raw_avih['dwMicroSecPerFrame']    = $this->EitherEndian2Int(substr($avihData,  0, 4)); // frame display rate (or 0L)
    662664                                        if ($thisfile_riff_raw_avih['dwMicroSecPerFrame'] == 0) {
    663                                                 $info['error'][] = 'Corrupt RIFF file: avih.dwMicroSecPerFrame == zero';
     665                                                $this->error('Corrupt RIFF file: avih.dwMicroSecPerFrame == zero');
    664666                                                return false;
    665667                                        }
    666668
    class getid3_riff extends getid3_handler { 
    858860                                                                                        break;
    859861
    860862                                                                                default:
    861                                                                                         $info['warning'][] = 'Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"';
     863                                                                                        $this->warning('Unhandled fccType for stream ('.$i.'): "'.$strhfccType.'"');
    862864                                                                                        break;
    863865
    864866                                                                        }
    class getid3_riff extends getid3_handler { 
    963965                                                        // structures rounded to 2-byte boundary, but dumb encoders
    964966                                                        // forget to pad end of file to make this actually work
    965967                                                } else {
    966                                                         $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
     968                                                        $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['SSND'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
    967969                                                }
    968970                                                $info['avdataend'] = $info['filesize'];
    969971                                        }
    class getid3_riff extends getid3_handler { 
    10201022                                        }
    10211023                                        $thisfile_audio['sample_rate']     = $thisfile_riff_audio['sample_rate'];
    10221024                                        if ($thisfile_audio['sample_rate'] == 0) {
    1023                                                 $info['error'][] = 'Corrupted AIFF file: sample_rate == zero';
     1025                                                $this->error('Corrupted AIFF file: sample_rate == zero');
    10241026                                                return false;
    10251027                                        }
    10261028                                        $info['playtime_seconds'] = $thisfile_riff_audio['total_samples'] / $thisfile_audio['sample_rate'];
    class getid3_riff extends getid3_handler { 
    10801082                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
    10811083                                        $info['avdataend']    = $info['avdataoffset'] + $thisfile_riff[$RIFFsubtype]['BODY'][0]['size'];
    10821084                                        if ($info['avdataend'] > $info['filesize']) {
    1083                                                 $info['warning'][] = 'Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found';
     1085                                                $this->warning('Probable truncated AIFF file: expecting '.$thisfile_riff[$RIFFsubtype]['BODY'][0]['size'].' bytes of audio data, only '.($info['filesize'] - $info['avdataoffset']).' bytes found');
    10841086                                        }
    10851087                                }
    10861088
    class getid3_riff extends getid3_handler { 
    11121114                                                        break;
    11131115
    11141116                                                default:
    1115                                                         $info['warning'][] = 'Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"';
     1117                                                        $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
    11161118                                                        break;
    11171119                                        }
    11181120                                }
    class getid3_riff extends getid3_handler { 
    11301132                                                        break;
    11311133
    11321134                                                default:
    1133                                                         $info['warning'][] = 'Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"';
     1135                                                        $this->warning('Unexpected value in 8SVX.CHAN chunk - expecting 2 or 4 or 6, found "'.$ChannelsIndex.'"');
    11341136                                                        break;
    11351137                                        }
    11361138
    class getid3_riff extends getid3_handler { 
    11701172                                }
    11711173                                break;
    11721174
     1175                        case 'WEBP':
     1176                                // https://developers.google.com/speed/webp/docs/riff_container
     1177                                // https://tools.ietf.org/html/rfc6386
     1178                                // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt
     1179                                $info['fileformat'] = 'webp';
     1180                                $info['mime_type']  = 'image/webp';
     1181
     1182                                if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) {
     1183                                        $old_offset = $this->ftell();
     1184                                        $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size
     1185                                        $WEBP_VP8_header = $this->fread(10);
     1186                                        $this->fseek($old_offset);
     1187                                        if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") {
     1188                                                $thisfile_riff['WEBP']['VP8 '][0]['keyframe']   = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000);
     1189                                                $thisfile_riff['WEBP']['VP8 '][0]['version']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20;
     1190                                                $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000);
     1191                                                $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >>  0;
     1192
     1193                                                $thisfile_riff['WEBP']['VP8 '][0]['scale_x']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14;
     1194                                                $thisfile_riff['WEBP']['VP8 '][0]['width']      =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF);
     1195                                                $thisfile_riff['WEBP']['VP8 '][0]['scale_y']    =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14;
     1196                                                $thisfile_riff['WEBP']['VP8 '][0]['height']     =  (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF);
     1197
     1198                                                $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width'];
     1199                                                $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height'];
     1200                                        } else {
     1201                                                $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"');
     1202                                        }
     1203
     1204                                }
     1205                                if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) {
     1206                                        $old_offset = $this->ftell();
     1207                                        $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size
     1208                                        $WEBP_VP8L_header = $this->fread(10);
     1209                                        $this->fseek($old_offset);
     1210                                        if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") {
     1211                                                $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4));
     1212                                                $thisfile_riff['WEBP']['VP8L'][0]['width']         =        bindec(substr($width_height_flags, 18, 14)) + 1;
     1213                                                $thisfile_riff['WEBP']['VP8L'][0]['height']        =        bindec(substr($width_height_flags,  4, 14)) + 1;
     1214                                                $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags,  3,  1));
     1215                                                $thisfile_riff['WEBP']['VP8L'][0]['version']       =        bindec(substr($width_height_flags,  0,  3));
     1216
     1217                                                $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width'];
     1218                                                $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height'];
     1219                                        } else {
     1220                                                $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"');
     1221                                        }
     1222
     1223                                }
     1224                                break;
    11731225
    11741226                        default:
    1175                                 $info['error'][] = 'Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA), found "'.$RIFFsubtype.'" instead';
     1227                                $this->error('Unknown RIFF type: expecting one of (WAVE|RMP3|AVI |CDDA|AIFF|AIFC|8SVX|CDXA|WEBP), found "'.$RIFFsubtype.'" instead');
    11761228                                //unset($info['fileformat']);
    11771229                }
    11781230
    class getid3_riff extends getid3_handler { 
    11851237                                foreach ($ID3v2_keys_bad as $ID3v2_key_bad) {
    11861238                                        if (isset($thisfile_riff[$RIFFsubtype][$ID3v2_key_bad]) && !array_key_exists($ID3v2_key_good, $thisfile_riff[$RIFFsubtype])) {
    11871239                                                $thisfile_riff[$RIFFsubtype][$ID3v2_key_good] = $thisfile_riff[$RIFFsubtype][$ID3v2_key_bad];
    1188                                                 $info['warning'][] = 'mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"';
     1240                                                $this->warning('mapping "'.$ID3v2_key_bad.'" chunk to "'.$ID3v2_key_good.'"');
    11891241                                        }
    11901242                                }
    11911243
    class getid3_riff extends getid3_handler { 
    15091561                                                                                        $info['ac3']     = $getid3_temp->info['ac3'];
    15101562                                                                                        if (!empty($getid3_temp->info['warning'])) {
    15111563                                                                                                foreach ($getid3_temp->info['warning'] as $key => $value) {
    1512                                                                                                         $info['warning'][] = $value;
     1564                                                                                                        $this->warning($value);
    15131565                                                                                                }
    15141566                                                                                        }
    15151567                                                                                }
    class getid3_riff extends getid3_handler { 
    25832635                return getid3_lib::BigEndian2Int($byteword, false, $signed);
    25842636        }
    25852637
    2586 }
    2587  No newline at end of file
     2638}
  • src/wp-includes/ID3/module.audio.ac3.php

    diff --git a/src/wp-includes/ID3/module.audio.ac3.php b/src/wp-includes/ID3/module.audio.ac3.php
    index 2dc52f4..27c328d 100644
    a b class getid3_ac3 extends getid3_handler 
    2020    private $AC3header = array();
    2121    private $BSIoffset = 0;
    2222
    23     const syncword = "\x0B\x77";
     23    const syncword = 0x0B77;
    2424
    2525        public function Analyze() {
    2626                $info = &$this->getid3->info;
    class getid3_ac3 extends getid3_handler 
    5555                // } /* end of syncinfo */
    5656
    5757                $this->fseek($info['avdataoffset']);
    58                 $this->AC3header['syncinfo'] = $this->fread(5);
     58                $tempAC3header = $this->fread(100); // should be enough to cover all data, there are some variable-length fields...?
     59                $this->AC3header['syncinfo']  =     getid3_lib::BigEndian2Int(substr($tempAC3header, 0, 2));
     60                $this->AC3header['bsi']       =     getid3_lib::BigEndian2Bin(substr($tempAC3header, 2));
     61                $thisfile_ac3_raw_bsi['bsid'] = (getid3_lib::LittleEndian2Int(substr($tempAC3header, 5, 1)) & 0xF8) >> 3; // AC3 and E-AC3 put the "bsid" version identifier in the same place, but unfortnately the 4 bytes between the syncword and the version identifier are interpreted differently, so grab it here so the following code structure can make sense
     62                unset($tempAC3header);
    5963
    60                 if (strpos($this->AC3header['syncinfo'], self::syncword) === 0) {
    61                         $thisfile_ac3_raw['synchinfo']['synchword'] = self::syncword;
    62                         $offset = 2;
    63                 } else {
     64                if ($this->AC3header['syncinfo'] !== self::syncword) {
    6465                        if (!$this->isDependencyFor('matroska')) {
    6566                                unset($info['fileformat'], $info['ac3']);
    66                                 return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($this->AC3header['syncinfo'], 0, 2)).'"');
     67                                return $this->error('Expecting "'.dechex(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.dechex($this->AC3header['syncinfo']).'"');
    6768                        }
    68                         $offset = 0;
    69                         $this->fseek(-2, SEEK_CUR);
    7069                }
    7170
    7271                $info['audio']['dataformat']   = 'ac3';
    7372                $info['audio']['bitrate_mode'] = 'cbr';
    7473                $info['audio']['lossless']     = false;
    7574
    76                 $thisfile_ac3_raw['synchinfo']['crc1']       = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], $offset, 2));
    77                 $ac3_synchinfo_fscod_frmsizecod              = getid3_lib::LittleEndian2Int(substr($this->AC3header['syncinfo'], ($offset + 2), 1));
    78                 $thisfile_ac3_raw['synchinfo']['fscod']      = ($ac3_synchinfo_fscod_frmsizecod & 0xC0) >> 6;
    79                 $thisfile_ac3_raw['synchinfo']['frmsizecod'] = ($ac3_synchinfo_fscod_frmsizecod & 0x3F);
     75                if ($thisfile_ac3_raw_bsi['bsid'] <= 8) {
    8076
    81                 $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw['synchinfo']['fscod']);
    82                 if ($thisfile_ac3_raw['synchinfo']['fscod'] <= 3) {
    83                         $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
    84                 }
     77                        $thisfile_ac3_raw_bsi['crc1']       = getid3_lib::Bin2Dec($this->readHeaderBSI(16));
     78                        $thisfile_ac3_raw_bsi['fscod']      =                     $this->readHeaderBSI(2);   // 5.4.1.3
     79                        $thisfile_ac3_raw_bsi['frmsizecod'] =                     $this->readHeaderBSI(6);   // 5.4.1.4
     80                        if ($thisfile_ac3_raw_bsi['frmsizecod'] > 37) { // binary: 100101 - see Table 5.18 Frame Size Code Table (1 word = 16 bits)
     81                                $this->warning('Unexpected ac3.bsi.frmsizecod value: '.$thisfile_ac3_raw_bsi['frmsizecod'].', bitrate not set correctly');
     82                        }
    8583
    86                 $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw['synchinfo']['frmsizecod'], $thisfile_ac3_raw['synchinfo']['fscod']);
    87                 $thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw['synchinfo']['frmsizecod']);
    88                 $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
     84                        $thisfile_ac3_raw_bsi['bsid']  = $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
     85                        $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
     86                        $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
    8987
    90                 $this->AC3header['bsi'] = getid3_lib::BigEndian2Bin($this->fread(15));
    91                 $ac3_bsi_offset = 0;
     88                        if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
     89                                // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
     90                                $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
     91                                $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
     92                        }
    9293
    93                 $thisfile_ac3_raw_bsi['bsid'] = $this->readHeaderBSI(5);
    94                 if ($thisfile_ac3_raw_bsi['bsid'] > 8) {
    95                         // Decoders which can decode version 8 will thus be able to decode version numbers less than 8.
    96                         // If this standard is extended by the addition of additional elements or features, a value of bsid greater than 8 will be used.
    97                         // Decoders built to this version of the standard will not be able to decode versions with bsid greater than 8.
    98                         $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 8');
    99                     unset($info['ac3']);
    100                         return false;
    101                 }
     94                        if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
     95                                // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
     96                                $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
     97                                $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
     98                        }
    10299
    103                 $thisfile_ac3_raw_bsi['bsmod'] = $this->readHeaderBSI(3);
    104                 $thisfile_ac3_raw_bsi['acmod'] = $this->readHeaderBSI(3);
     100                        if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
     101                                // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
     102                                $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
     103                                $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
     104                        }
    105105
    106                 $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
    107                 $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
    108                 foreach($ac3_coding_mode as $key => $value) {
    109                         $thisfile_ac3[$key] = $value;
    110                 }
    111                 switch ($thisfile_ac3_raw_bsi['acmod']) {
    112                         case 0:
    113                         case 1:
    114                                 $info['audio']['channelmode'] = 'mono';
    115                                 break;
    116                         case 3:
    117                         case 4:
    118                                 $info['audio']['channelmode'] = 'stereo';
    119                                 break;
    120                         default:
    121                                 $info['audio']['channelmode'] = 'surround';
    122                                 break;
    123                 }
    124                 $info['audio']['channels'] = $thisfile_ac3['num_channels'];
     106                        $thisfile_ac3_raw_bsi['flags']['lfeon'] = (bool) $this->readHeaderBSI(1);
    125107
    126                 if ($thisfile_ac3_raw_bsi['acmod'] & 0x01) {
    127                         // If the lsb of acmod is a 1, center channel is in use and cmixlev follows in the bit stream.
    128                         $thisfile_ac3_raw_bsi['cmixlev'] = $this->readHeaderBSI(2);
    129                         $thisfile_ac3['center_mix_level'] = self::centerMixLevelLookup($thisfile_ac3_raw_bsi['cmixlev']);
    130                 }
     108                        // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
     109                        // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
     110                        $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);                 // 5.4.2.8 dialnorm: Dialogue Normalization, 5 Bits
    131111
    132                 if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) {
    133                         // If the msb of acmod is a 1, surround channels are in use and surmixlev follows in the bit stream.
    134                         $thisfile_ac3_raw_bsi['surmixlev'] = $this->readHeaderBSI(2);
    135                         $thisfile_ac3['surround_mix_level'] = self::surroundMixLevelLookup($thisfile_ac3_raw_bsi['surmixlev']);
    136                 }
     112                        $thisfile_ac3_raw_bsi['flags']['compr'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.9 compre: Compression Gain Word Exists, 1 Bit
     113                        if ($thisfile_ac3_raw_bsi['flags']['compr']) {
     114                                $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);                // 5.4.2.10 compr: Compression Gain Word, 8 Bits
     115                                $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
     116                        }
    137117
    138                 if ($thisfile_ac3_raw_bsi['acmod'] == 0x02) {
    139                         // When operating in the two channel mode, this 2-bit code indicates whether or not the program has been encoded in Dolby Surround.
    140                         $thisfile_ac3_raw_bsi['dsurmod'] = $this->readHeaderBSI(2);
    141                         $thisfile_ac3['dolby_surround_mode'] = self::dolbySurroundModeLookup($thisfile_ac3_raw_bsi['dsurmod']);
    142                 }
     118                        $thisfile_ac3_raw_bsi['flags']['langcod'] = (bool) $this->readHeaderBSI(1);     // 5.4.2.11 langcode: Language Code Exists, 1 Bit
     119                        if ($thisfile_ac3_raw_bsi['flags']['langcod']) {
     120                                $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);              // 5.4.2.12 langcod: Language Code, 8 Bits
     121                        }
    143122
    144                 $thisfile_ac3_raw_bsi['lfeon'] = (bool) $this->readHeaderBSI(1);
    145                 $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['lfeon'];
    146                 if ($thisfile_ac3_raw_bsi['lfeon']) {
    147                         //$info['audio']['channels']++;
    148                         $info['audio']['channels'] .= '.1';
    149                 }
     123                        $thisfile_ac3_raw_bsi['flags']['audprodinfo'] = (bool) $this->readHeaderBSI(1);  // 5.4.2.13 audprodie: Audio Production Information Exists, 1 Bit
     124                        if ($thisfile_ac3_raw_bsi['flags']['audprodinfo']) {
     125                                $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);             // 5.4.2.14 mixlevel: Mixing Level, 5 Bits
     126                                $thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);             // 5.4.2.15 roomtyp: Room Type, 2 Bits
    150127
    151                 $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['lfeon']);
     128                                $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
     129                                $thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
     130                        }
    152131
    153                 // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
    154                 // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
    155                 $thisfile_ac3_raw_bsi['dialnorm'] = $this->readHeaderBSI(5);
    156                 $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
    157132
    158                 $thisfile_ac3_raw_bsi['compre_flag'] = (bool) $this->readHeaderBSI(1);
    159                 if ($thisfile_ac3_raw_bsi['compre_flag']) {
    160                         $thisfile_ac3_raw_bsi['compr'] = $this->readHeaderBSI(8);
    161                         $thisfile_ac3['heavy_compression'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr']);
    162                 }
     133                        $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);                // 5.4.2.16 dialnorm2: Dialogue Normalization, ch2, 5 Bits
     134                        $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';  // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31. The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
    163135
    164                 $thisfile_ac3_raw_bsi['langcode_flag'] = (bool) $this->readHeaderBSI(1);
    165                 if ($thisfile_ac3_raw_bsi['langcode_flag']) {
    166                         $thisfile_ac3_raw_bsi['langcod'] = $this->readHeaderBSI(8);
    167                 }
     136                        $thisfile_ac3_raw_bsi['flags']['compr2'] = (bool) $this->readHeaderBSI(1);       // 5.4.2.17 compr2e: Compression Gain Word Exists, ch2, 1 Bit
     137                        if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
     138                                $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);               // 5.4.2.18 compr2: Compression Gain Word, ch2, 8 Bits
     139                                $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
     140                        }
    168141
    169                 $thisfile_ac3_raw_bsi['audprodie'] = (bool) $this->readHeaderBSI(1);
    170                 if ($thisfile_ac3_raw_bsi['audprodie']) {
    171                         $thisfile_ac3_raw_bsi['mixlevel'] = $this->readHeaderBSI(5);
    172                         $thisfile_ac3_raw_bsi['roomtyp']  = $this->readHeaderBSI(2);
     142                        $thisfile_ac3_raw_bsi['flags']['langcod2'] = (bool) $this->readHeaderBSI(1);    // 5.4.2.19 langcod2e: Language Code Exists, ch2, 1 Bit
     143                        if ($thisfile_ac3_raw_bsi['flags']['langcod2']) {
     144                                $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);             // 5.4.2.20 langcod2: Language Code, ch2, 8 Bits
     145                        }
    173146
    174                         $thisfile_ac3['mixing_level'] = (80 + $thisfile_ac3_raw_bsi['mixlevel']).'dB';
    175                         $thisfile_ac3['room_type']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp']);
    176                 }
     147                        $thisfile_ac3_raw_bsi['flags']['audprodinfo2'] = (bool) $this->readHeaderBSI(1); // 5.4.2.21 audprodi2e: Audio Production Information Exists, ch2, 1 Bit
     148                        if ($thisfile_ac3_raw_bsi['flags']['audprodinfo2']) {
     149                                $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);            // 5.4.2.22 mixlevel2: Mixing Level, ch2, 5 Bits
     150                                $thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(2);            // 5.4.2.23 roomtyp2: Room Type, ch2, 2 Bits
     151
     152                                $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
     153                                $thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
     154                        }
    177155
    178                 if ($thisfile_ac3_raw_bsi['acmod'] == 0x00) {
    179                         // If acmod is 0, then two completely independent program channels (dual mono)
    180                         // are encoded into the bit stream, and are referenced as Ch1, Ch2. In this case,
    181                         // a number of additional items are present in BSI or audblk to fully describe Ch2.
     156                        $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);         // 5.4.2.24 copyrightb: Copyright Bit, 1 Bit
    182157
    183                         // This indicates how far the average dialogue level is below digital 100 percent. Valid values are 1-31.
    184                         // The value of 0 is reserved. The values of 1 to 31 are interpreted as -1 dB to -31 dB with respect to digital 100 percent.
    185                         $thisfile_ac3_raw_bsi['dialnorm2'] = $this->readHeaderBSI(5);
    186                         $thisfile_ac3['dialogue_normalization2'] = '-'.$thisfile_ac3_raw_bsi['dialnorm2'].'dB';
     158                        $thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);         // 5.4.2.25 origbs: Original Bit Stream, 1 Bit
    187159
    188                         $thisfile_ac3_raw_bsi['compre_flag2'] = (bool) $this->readHeaderBSI(1);
    189                         if ($thisfile_ac3_raw_bsi['compre_flag2']) {
    190                                 $thisfile_ac3_raw_bsi['compr2'] = $this->readHeaderBSI(8);
    191                                 $thisfile_ac3['heavy_compression2'] = self::heavyCompression($thisfile_ac3_raw_bsi['compr2']);
     160                        $thisfile_ac3_raw_bsi['flags']['timecod1'] = $this->readHeaderBSI(2);            // 5.4.2.26 timecod1e, timcode2e: Time Code (first and second) Halves Exist, 2 Bits
     161                        if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) {
     162                                $thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14);            // 5.4.2.27 timecod1: Time code first half, 14 bits
     163                                $thisfile_ac3['timecode1'] = 0;
     164                                $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >>  9) * 3600;  // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23
     165                                $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >>  3) *   60;  // The next 6 bits represent the time in minutes, with valid values of 0�59
     166                                $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >>  0) *    8;  // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds)
    192167                        }
    193 
    194                         $thisfile_ac3_raw_bsi['langcode_flag2'] = (bool) $this->readHeaderBSI(1);
    195                         if ($thisfile_ac3_raw_bsi['langcode_flag2']) {
    196                                 $thisfile_ac3_raw_bsi['langcod2'] = $this->readHeaderBSI(8);
     168                        if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) {
     169                                $thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14);            // 5.4.2.28 timecod2: Time code second half, 14 bits
     170                                $thisfile_ac3['timecode2'] = 0;
     171                                $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) *   1;              // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds)
     172                                $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >>  6) *  (1 / 30);        // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second)
     173                                $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >>  0) * ((1 / 30) / 60);  // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63
    197174                        }
    198175
    199                         $thisfile_ac3_raw_bsi['audprodie2'] = (bool) $this->readHeaderBSI(1);
    200                         if ($thisfile_ac3_raw_bsi['audprodie2']) {
    201                                 $thisfile_ac3_raw_bsi['mixlevel2'] = $this->readHeaderBSI(5);
    202                                 $thisfile_ac3_raw_bsi['roomtyp2']  = $this->readHeaderBSI(2);
     176                        $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1);
     177                        if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
     178                                $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively.
    203179
    204                                 $thisfile_ac3['mixing_level2'] = (80 + $thisfile_ac3_raw_bsi['mixlevel2']).'dB';
    205                                 $thisfile_ac3['room_type2']    = self::roomTypeLookup($thisfile_ac3_raw_bsi['roomtyp2']);
     180                                $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
     181
     182                                $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
     183                                $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
    206184                        }
    207185
    208                 }
    209186
    210                 $thisfile_ac3_raw_bsi['copyright'] = (bool) $this->readHeaderBSI(1);
     187                } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
    211188
    212                 $thisfile_ac3_raw_bsi['original']  = (bool) $this->readHeaderBSI(1);
    213189
    214                 $thisfile_ac3_raw_bsi['timecode1_flag'] = (bool) $this->readHeaderBSI(1);
    215                 if ($thisfile_ac3_raw_bsi['timecode1_flag']) {
    216                         $thisfile_ac3_raw_bsi['timecode1'] = $this->readHeaderBSI(14);
    217                 }
     190$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
     191                        $info['audio']['dataformat'] = 'eac3';
     192
     193                        $thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
     194                        $thisfile_ac3_raw_bsi['substreamid']      =        $this->readHeaderBSI(3);
     195                        $thisfile_ac3_raw_bsi['frmsiz']           =        $this->readHeaderBSI(11);
     196                        $thisfile_ac3_raw_bsi['fscod']            =        $this->readHeaderBSI(2);
     197                        if ($thisfile_ac3_raw_bsi['fscod'] == 3) {
     198                                $thisfile_ac3_raw_bsi['fscod2']       =        $this->readHeaderBSI(2);
     199                                $thisfile_ac3_raw_bsi['numblkscod'] = 3; // six blocks per syncframe
     200                        } else {
     201                                $thisfile_ac3_raw_bsi['numblkscod']   =        $this->readHeaderBSI(2);
     202                        }
     203                        $thisfile_ac3['bsi']['blocks_per_sync_frame'] = self::blocksPerSyncFrame($thisfile_ac3_raw_bsi['numblkscod']);
     204                        $thisfile_ac3_raw_bsi['acmod']            =        $this->readHeaderBSI(3);
     205                        $thisfile_ac3_raw_bsi['flags']['lfeon']   = (bool) $this->readHeaderBSI(1);
     206                        $thisfile_ac3_raw_bsi['bsid']             =        $this->readHeaderBSI(5); // we already know this from pre-parsing the version identifier, but re-read it to let the bitstream flow as intended
     207                        $thisfile_ac3_raw_bsi['dialnorm']         =        $this->readHeaderBSI(5);
     208                        $thisfile_ac3_raw_bsi['flags']['compr']       = (bool) $this->readHeaderBSI(1);
     209                        if ($thisfile_ac3_raw_bsi['flags']['compr']) {
     210                                $thisfile_ac3_raw_bsi['compr']        =        $this->readHeaderBSI(8);
     211                        }
     212                        if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
     213                                $thisfile_ac3_raw_bsi['dialnorm2']    =        $this->readHeaderBSI(5);
     214                                $thisfile_ac3_raw_bsi['flags']['compr2']  = (bool) $this->readHeaderBSI(1);
     215                                if ($thisfile_ac3_raw_bsi['flags']['compr2']) {
     216                                        $thisfile_ac3_raw_bsi['compr2']   =        $this->readHeaderBSI(8);
     217                                }
     218                        }
     219                        if ($thisfile_ac3_raw_bsi['strmtyp'] == 1) { // if dependent stream
     220                                $thisfile_ac3_raw_bsi['flags']['chanmap'] = (bool) $this->readHeaderBSI(1);
     221                                if ($thisfile_ac3_raw_bsi['flags']['chanmap']) {
     222                                        $thisfile_ac3_raw_bsi['chanmap']  =        $this->readHeaderBSI(8);
     223                                }
     224                        }
     225                        $thisfile_ac3_raw_bsi['flags']['mixmdat']     = (bool) $this->readHeaderBSI(1);
     226                        if ($thisfile_ac3_raw_bsi['flags']['mixmdat']) { // Mixing metadata
     227                                if ($thisfile_ac3_raw_bsi['acmod'] > 2) { // if more than 2 channels
     228                                        $thisfile_ac3_raw_bsi['dmixmod']  =        $this->readHeaderBSI(2);
     229                                }
     230                                if (($thisfile_ac3_raw_bsi['acmod'] & 0x01) && ($thisfile_ac3_raw_bsi['acmod'] > 2)) { // if three front channels exist
     231                                        $thisfile_ac3_raw_bsi['ltrtcmixlev'] =        $this->readHeaderBSI(3);
     232                                        $thisfile_ac3_raw_bsi['lorocmixlev'] =        $this->readHeaderBSI(3);
     233                                }
     234                                if ($thisfile_ac3_raw_bsi['acmod'] & 0x04) { // if a surround channel exists
     235                                        $thisfile_ac3_raw_bsi['ltrtsurmixlev'] =        $this->readHeaderBSI(3);
     236                                        $thisfile_ac3_raw_bsi['lorosurmixlev'] =        $this->readHeaderBSI(3);
     237                                }
     238                                if ($thisfile_ac3_raw_bsi['flags']['lfeon']) { // if the LFE channel exists
     239                                        $thisfile_ac3_raw_bsi['flags']['lfemixlevcod'] = (bool) $this->readHeaderBSI(1);
     240                                        if ($thisfile_ac3_raw_bsi['flags']['lfemixlevcod']) {
     241                                                $thisfile_ac3_raw_bsi['lfemixlevcod']  =        $this->readHeaderBSI(5);
     242                                        }
     243                                }
     244                                if ($thisfile_ac3_raw_bsi['strmtyp'] == 0) { // if independent stream
     245                                        $thisfile_ac3_raw_bsi['flags']['pgmscl'] = (bool) $this->readHeaderBSI(1);
     246                                        if ($thisfile_ac3_raw_bsi['flags']['pgmscl']) {
     247                                                $thisfile_ac3_raw_bsi['pgmscl']  =        $this->readHeaderBSI(6);
     248                                        }
     249                                        if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
     250                                                $thisfile_ac3_raw_bsi['flags']['pgmscl2'] = (bool) $this->readHeaderBSI(1);
     251                                                if ($thisfile_ac3_raw_bsi['flags']['pgmscl2']) {
     252                                                        $thisfile_ac3_raw_bsi['pgmscl2']  =        $this->readHeaderBSI(6);
     253                                                }
     254                                        }
     255                                        $thisfile_ac3_raw_bsi['flags']['extpgmscl'] = (bool) $this->readHeaderBSI(1);
     256                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmscl']) {
     257                                                $thisfile_ac3_raw_bsi['extpgmscl']  =        $this->readHeaderBSI(6);
     258                                        }
     259                                        $thisfile_ac3_raw_bsi['mixdef']  =        $this->readHeaderBSI(2);
     260                                        if ($thisfile_ac3_raw_bsi['mixdef'] == 1) { // mixing option 2
     261                                                $thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1);
     262                                                $thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1);
     263                                                $thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3);
     264                                        } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 2) { // mixing option 3
     265                                                $thisfile_ac3_raw_bsi['mixdata']       =        $this->readHeaderBSI(12);
     266                                        } elseif ($thisfile_ac3_raw_bsi['mixdef'] == 3) { // mixing option 4
     267                                                $mixdefbitsread = 0;
     268                                                $thisfile_ac3_raw_bsi['mixdeflen']     =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
     269                                                $thisfile_ac3_raw_bsi['flags']['mixdata2'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     270                                                if ($thisfile_ac3_raw_bsi['flags']['mixdata2']) {
     271                                                        $thisfile_ac3_raw_bsi['premixcmpsel']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     272                                                        $thisfile_ac3_raw_bsi['drcsrc']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     273                                                        $thisfile_ac3_raw_bsi['premixcmpscl']  =        $this->readHeaderBSI(3); $mixdefbitsread += 3;
     274                                                        $thisfile_ac3_raw_bsi['flags']['extpgmlscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     275                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmlscl']) {
     276                                                                $thisfile_ac3_raw_bsi['extpgmlscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     277                                                        }
     278                                                        $thisfile_ac3_raw_bsi['flags']['extpgmcscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     279                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmcscl']) {
     280                                                                $thisfile_ac3_raw_bsi['extpgmcscl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     281                                                        }
     282                                                        $thisfile_ac3_raw_bsi['flags']['extpgmrscl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     283                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmrscl']) {
     284                                                                $thisfile_ac3_raw_bsi['extpgmrscl']    =        $this->readHeaderBSI(4);
     285                                                        }
     286                                                        $thisfile_ac3_raw_bsi['flags']['extpgmlsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     287                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmlsscl']) {
     288                                                                $thisfile_ac3_raw_bsi['extpgmlsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     289                                                        }
     290                                                        $thisfile_ac3_raw_bsi['flags']['extpgmrsscl']  = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     291                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmrsscl']) {
     292                                                                $thisfile_ac3_raw_bsi['extpgmrsscl']   =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     293                                                        }
     294                                                        $thisfile_ac3_raw_bsi['flags']['extpgmlfescl'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     295                                                        if ($thisfile_ac3_raw_bsi['flags']['extpgmlfescl']) {
     296                                                                $thisfile_ac3_raw_bsi['extpgmlfescl']  =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     297                                                        }
     298                                                        $thisfile_ac3_raw_bsi['flags']['dmixscl']      = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     299                                                        if ($thisfile_ac3_raw_bsi['flags']['dmixscl']) {
     300                                                                $thisfile_ac3_raw_bsi['dmixscl']       =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     301                                                        }
     302                                                        $thisfile_ac3_raw_bsi['flags']['addch']        = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     303                                                        if ($thisfile_ac3_raw_bsi['flags']['addch']) {
     304                                                                $thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     305                                                                if ($thisfile_ac3_raw_bsi['flags']['extpgmaux1scl']) {
     306                                                                        $thisfile_ac3_raw_bsi['extpgmaux1scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     307                                                                }
     308                                                                $thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']   = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     309                                                                if ($thisfile_ac3_raw_bsi['flags']['extpgmaux2scl']) {
     310                                                                        $thisfile_ac3_raw_bsi['extpgmaux2scl']    =        $this->readHeaderBSI(4); $mixdefbitsread += 4;
     311                                                                }
     312                                                        }
     313                                                }
     314                                                $thisfile_ac3_raw_bsi['flags']['mixdata3'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     315                                                if ($thisfile_ac3_raw_bsi['flags']['mixdata3']) {
     316                                                        $thisfile_ac3_raw_bsi['spchdat']   =        $this->readHeaderBSI(5); $mixdefbitsread += 5;
     317                                                        $thisfile_ac3_raw_bsi['flags']['addspchdat'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     318                                                        if ($thisfile_ac3_raw_bsi['flags']['addspchdat']) {
     319                                                                $thisfile_ac3_raw_bsi['spchdat1']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
     320                                                                $thisfile_ac3_raw_bsi['spchan1att'] =         $this->readHeaderBSI(2); $mixdefbitsread += 2;
     321                                                                $thisfile_ac3_raw_bsi['flags']['addspchdat1'] = (bool) $this->readHeaderBSI(1); $mixdefbitsread += 1;
     322                                                                if ($thisfile_ac3_raw_bsi['flags']['addspchdat1']) {
     323                                                                        $thisfile_ac3_raw_bsi['spchdat2']   =         $this->readHeaderBSI(5); $mixdefbitsread += 5;
     324                                                                        $thisfile_ac3_raw_bsi['spchan2att'] =         $this->readHeaderBSI(3); $mixdefbitsread += 3;
     325                                                                }
     326                                                        }
     327                                                }
     328                                                $mixdata_bits = (8 * ($thisfile_ac3_raw_bsi['mixdeflen'] + 2)) - $mixdefbitsread;
     329                                                $mixdata_fill = (($mixdata_bits % 8) ? 8 - ($mixdata_bits % 8) : 0);
     330                                                $thisfile_ac3_raw_bsi['mixdata']     =        $this->readHeaderBSI($mixdata_bits);
     331                                                $thisfile_ac3_raw_bsi['mixdatafill'] =        $this->readHeaderBSI($mixdata_fill);
     332                                                unset($mixdefbitsread, $mixdata_bits, $mixdata_fill);
     333                                        }
     334                                        if ($thisfile_ac3_raw_bsi['acmod'] < 2) { // if mono or dual mono source
     335                                                $thisfile_ac3_raw_bsi['flags']['paninfo'] = (bool) $this->readHeaderBSI(1);
     336                                                if ($thisfile_ac3_raw_bsi['flags']['paninfo']) {
     337                                                        $thisfile_ac3_raw_bsi['panmean']   =        $this->readHeaderBSI(8);
     338                                                        $thisfile_ac3_raw_bsi['paninfo']   =        $this->readHeaderBSI(6);
     339                                                }
     340                                                if ($thisfile_ac3_raw_bsi['acmod'] == 0) { // if 1+1 mode (dual mono, so some items need a second value)
     341                                                        $thisfile_ac3_raw_bsi['flags']['paninfo2'] = (bool) $this->readHeaderBSI(1);
     342                                                        if ($thisfile_ac3_raw_bsi['flags']['paninfo2']) {
     343                                                                $thisfile_ac3_raw_bsi['panmean2']   =        $this->readHeaderBSI(8);
     344                                                                $thisfile_ac3_raw_bsi['paninfo2']   =        $this->readHeaderBSI(6);
     345                                                        }
     346                                                }
     347                                        }
     348                                        $thisfile_ac3_raw_bsi['flags']['frmmixcfginfo'] = (bool) $this->readHeaderBSI(1);
     349                                        if ($thisfile_ac3_raw_bsi['flags']['frmmixcfginfo']) { // mixing configuration information
     350                                                if ($thisfile_ac3_raw_bsi['numblkscod'] == 0) {
     351                                                        $thisfile_ac3_raw_bsi['blkmixcfginfo'][0]  =        $this->readHeaderBSI(5);
     352                                                } else {
     353                                                        for ($blk = 0; $blk < $thisfile_ac3_raw_bsi['numblkscod']; $blk++) {
     354                                                                $thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk] = (bool) $this->readHeaderBSI(1);
     355                                                                if ($thisfile_ac3_raw_bsi['flags']['blkmixcfginfo'.$blk]) { // mixing configuration information
     356                                                                        $thisfile_ac3_raw_bsi['blkmixcfginfo'][$blk]  =        $this->readHeaderBSI(5);
     357                                                                }
     358                                                        }
     359                                                }
     360                                        }
     361                                }
     362                        }
     363                        $thisfile_ac3_raw_bsi['flags']['infomdat']          = (bool) $this->readHeaderBSI(1);
     364                        if ($thisfile_ac3_raw_bsi['flags']['infomdat']) { // Informational metadata
     365                                $thisfile_ac3_raw_bsi['bsmod']                  =        $this->readHeaderBSI(3);
     366                                $thisfile_ac3_raw_bsi['flags']['copyrightb']    = (bool) $this->readHeaderBSI(1);
     367                                $thisfile_ac3_raw_bsi['flags']['origbs']        = (bool) $this->readHeaderBSI(1);
     368                                if ($thisfile_ac3_raw_bsi['acmod'] == 2) { //  if in 2/0 mode
     369                                        $thisfile_ac3_raw_bsi['dsurmod']            =        $this->readHeaderBSI(2);
     370                                        $thisfile_ac3_raw_bsi['dheadphonmod']       =        $this->readHeaderBSI(2);
     371                                }
     372                                if ($thisfile_ac3_raw_bsi['acmod'] >= 6) { //  if both surround channels exist
     373                                        $thisfile_ac3_raw_bsi['dsurexmod']          =        $this->readHeaderBSI(2);
     374                                }
     375                                $thisfile_ac3_raw_bsi['flags']['audprodi']      = (bool) $this->readHeaderBSI(1);
     376                                if ($thisfile_ac3_raw_bsi['flags']['audprodi']) {
     377                                        $thisfile_ac3_raw_bsi['mixlevel']           =        $this->readHeaderBSI(5);
     378                                        $thisfile_ac3_raw_bsi['roomtyp']            =        $this->readHeaderBSI(2);
     379                                        $thisfile_ac3_raw_bsi['flags']['adconvtyp'] = (bool) $this->readHeaderBSI(1);
     380                                }
     381                                if ($thisfile_ac3_raw_bsi['acmod'] == 0) { //  if 1+1 mode (dual mono, so some items need a second value)
     382                                        $thisfile_ac3_raw_bsi['flags']['audprodi2']      = (bool) $this->readHeaderBSI(1);
     383                                        if ($thisfile_ac3_raw_bsi['flags']['audprodi2']) {
     384                                                $thisfile_ac3_raw_bsi['mixlevel2']           =        $this->readHeaderBSI(5);
     385                                                $thisfile_ac3_raw_bsi['roomtyp2']            =        $this->readHeaderBSI(2);
     386                                                $thisfile_ac3_raw_bsi['flags']['adconvtyp2'] = (bool) $this->readHeaderBSI(1);
     387                                        }
     388                                }
     389                                if ($thisfile_ac3_raw_bsi['fscod'] < 3) { // if not half sample rate
     390                                        $thisfile_ac3_raw_bsi['flags']['sourcefscod'] = (bool) $this->readHeaderBSI(1);
     391                                }
     392                        }
     393                        if (($thisfile_ac3_raw_bsi['strmtyp'] == 0) && ($thisfile_ac3_raw_bsi['numblkscod'] != 3)) { //  if both surround channels exist
     394                                $thisfile_ac3_raw_bsi['flags']['convsync'] = (bool) $this->readHeaderBSI(1);
     395                        }
     396                        if ($thisfile_ac3_raw_bsi['strmtyp'] == 2) { //  if bit stream converted from AC-3
     397                                if ($thisfile_ac3_raw_bsi['numblkscod'] != 3) { // 6 blocks per syncframe
     398                                        $thisfile_ac3_raw_bsi['flags']['blkid']  = 1;
     399                                } else {
     400                                        $thisfile_ac3_raw_bsi['flags']['blkid']  = (bool) $this->readHeaderBSI(1);
     401                                }
     402                                if ($thisfile_ac3_raw_bsi['flags']['blkid']) {
     403                                        $thisfile_ac3_raw_bsi['frmsizecod']  =        $this->readHeaderBSI(6);
     404                                }
     405                        }
     406                        $thisfile_ac3_raw_bsi['flags']['addbsi']  = (bool) $this->readHeaderBSI(1);
     407                        if ($thisfile_ac3_raw_bsi['flags']['addbsi']) {
     408                                $thisfile_ac3_raw_bsi['addbsil']  =        $this->readHeaderBSI(6);
     409                                $thisfile_ac3_raw_bsi['addbsi']   =        $this->readHeaderBSI(($thisfile_ac3_raw_bsi['addbsil'] + 1) * 8);
     410                        }
     411
     412                } else {
     413
     414                        $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
     415                    unset($info['ac3']);
     416                        return false;
    218417
    219                 $thisfile_ac3_raw_bsi['timecode2_flag'] = (bool) $this->readHeaderBSI(1);
    220                 if ($thisfile_ac3_raw_bsi['timecode2_flag']) {
    221                         $thisfile_ac3_raw_bsi['timecode2'] = $this->readHeaderBSI(14);
    222418                }
    223419
    224                 $thisfile_ac3_raw_bsi['addbsi_flag'] = (bool) $this->readHeaderBSI(1);
    225                 if ($thisfile_ac3_raw_bsi['addbsi_flag']) {
    226                         $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6);
     420                if (isset($thisfile_ac3_raw_bsi['fscod2'])) {
     421                        $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup2($thisfile_ac3_raw_bsi['fscod2']);
     422                } else {
     423                        $thisfile_ac3['sample_rate'] = self::sampleRateCodeLookup($thisfile_ac3_raw_bsi['fscod']);
     424                }
     425                if ($thisfile_ac3_raw_bsi['fscod'] <= 3) {
     426                        $info['audio']['sample_rate'] = $thisfile_ac3['sample_rate'];
     427                } else {
     428                        $this->warning('Unexpected ac3.bsi.fscod value: '.$thisfile_ac3_raw_bsi['fscod']);
     429                }
     430                if (isset($thisfile_ac3_raw_bsi['frmsizecod'])) {
     431                        $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
     432                        $thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
     433                } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
     434// this isn't right, but it's (usually) close, roughly 5% less than it should be.
     435// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
     436                        $thisfile_ac3['bitrate']      = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
     437// kludge-fix to make it approximately the expected value, still not "right":
     438$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
     439                }
     440                $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
    227441
    228                         $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length']));
     442                $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
     443                $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
     444                foreach($ac3_coding_mode as $key => $value) {
     445                        $thisfile_ac3[$key] = $value;
     446                }
     447                switch ($thisfile_ac3_raw_bsi['acmod']) {
     448                        case 0:
     449                        case 1:
     450                                $info['audio']['channelmode'] = 'mono';
     451                                break;
     452                        case 3:
     453                        case 4:
     454                                $info['audio']['channelmode'] = 'stereo';
     455                                break;
     456                        default:
     457                                $info['audio']['channelmode'] = 'surround';
     458                                break;
     459                }
     460                $info['audio']['channels'] = $thisfile_ac3['num_channels'];
    229461
    230                         $thisfile_ac3_raw_bsi['addbsi_data'] = substr($this->AC3header['bsi'], $this->BSIoffset, $thisfile_ac3_raw_bsi['addbsi_length'] * 8);
    231                         $this->BSIoffset += $thisfile_ac3_raw_bsi['addbsi_length'] * 8;
     462                $thisfile_ac3['lfe_enabled'] = $thisfile_ac3_raw_bsi['flags']['lfeon'];
     463                if ($thisfile_ac3_raw_bsi['flags']['lfeon']) {
     464                        $info['audio']['channels'] .= '.1';
    232465                }
    233466
     467                $thisfile_ac3['channels_enabled'] = self::channelsEnabledLookup($thisfile_ac3_raw_bsi['acmod'], $thisfile_ac3_raw_bsi['flags']['lfeon']);
     468                $thisfile_ac3['dialogue_normalization'] = '-'.$thisfile_ac3_raw_bsi['dialnorm'].'dB';
     469
    234470                return true;
    235471        }
    236472
    class getid3_ac3 extends getid3_handler 
    251487                return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
    252488        }
    253489
     490        public static function sampleRateCodeLookup2($fscod2) {
     491                static $sampleRateCodeLookup2 = array(
     492                        0 => 24000,
     493                        1 => 22050,
     494                        2 => 16000,
     495                        3 => 'reserved' // If the reserved code is indicated, the decoder should not attempt to decode audio and should mute.
     496                );
     497                return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
     498        }
     499
    254500        public static function serviceTypeLookup($bsmod, $acmod) {
    255501                static $serviceTypeLookup = array();
    256502                if (empty($serviceTypeLookup)) {
    class getid3_ac3 extends getid3_handler 
    409655        }
    410656
    411657        public static function frameSizeLookup($frmsizecod, $fscod) {
    412                 $padding     = (bool) ($frmsizecod % 2);
    413                 $framesizeid =   floor($frmsizecod / 2);
     658                // LSB is whether padding is used or not
     659                $padding     = (bool) ($frmsizecod & 0x01);
     660                $framesizeid =        ($frmsizecod & 0x3E) >> 1;
    414661
    415662                static $frameSizeLookup = array();
    416663                if (empty($frameSizeLookup)) {
    417664                        $frameSizeLookup = array (
    418                                 0  => array(128, 138, 192),
    419                                 1  => array(40, 160, 174, 240),
    420                                 2  => array(48, 192, 208, 288),
    421                                 3  => array(56, 224, 242, 336),
    422                                 4  => array(64, 256, 278, 384),
    423                                 5  => array(80, 320, 348, 480),
    424                                 6  => array(96, 384, 416, 576),
    425                                 7  => array(112, 448, 486, 672),
    426                                 8  => array(128, 512, 556, 768),
    427                                 9  => array(160, 640, 696, 960),
    428                                 10 => array(192, 768, 834, 1152),
    429                                 11 => array(224, 896, 974, 1344),
    430                                 12 => array(256, 1024, 1114, 1536),
    431                                 13 => array(320, 1280, 1392, 1920),
    432                                 14 => array(384, 1536, 1670, 2304),
    433                                 15 => array(448, 1792, 1950, 2688),
    434                                 16 => array(512, 2048, 2228, 3072),
    435                                 17 => array(576, 2304, 2506, 3456),
    436                                 18 => array(640, 2560, 2786, 3840)
     665                                0  => array( 128,  138,  192),  //  32 kbps
     666                                1  => array( 160,  174,  240),  //  40 kbps
     667                                2  => array( 192,  208,  288),  //  48