WordPress.org

Make WordPress Core

Changeset 46112


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

Update getID3 library to fix issues with PHP7.4

Updates to trunk version that includes fixes for PHP7.4

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

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

Location:
trunk/src/wp-includes/ID3
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/ID3/getid3.lib.php

    r41196 r46112  
    11<?php
     2
    23/////////////////////////////////////////////////////////////////
    34/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
     5//  available at https://github.com/JamesHeinrich/getID3       //
     6//            or https://www.getid3.org                        //
     7//            or http://getid3.sourceforge.net                 //
    88//                                                             //
    99// getid3.lib.php - part of getID3()                           //
    10 // See readme.txt for more details                             //
     10//  see readme.txt for more details                            //
    1111//                                                            ///
    1212/////////////////////////////////////////////////////////////////
     
    1515class getid3_lib
    1616{
    17 
     17    /**
     18     * @param string $string
     19     * @param bool   $hex
     20     * @param bool   $spaces
     21     * @param string $htmlencoding
     22     *
     23     * @return string
     24     */
    1825    public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
    1926        $returnstring = '';
    2027        for ($i = 0; $i < strlen($string); $i++) {
    2128            if ($hex) {
    22                 $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
     29                $returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
    2330            } else {
    24                 $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤');
     31                $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤');
    2532            }
    2633            if ($spaces) {
     
    3744    }
    3845
     46    /**
     47     * Truncates a floating-point number at the decimal point.
     48     *
     49     * @param float $floatnumber
     50     *
     51     * @return float|int returns int (if possible, otherwise float)
     52     */
    3953    public static function trunc($floatnumber) {
    40         // truncates a floating-point number at the decimal point
    41         // returns int (if possible, otherwise float)
    4254        if ($floatnumber >= 1) {
    4355            $truncatednumber = floor($floatnumber);
     
    5365    }
    5466
    55 
     67    /**
     68     * @param int|null $variable
     69     * @param int      $increment
     70     *
     71     * @return bool
     72     */
    5673    public static function safe_inc(&$variable, $increment=1) {
    5774        if (isset($variable)) {
     
    6380    }
    6481
     82    /**
     83     * @param int|float $floatnum
     84     *
     85     * @return int|float
     86     */
    6587    public static function CastAsInt($floatnum) {
    6688        // convert to float if not already
     
    78100    }
    79101
     102    /**
     103     * @param int $num
     104     *
     105     * @return bool
     106     */
    80107    public static function intValueSupported($num) {
    81108        // check if integers are 64-bit
     
    94121    }
    95122
     123    /**
     124     * @param string $fraction
     125     *
     126     * @return float
     127     */
    96128    public static function DecimalizeFraction($fraction) {
    97129        list($numerator, $denominator) = explode('/', $fraction);
     
    99131    }
    100132
    101 
     133    /**
     134     * @param string $binarynumerator
     135     *
     136     * @return float
     137     */
    102138    public static function DecimalBinary2Float($binarynumerator) {
    103139        $numerator   = self::Bin2Dec($binarynumerator);
     
    106142    }
    107143
    108 
     144    /**
     145     * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
     146     *
     147     * @param string $binarypointnumber
     148     * @param int    $maxbits
     149     *
     150     * @return array
     151     */
    109152    public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
    110         // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
    111153        if (strpos($binarypointnumber, '.') === false) {
    112154            $binarypointnumber = '0.'.$binarypointnumber;
    113         } elseif ($binarypointnumber{0} == '.') {
     155        } elseif ($binarypointnumber[0] == '.') {
    114156            $binarypointnumber = '0'.$binarypointnumber;
    115157        }
    116158        $exponent = 0;
    117         while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
     159        while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
    118160            if (substr($binarypointnumber, 1, 1) == '.') {
    119161                $exponent--;
     
    123165                $exponent += ($pointpos - 1);
    124166                $binarypointnumber = str_replace('.', '', $binarypointnumber);
    125                 $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
     167                $binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
    126168            }
    127169        }
     
    130172    }
    131173
    132 
     174    /**
     175     * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
     176     *
     177     * @param float $floatvalue
     178     *
     179     * @return string
     180     */
    133181    public static function Float2BinaryDecimal($floatvalue) {
    134         // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
    135182        $maxbits = 128; // to how many bits of precision should the calculations be taken?
    136183        $intpart   = self::trunc($floatvalue);
     
    146193    }
    147194
    148 
     195    /**
     196     * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
     197     *
     198     * @param float $floatvalue
     199     * @param int $bits
     200     *
     201     * @return string|false
     202     */
    149203    public static function Float2String($floatvalue, $bits) {
    150         // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
     204        $exponentbits = 0;
     205        $fractionbits = 0;
    151206        switch ($bits) {
    152207            case 32:
     
    177232    }
    178233
    179 
     234    /**
     235     * @param string $byteword
     236     *
     237     * @return float|false
     238     */
    180239    public static function LittleEndian2Float($byteword) {
    181240        return self::BigEndian2Float(strrev($byteword));
    182241    }
    183242
    184 
     243    /**
     244     * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
     245     *
     246     * @link http://www.psc.edu/general/software/packages/ieee/ieee.html
     247     * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
     248     *
     249     * @param string $byteword
     250     *
     251     * @return float|false
     252     */
    185253    public static function BigEndian2Float($byteword) {
    186         // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
    187         // http://www.psc.edu/general/software/packages/ieee/ieee.html
    188         // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
    189 
    190254        $bitword = self::BigEndian2Bin($byteword);
    191255        if (!$bitword) {
    192256            return 0;
    193257        }
    194         $signbit = $bitword{0};
     258        $signbit = $bitword[0];
     259        $floatvalue = 0;
     260        $exponentbits = 0;
     261        $fractionbits = 0;
    195262
    196263        switch (strlen($byteword) * 8) {
     
    209276                // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
    210277                $exponentstring = substr($bitword, 1, 15);
    211                 $isnormalized = intval($bitword{16});
     278                $isnormalized = intval($bitword[16]);
    212279                $fractionstring = substr($bitword, 17, 63);
    213280                $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
     
    260327    }
    261328
    262 
     329    /**
     330     * @param string $byteword
     331     * @param bool   $synchsafe
     332     * @param bool   $signed
     333     *
     334     * @return int|float|false
     335     * @throws Exception
     336     */
    263337    public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
    264338        $intvalue = 0;
     
    270344            if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
    271345                //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
    272                 $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
     346                $intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
    273347            } else {
    274                 $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
     348                $intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
    275349            }
    276350        }
     
    289363    }
    290364
    291 
     365    /**
     366     * @param string $byteword
     367     * @param bool   $signed
     368     *
     369     * @return int|float|false
     370     */
    292371    public static function LittleEndian2Int($byteword, $signed=false) {
    293372        return self::BigEndian2Int(strrev($byteword), false, $signed);
    294373    }
    295374
     375    /**
     376     * @param string $byteword
     377     *
     378     * @return string
     379     */
    296380    public static function LittleEndian2Bin($byteword) {
    297381        return self::BigEndian2Bin(strrev($byteword));
    298382    }
    299383
     384    /**
     385     * @param string $byteword
     386     *
     387     * @return string
     388     */
    300389    public static function BigEndian2Bin($byteword) {
    301390        $binvalue = '';
    302391        $bytewordlen = strlen($byteword);
    303392        for ($i = 0; $i < $bytewordlen; $i++) {
    304             $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
     393            $binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
    305394        }
    306395        return $binvalue;
    307396    }
    308397
    309 
     398    /**
     399     * @param int  $number
     400     * @param int  $minbytes
     401     * @param bool $synchsafe
     402     * @param bool $signed
     403     *
     404     * @return string
     405     * @throws Exception
     406     */
    310407    public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
    311408        if ($number < 0) {
     
    328425    }
    329426
    330 
     427    /**
     428     * @param int $number
     429     *
     430     * @return string
     431     */
    331432    public static function Dec2Bin($number) {
    332433        while ($number >= 256) {
     
    342443    }
    343444
    344 
     445    /**
     446     * @param string $binstring
     447     * @param bool   $signed
     448     *
     449     * @return int|float
     450     */
    345451    public static function Bin2Dec($binstring, $signed=false) {
    346452        $signmult = 1;
    347453        if ($signed) {
    348             if ($binstring{0} == '1') {
     454            if ($binstring[0] == '1') {
    349455                $signmult = -1;
    350456            }
     
    358464    }
    359465
    360 
     466    /**
     467     * @param string $binstring
     468     *
     469     * @return string
     470     */
    361471    public static function Bin2String($binstring) {
    362472        // return 'hi' for input of '0110100001101001'
     
    369479    }
    370480
    371 
     481    /**
     482     * @param int  $number
     483     * @param int  $minbytes
     484     * @param bool $synchsafe
     485     *
     486     * @return string
     487     */
    372488    public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
    373489        $intstring = '';
     
    384500    }
    385501
    386 
     502    /**
     503     * @param array $array1
     504     * @param array $array2
     505     *
     506     * @return array|false
     507     */
    387508    public static function array_merge_clobber($array1, $array2) {
    388509        // written by kcØhireability*com
     
    402523    }
    403524
    404 
     525    /**
     526     * @param array $array1
     527     * @param array $array2
     528     *
     529     * @return array|false
     530     */
    405531    public static function array_merge_noclobber($array1, $array2) {
    406532        if (!is_array($array1) || !is_array($array2)) {
     
    418544    }
    419545
     546    /**
     547     * @param array $array1
     548     * @param array $array2
     549     *
     550     * @return array|false|null
     551     */
    420552    public static function flipped_array_merge_noclobber($array1, $array2) {
    421553        if (!is_array($array1) || !is_array($array2)) {
     
    432564    }
    433565
    434 
     566    /**
     567     * @param array $theArray
     568     *
     569     * @return bool
     570     */
    435571    public static function ksort_recursive(&$theArray) {
    436572        ksort($theArray);
     
    443579    }
    444580
     581    /**
     582     * @param string $filename
     583     * @param int    $numextensions
     584     *
     585     * @return string
     586     */
    445587    public static function fileextension($filename, $numextensions=1) {
    446588        if (strstr($filename, '.')) {
     
    458600    }
    459601
    460 
     602    /**
     603     * @param int $seconds
     604     *
     605     * @return string
     606     */
    461607    public static function PlaytimeString($seconds) {
    462608        $sign = (($seconds < 0) ? '-' : '');
     
    468614    }
    469615
    470 
     616    /**
     617     * @param int $macdate
     618     *
     619     * @return int|float
     620     */
    471621    public static function DateMac2Unix($macdate) {
    472622        // Macintosh timestamp: seconds since 00:00h January 1, 1904
     
    475625    }
    476626
    477 
     627    /**
     628     * @param string $rawdata
     629     *
     630     * @return float
     631     */
    478632    public static function FixedPoint8_8($rawdata) {
    479633        return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
    480634    }
    481635
    482 
     636    /**
     637     * @param string $rawdata
     638     *
     639     * @return float
     640     */
    483641    public static function FixedPoint16_16($rawdata) {
    484642        return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
    485643    }
    486644
    487 
     645    /**
     646     * @param string $rawdata
     647     *
     648     * @return float
     649     */
    488650    public static function FixedPoint2_30($rawdata) {
    489651        $binarystring = self::BigEndian2Bin($rawdata);
     
    492654
    493655
     656    /**
     657     * @param string $ArrayPath
     658     * @param string $Separator
     659     * @param mixed $Value
     660     *
     661     * @return array
     662     */
    494663    public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
    495664        // assigns $Value to a nested array path:
     
    508677    }
    509678
     679    /**
     680     * @param array $arraydata
     681     * @param bool  $returnkey
     682     *
     683     * @return int|false
     684     */
    510685    public static function array_max($arraydata, $returnkey=false) {
    511686        $maxvalue = false;
     
    522697    }
    523698
     699    /**
     700     * @param array $arraydata
     701     * @param bool  $returnkey
     702     *
     703     * @return int|false
     704     */
    524705    public static function array_min($arraydata, $returnkey=false) {
    525706        $minvalue = false;
     
    536717    }
    537718
     719    /**
     720     * @param string $XMLstring
     721     *
     722     * @return array|false
     723     */
    538724    public static function XML2array($XMLstring) {
    539725        if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
     
    549735    }
    550736
     737    /**
     738    * @param SimpleXMLElement|array $XMLobject
     739    *
     740    * @return array
     741    */
    551742    public static function SimpleXMLelement2array($XMLobject) {
    552743        if (!is_object($XMLobject) && !is_array($XMLobject)) {
    553744            return $XMLobject;
    554745        }
    555         $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject);
     746        $XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject;
    556747        foreach ($XMLarray as $key => $value) {
    557748            $XMLarray[$key] = self::SimpleXMLelement2array($value);
     
    560751    }
    561752
    562 
    563     // Allan Hansen <ahØartemis*dk>
    564     // self::md5_data() - returns md5sum for a file from startuing position to absolute end position
     753    /**
     754     * Returns checksum for a file from starting position to absolute end position.
     755     *
     756     * @param string $file
     757     * @param int    $offset
     758     * @param int    $end
     759     * @param string $algorithm
     760     *
     761     * @return string|false
     762     * @throws getid3_exception
     763     */
    565764    public static function hash_data($file, $offset, $end, $algorithm) {
    566         static $tempdir = '';
    567765        if (!self::intValueSupported($end)) {
    568766            return false;
    569767        }
    570         switch ($algorithm) {
    571             case 'md5':
    572                 $hash_function = 'md5_file';
    573                 $unix_call     = 'md5sum';
    574                 $windows_call  = 'md5sum.exe';
    575                 $hash_length   = 32;
    576                 break;
    577 
    578             case 'sha1':
    579                 $hash_function = 'sha1_file';
    580                 $unix_call     = 'sha1sum';
    581                 $windows_call  = 'sha1sum.exe';
    582                 $hash_length   = 40;
    583                 break;
    584 
    585             default:
    586                 throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
    587                 break;
    588         }
     768        if (!in_array($algorithm, array('md5', 'sha1'))) {
     769            throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
     770        }
     771
    589772        $size = $end - $offset;
    590         while (true) {
    591             if (GETID3_OS_ISWINDOWS) {
    592 
    593                 // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
    594                 // Fall back to create-temp-file method:
    595                 if ($algorithm == 'sha1') {
    596                     break;
    597                 }
    598 
    599                 $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
    600                 foreach ($RequiredFiles as $required_file) {
    601                     if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
    602                         // helper apps not available - fall back to old method
    603                         break 2;
    604                     }
    605                 }
    606                 $commandline  = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | ';
    607                 $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
    608                 $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
    609 
    610             } else {
    611 
    612                 $commandline  = 'head -c'.$end.' '.escapeshellarg($file).' | ';
    613                 $commandline .= 'tail -c'.$size.' | ';
    614                 $commandline .= $unix_call;
    615 
    616             }
    617             if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
    618                 //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm');
    619                 break;
    620             }
    621             return substr(`$commandline`, 0, $hash_length);
    622         }
    623 
    624         if (empty($tempdir)) {
    625             // yes this is ugly, feel free to suggest a better way
    626             require_once(dirname(__FILE__).'/getid3.php');
    627             $getid3_temp = new getID3();
    628             $tempdir = $getid3_temp->tempdir;
    629             unset($getid3_temp);
    630         }
    631         // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
    632         if (($data_filename = tempnam($tempdir, 'gI3')) === false) {
    633             // can't find anywhere to create a temp file, just fail
    634             return false;
    635         }
    636 
    637         // Init
    638         $result = false;
    639 
    640         // copy parts of file
    641         try {
    642             self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
    643             $result = $hash_function($data_filename);
    644         } catch (Exception $e) {
    645             throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
    646         }
    647         unlink($data_filename);
    648         return $result;
    649     }
    650 
     773
     774        $fp = fopen($file, 'rb');
     775        fseek($fp, $offset);
     776        $ctx = hash_init($algorithm);
     777        while ($size > 0) {
     778            $buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE));
     779            hash_update($ctx, $buffer);
     780            $size -= getID3::FREAD_BUFFER_SIZE;
     781        }
     782        $hash = hash_final($ctx);
     783        fclose($fp);
     784
     785        return $hash;
     786    }
     787
     788    /**
     789     * @param string $filename_source
     790     * @param string $filename_dest
     791     * @param int    $offset
     792     * @param int    $length
     793     *
     794     * @return bool
     795     * @throws Exception
     796     *
     797     * @deprecated Unused, may be removed in future versions of getID3
     798     */
    651799    public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
    652800        if (!self::intValueSupported($offset + $length)) {
     
    661809                        $byteslefttowrite -= $byteswritten;
    662810                    }
     811                    fclose($fp_dest);
    663812                    return true;
    664813                } else {
     814                    fclose($fp_src);
    665815                    throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
    666816                }
    667                 fclose($fp_dest);
    668817            } else {
    669818                throw new Exception('failed to create file for writing '.$filename_dest);
    670819            }
    671             fclose($fp_src);
    672820        } else {
    673821            throw new Exception('failed to open file for reading '.$filename_source);
    674822        }
    675         return false;
    676     }
    677 
     823    }
     824
     825    /**
     826     * @param int $charval
     827     *
     828     * @return string
     829     */
    678830    public static function iconv_fallback_int_utf8($charval) {
    679831        if ($charval < 128) {
     
    699851    }
    700852
    701     // ISO-8859-1 => UTF-8
     853    /**
     854     * ISO-8859-1 => UTF-8
     855     *
     856     * @param string $string
     857     * @param bool   $bom
     858     *
     859     * @return string
     860     */
    702861    public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
    703862        if (function_exists('utf8_encode')) {
     
    710869        }
    711870        for ($i = 0; $i < strlen($string); $i++) {
    712             $charval = ord($string{$i});
     871            $charval = ord($string[$i]);
    713872            $newcharstring .= self::iconv_fallback_int_utf8($charval);
    714873        }
     
    716875    }
    717876
    718     // ISO-8859-1 => UTF-16BE
     877    /**
     878     * ISO-8859-1 => UTF-16BE
     879     *
     880     * @param string $string
     881     * @param bool   $bom
     882     *
     883     * @return string
     884     */
    719885    public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
    720886        $newcharstring = '';
     
    723889        }
    724890        for ($i = 0; $i < strlen($string); $i++) {
    725             $newcharstring .= "\x00".$string{$i};
     891            $newcharstring .= "\x00".$string[$i];
    726892        }
    727893        return $newcharstring;
    728894    }
    729895
    730     // ISO-8859-1 => UTF-16LE
     896    /**
     897     * ISO-8859-1 => UTF-16LE
     898     *
     899     * @param string $string
     900     * @param bool   $bom
     901     *
     902     * @return string
     903     */
    731904    public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
    732905        $newcharstring = '';
     
    735908        }
    736909        for ($i = 0; $i < strlen($string); $i++) {
    737             $newcharstring .= $string{$i}."\x00";
     910            $newcharstring .= $string[$i]."\x00";
    738911        }
    739912        return $newcharstring;
    740913    }
    741914
    742     // ISO-8859-1 => UTF-16LE (BOM)
     915    /**
     916     * ISO-8859-1 => UTF-16LE (BOM)
     917     *
     918     * @param string $string
     919     *
     920     * @return string
     921     */
    743922    public static function iconv_fallback_iso88591_utf16($string) {
    744923        return self::iconv_fallback_iso88591_utf16le($string, true);
    745924    }
    746925
    747     // UTF-8 => ISO-8859-1
     926    /**
     927     * UTF-8 => ISO-8859-1
     928     *
     929     * @param string $string
     930     *
     931     * @return string
     932     */
    748933    public static function iconv_fallback_utf8_iso88591($string) {
    749934        if (function_exists('utf8_decode')) {
     
    755940        $stringlength = strlen($string);
    756941        while ($offset < $stringlength) {
    757             if ((ord($string{$offset}) | 0x07) == 0xF7) {
     942            if ((ord($string[$offset]) | 0x07) == 0xF7) {
    758943                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
    759                 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
    760                            ((ord($string{($offset + 1)}) & 0x3F) << 12) &
    761                            ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
    762                             (ord($string{($offset + 3)}) & 0x3F);
     944                $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
     945                           ((ord($string[($offset + 1)]) & 0x3F) << 12) &
     946                           ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
     947                            (ord($string[($offset + 3)]) & 0x3F);
    763948                $offset += 4;
    764             } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
     949            } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
    765950                // 1110bbbb 10bbbbbb 10bbbbbb
    766                 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
    767                            ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
    768                             (ord($string{($offset + 2)}) & 0x3F);
     951                $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
     952                           ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
     953                            (ord($string[($offset + 2)]) & 0x3F);
    769954                $offset += 3;
    770             } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
     955            } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
    771956                // 110bbbbb 10bbbbbb
    772                 $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
    773                             (ord($string{($offset + 1)}) & 0x3F);
     957                $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
     958                            (ord($string[($offset + 1)]) & 0x3F);
    774959                $offset += 2;
    775             } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
     960            } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
    776961                // 0bbbbbbb
    777                 $charval = ord($string{$offset});
     962                $charval = ord($string[$offset]);
    778963                $offset += 1;
    779964            } else {
     
    789974    }
    790975
    791     // UTF-8 => UTF-16BE
     976    /**
     977     * UTF-8 => UTF-16BE
     978     *
     979     * @param string $string
     980     * @param bool   $bom
     981     *
     982     * @return string
     983     */
    792984    public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
    793985        $newcharstring = '';
     
    798990        $stringlength = strlen($string);
    799991        while ($offset < $stringlength) {
    800             if ((ord($string{$offset}) | 0x07) == 0xF7) {
     992            if ((ord($string[$offset]) | 0x07) == 0xF7) {
    801993                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
    802                 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
    803                            ((ord($string{($offset + 1)}) & 0x3F) << 12) &
    804                            ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
    805                             (ord($string{($offset + 3)}) & 0x3F);
     994                $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
     995                           ((ord($string[($offset + 1)]) & 0x3F) << 12) &
     996                           ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
     997                            (ord($string[($offset + 3)]) & 0x3F);
    806998                $offset += 4;
    807             } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
     999            } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
    8081000                // 1110bbbb 10bbbbbb 10bbbbbb
    809                 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
    810                            ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
    811                             (ord($string{($offset + 2)}) & 0x3F);
     1001                $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
     1002                           ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
     1003                            (ord($string[($offset + 2)]) & 0x3F);
    8121004                $offset += 3;
    813             } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
     1005            } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
    8141006                // 110bbbbb 10bbbbbb
    815                 $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
    816                             (ord($string{($offset + 1)}) & 0x3F);
     1007                $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
     1008                            (ord($string[($offset + 1)]) & 0x3F);
    8171009                $offset += 2;
    818             } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
     1010            } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
    8191011                // 0bbbbbbb
    820                 $charval = ord($string{$offset});
     1012                $charval = ord($string[$offset]);
    8211013                $offset += 1;
    8221014            } else {
     
    8321024    }
    8331025
    834     // UTF-8 => UTF-16LE
     1026    /**
     1027     * UTF-8 => UTF-16LE
     1028     *
     1029     * @param string $string
     1030     * @param bool   $bom
     1031     *
     1032     * @return string
     1033     */
    8351034    public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
    8361035        $newcharstring = '';
     
    8411040        $stringlength = strlen($string);
    8421041        while ($offset < $stringlength) {
    843             if ((ord($string{$offset}) | 0x07) == 0xF7) {
     1042            if ((ord($string[$offset]) | 0x07) == 0xF7) {
    8441043                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
    845                 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
    846                            ((ord($string{($offset + 1)}) & 0x3F) << 12) &
    847                            ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
    848                             (ord($string{($offset + 3)}) & 0x3F);
     1044                $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
     1045                           ((ord($string[($offset + 1)]) & 0x3F) << 12) &
     1046                           ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
     1047                            (ord($string[($offset + 3)]) & 0x3F);
    8491048                $offset += 4;
    850             } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
     1049            } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
    8511050                // 1110bbbb 10bbbbbb 10bbbbbb
    852                 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
    853                            ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
    854                             (ord($string{($offset + 2)}) & 0x3F);
     1051                $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
     1052                           ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
     1053                            (ord($string[($offset + 2)]) & 0x3F);
    8551054                $offset += 3;
    856             } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
     1055            } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
    8571056                // 110bbbbb 10bbbbbb
    858                 $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
    859                             (ord($string{($offset + 1)}) & 0x3F);
     1057                $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
     1058                            (ord($string[($offset + 1)]) & 0x3F);
    8601059                $offset += 2;
    861             } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
     1060            } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
    8621061                // 0bbbbbbb
    863                 $charval = ord($string{$offset});
     1062                $charval = ord($string[$offset]);
    8641063                $offset += 1;
    8651064            } else {
     
    8751074    }
    8761075
    877     // UTF-8 => UTF-16LE (BOM)
     1076    /**
     1077     * UTF-8 => UTF-16LE (BOM)
     1078     *
     1079     * @param string $string
     1080     *
     1081     * @return string
     1082     */
    8781083    public static function iconv_fallback_utf8_utf16($string) {
    8791084        return self::iconv_fallback_utf8_utf16le($string, true);
    8801085    }
    8811086
    882     // UTF-16BE => UTF-8
     1087    /**
     1088     * UTF-16BE => UTF-8
     1089     *
     1090     * @param string $string
     1091     *
     1092     * @return string
     1093     */
    8831094    public static function iconv_fallback_utf16be_utf8($string) {
    8841095        if (substr($string, 0, 2) == "\xFE\xFF") {
     
    8941105    }
    8951106
    896     // UTF-16LE => UTF-8
     1107    /**
     1108     * UTF-16LE => UTF-8
     1109     *
     1110     * @param string $string
     1111     *
     1112     * @return string
     1113     */
    8971114    public static function iconv_fallback_utf16le_utf8($string) {
    8981115        if (substr($string, 0, 2) == "\xFF\xFE") {
     
    9081125    }
    9091126
    910     // UTF-16BE => ISO-8859-1
     1127    /**
     1128     * UTF-16BE => ISO-8859-1
     1129     *
     1130     * @param string $string
     1131     *
     1132     * @return string
     1133     */
    9111134    public static function iconv_fallback_utf16be_iso88591($string) {
    9121135        if (substr($string, 0, 2) == "\xFE\xFF") {
     
    9221145    }
    9231146
    924     // UTF-16LE => ISO-8859-1
     1147    /**
     1148     * UTF-16LE => ISO-8859-1
     1149     *
     1150     * @param string $string
     1151     *
     1152     * @return string
     1153     */
    9251154    public static function iconv_fallback_utf16le_iso88591($string) {
    9261155        if (substr($string, 0, 2) == "\xFF\xFE") {
     
    9361165    }
    9371166
    938     // UTF-16 (BOM) => ISO-8859-1
     1167    /**
     1168     * UTF-16 (BOM) => ISO-8859-1
     1169     *
     1170     * @param string $string
     1171     *
     1172     * @return string
     1173     */
    9391174    public static function iconv_fallback_utf16_iso88591($string) {
    9401175        $bom = substr($string, 0, 2);
     
    9471182    }
    9481183
    949     // UTF-16 (BOM) => UTF-8
     1184    /**
     1185     * UTF-16 (BOM) => UTF-8
     1186     *
     1187     * @param string $string
     1188     *
     1189     * @return string
     1190     */
    9501191    public static function iconv_fallback_utf16_utf8($string) {
    9511192        $bom = substr($string, 0, 2);
     
    9581199    }
    9591200
     1201    /**
     1202     * @param string $in_charset
     1203     * @param string $out_charset
     1204     * @param string $string
     1205     *
     1206     * @return string
     1207     * @throws Exception
     1208     */
    9601209    public static function iconv_fallback($in_charset, $out_charset, $string) {
    9611210
     
    9641213        }
    9651214
    966         // mb_convert_encoding() availble
     1215        // mb_convert_encoding() available
    9671216        if (function_exists('mb_convert_encoding')) {
     1217            if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) {
     1218                // if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM
     1219                $string = "\xFF\xFE".$string;
     1220            }
     1221            if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) {
     1222                if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) {
     1223                    // if string consists of only BOM, mb_convert_encoding will return the BOM unmodified
     1224                    return '';
     1225                }
     1226            }
    9681227            if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
    9691228                switch ($out_charset) {
     
    9751234            }
    9761235            return $string;
    977         }
    978         // iconv() availble
    979         else if (function_exists('iconv')) {
     1236
     1237        // iconv() available
     1238        } elseif (function_exists('iconv')) {
    9801239            if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
    9811240                switch ($out_charset) {
     
    10181277    }
    10191278
     1279    /**
     1280     * @param mixed  $data
     1281     * @param string $charset
     1282     *
     1283     * @return mixed
     1284     */
    10201285    public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
    10211286        if (is_string($data)) {
     
    10321297    }
    10331298
     1299    /**
     1300     * @param string|int|float $string
     1301     * @param string           $charset
     1302     *
     1303     * @return string
     1304     */
    10341305    public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
    10351306        $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
     
    10701341                $strlen = strlen($string);
    10711342                for ($i = 0; $i < $strlen; $i++) {
    1072                     $char_ord_val = ord($string{$i});
     1343                    $char_ord_val = ord($string[$i]);
    10731344                    $charval = 0;
    10741345                    if ($char_ord_val < 0x80) {
     
    10761347                    } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F  &&  $i+3 < $strlen) {
    10771348                        $charval  = (($char_ord_val & 0x07) << 18);
    1078                         $charval += ((ord($string{++$i}) & 0x3F) << 12);
    1079                         $charval += ((ord($string{++$i}) & 0x3F) << 6);
    1080                         $charval +=  (ord($string{++$i}) & 0x3F);
     1349                        $charval += ((ord($string[++$i]) & 0x3F) << 12);
     1350                        $charval += ((ord($string[++$i]) & 0x3F) << 6);
     1351                        $charval +=  (ord($string[++$i]) & 0x3F);
    10811352                    } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07  &&  $i+2 < $strlen) {
    10821353                        $charval  = (($char_ord_val & 0x0F) << 12);
    1083                         $charval += ((ord($string{++$i}) & 0x3F) << 6);
    1084                         $charval +=  (ord($string{++$i}) & 0x3F);
     1354                        $charval += ((ord($string[++$i]) & 0x3F) << 6);
     1355                        $charval +=  (ord($string[++$i]) & 0x3F);
    10851356                    } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03  &&  $i+1 < $strlen) {
    10861357                        $charval  = (($char_ord_val & 0x1F) << 6);
    1087                         $charval += (ord($string{++$i}) & 0x3F);
     1358                        $charval += (ord($string[++$i]) & 0x3F);
    10881359                    }
    10891360                    if (($charval >= 32) && ($charval <= 127)) {
     
    11241395    }
    11251396
    1126 
    1127 
     1397    /**
     1398     * @param int $namecode
     1399     *
     1400     * @return string
     1401     */
    11281402    public static function RGADnameLookup($namecode) {
    11291403        static $RGADname = array();
     
    11371411    }
    11381412
    1139 
     1413    /**
     1414     * @param int $originatorcode
     1415     *
     1416     * @return string
     1417     */
    11401418    public static function RGADoriginatorLookup($originatorcode) {
    11411419        static $RGADoriginator = array();
     
    11501428    }
    11511429
    1152 
     1430    /**
     1431     * @param int $rawadjustment
     1432     * @param int $signbit
     1433     *
     1434     * @return float
     1435     */
    11531436    public static function RGADadjustmentLookup($rawadjustment, $signbit) {
    1154         $adjustment = $rawadjustment / 10;
     1437        $adjustment = (float) $rawadjustment / 10;
    11551438        if ($signbit == 1) {
    11561439            $adjustment *= -1;
    11571440        }
    1158         return (float) $adjustment;
    1159     }
    1160 
    1161 
     1441        return $adjustment;
     1442    }
     1443
     1444    /**
     1445     * @param int $namecode
     1446     * @param int $originatorcode
     1447     * @param int $replaygain
     1448     *
     1449     * @return string
     1450     */
    11621451    public static function RGADgainString($namecode, $originatorcode, $replaygain) {
    11631452        if ($replaygain < 0) {
     
    11751464    }
    11761465
     1466    /**
     1467     * @param float $amplitude
     1468     *
     1469     * @return float
     1470     */
    11771471    public static function RGADamplitude2dB($amplitude) {
    11781472        return 20 * log10($amplitude);
    11791473    }
    11801474
    1181 
     1475    /**
     1476     * @param string $imgData
     1477     * @param array  $imageinfo
     1478     *
     1479     * @return array|false
     1480     */
    11821481    public static function GetDataImageSize($imgData, &$imageinfo=array()) {
    11831482        static $tempdir = '';
     
    12141513    }
    12151514
     1515    /**
     1516     * @param string $mime_type
     1517     *
     1518     * @return string
     1519     */
    12161520    public static function ImageExtFromMime($mime_type) {
    12171521        // temporary way, works OK for now, but should be reworked in the future
     
    12191523    }
    12201524
    1221     public static function ImageTypesLookup($imagetypeid) {
    1222         static $ImageTypesLookup = array();
    1223         if (empty($ImageTypesLookup)) {
    1224             $ImageTypesLookup[1]  = 'gif';
    1225             $ImageTypesLookup[2]  = 'jpeg';
    1226             $ImageTypesLookup[3]  = 'png';
    1227             $ImageTypesLookup[4]  = 'swf';
    1228             $ImageTypesLookup[5]  = 'psd';
    1229             $ImageTypesLookup[6]  = 'bmp';
    1230             $ImageTypesLookup[7]  = 'tiff (little-endian)';
    1231             $ImageTypesLookup[8]  = 'tiff (big-endian)';
    1232             $ImageTypesLookup[9]  = 'jpc';
    1233             $ImageTypesLookup[10] = 'jp2';
    1234             $ImageTypesLookup[11] = 'jpx';
    1235             $ImageTypesLookup[12] = 'jb2';
    1236             $ImageTypesLookup[13] = 'swc';
    1237             $ImageTypesLookup[14] = 'iff';
    1238         }
    1239         return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
    1240     }
    1241 
     1525    /**
     1526     * @param array $ThisFileInfo
     1527     *
     1528     * @return bool
     1529     */
    12421530    public static function CopyTagsToComments(&$ThisFileInfo) {
    12431531
     
    13271615    }
    13281616
    1329 
     1617    /**
     1618     * @param string $key
     1619     * @param int    $begin
     1620     * @param int    $end
     1621     * @param string $file
     1622     * @param string $name
     1623     *
     1624     * @return string
     1625     */
    13301626    public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
    13311627
     
    13741670    }
    13751671
     1672    /**
     1673     * @param string $filename
     1674     * @param string $sourcefile
     1675     * @param bool   $DieOnFailure
     1676     *
     1677     * @return bool
     1678     * @throws Exception
     1679     */
    13761680    public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
    13771681        global $GETID3_ERRORARRAY;
     
    13941698    }
    13951699
     1700    /**
     1701     * @param string $string
     1702     *
     1703     * @return string
     1704     */
    13961705    public static function trimNullByte($string) {
    13971706        return trim($string, "\x00");
    13981707    }
    13991708
     1709    /**
     1710     * @param string $path
     1711     *
     1712     * @return float|bool
     1713     */
    14001714    public static function getFileSizeSyscall($path) {
    14011715        $filesize = false;
     
    14221736    }
    14231737
    1424 
    1425     /**
    1426     * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
    1427     * @param string $path A path.
    1428     * @param string $suffix If the name component ends in suffix this will also be cut off.
    1429     * @return string
    1430     */
     1738    /**
     1739     * @param string $filename
     1740     *
     1741     * @return string|false
     1742     */
     1743    public static function truepath($filename) {
     1744        // 2017-11-08: this could use some improvement, patches welcome
     1745        if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) {
     1746            // PHP's built-in realpath function does not work on UNC Windows shares
     1747            $goodpath = array();
     1748            foreach (explode('/', str_replace('\\', '/', $filename)) as $part) {
     1749                if ($part == '.') {
     1750                    continue;
     1751                }
     1752                if ($part == '..') {
     1753                    if (count($goodpath)) {
     1754                        array_pop($goodpath);
     1755                    } else {
     1756                        // cannot step above this level, already at top level
     1757                        return false;
     1758                    }
     1759                } else {
     1760                    $goodpath[] = $part;
     1761                }
     1762            }
     1763            return implode(DIRECTORY_SEPARATOR, $goodpath);
     1764        }
     1765        return realpath($filename);
     1766    }
     1767
     1768    /**
     1769     * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
     1770     *
     1771     * @param string $path A path.
     1772     * @param string $suffix If the name component ends in suffix this will also be cut off.
     1773     *
     1774     * @return string
     1775     */
    14311776    public static function mb_basename($path, $suffix = null) {
    14321777        $splited = preg_split('#/#', rtrim($path, '/ '));
  • trunk/src/wp-includes/ID3/getid3.php

    r41196 r46112  
    22/////////////////////////////////////////////////////////////////
    33/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
     4//  available at https://github.com/JamesHeinrich/getID3       //
     5//            or https://www.getid3.org                        //
     6//            or http://getid3.sourceforge.net                 //
    87//                                                             //
    98// Please see readme.txt for more information                  //
     
    2625    define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
    2726}
     27
     28/*
     29https://www.getid3.org/phpBB3/viewtopic.php?t=2114
     30If you are running into a the problem where filenames with special characters are being handled
     31incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed,
     32and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line:
     33*/
     34//setlocale(LC_CTYPE, 'en_US.UTF-8');
    2835
    2936// attempt to define temp dir as something flexible but reliable
     
    7582class getID3
    7683{
    77     // public: Settings
    78     public $encoding        = 'UTF-8';        // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples:  ISO-8859-1  UTF-8  UTF-16  UTF-16BE
    79     public $encoding_id3v1  = 'ISO-8859-1';   // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
    80 
    81     // public: Optional tag checks - disable for speed.
    82     public $option_tag_id3v1         = true;  // Read and process ID3v1 tags
    83     public $option_tag_id3v2         = true;  // Read and process ID3v2 tags
    84     public $option_tag_lyrics3       = true;  // Read and process Lyrics3 tags
    85     public $option_tag_apetag        = true;  // Read and process APE tags
    86     public $option_tags_process      = true;  // Copy tags to root key 'tags' and encode to $this->encoding
    87     public $option_tags_html         = true;  // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
    88 
    89     // public: Optional tag/comment calucations
    90     public $option_extra_info        = true;  // Calculate additional info such as bitrate, channelmode etc
    91 
    92     // public: Optional handling of embedded attachments (e.g. images)
    93     public $option_save_attachments  = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
    94 
    95     // public: Optional calculations
    96     public $option_md5_data          = false; // Get MD5 sum of data part - slow
    97     public $option_md5_data_source   = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
    98     public $option_sha1_data         = false; // Get SHA1 sum of data part - slow
    99     public $option_max_2gb_check     = null;  // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX)
    100 
    101     // public: Read buffer size in bytes
     84    /*
     85     * Settings
     86     */
     87
     88    /**
     89     * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples:  ISO-8859-1  UTF-8  UTF-16  UTF-16BE
     90     *
     91     * @var string
     92     */
     93    public $encoding        = 'UTF-8';
     94
     95    /**
     96     * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
     97     *
     98     * @var string
     99     */
     100    public $encoding_id3v1  = 'ISO-8859-1';
     101
     102    /*
     103     * Optional tag checks - disable for speed.
     104     */
     105
     106    /**
     107     * Read and process ID3v1 tags
     108     *
     109     * @var bool
     110     */
     111    public $option_tag_id3v1         = true;
     112
     113    /**
     114     * Read and process ID3v2 tags
     115     *
     116     * @var bool
     117     */
     118    public $option_tag_id3v2         = true;
     119
     120    /**
     121     * Read and process Lyrics3 tags
     122     *
     123     * @var bool
     124     */
     125    public $option_tag_lyrics3       = true;
     126
     127    /**
     128     * Read and process APE tags
     129     *
     130     * @var bool
     131     */
     132    public $option_tag_apetag        = true;
     133
     134    /**
     135     * Copy tags to root key 'tags' and encode to $this->encoding
     136     *
     137     * @var bool
     138     */
     139    public $option_tags_process      = true;
     140
     141    /**
     142     * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
     143     *
     144     * @var bool
     145     */
     146    public $option_tags_html         = true;
     147
     148    /*
     149     * Optional tag/comment calculations
     150     */
     151
     152    /**
     153     * Calculate additional info such as bitrate, channelmode etc
     154     *
     155     * @var bool
     156     */
     157    public $option_extra_info        = true;
     158
     159    /*
     160     * Optional handling of embedded attachments (e.g. images)
     161     */
     162
     163    /**
     164     * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility
     165     *
     166     * @var bool|string
     167     */
     168    public $option_save_attachments  = true;
     169
     170    /*
     171     * Optional calculations
     172     */
     173
     174    /**
     175     * Get MD5 sum of data part - slow
     176     *
     177     * @var bool
     178     */
     179    public $option_md5_data          = false;
     180
     181    /**
     182     * Use MD5 of source file if availble - only FLAC and OptimFROG
     183     *
     184     * @var bool
     185     */
     186    public $option_md5_data_source   = false;
     187
     188    /**
     189     * Get SHA1 sum of data part - slow
     190     *
     191     * @var bool
     192     */
     193    public $option_sha1_data         = false;
     194
     195    /**
     196     * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on
     197     * PHP_INT_MAX)
     198     *
     199     * @var bool|null
     200     */
     201    public $option_max_2gb_check;
     202
     203    /**
     204     * Read buffer size in bytes
     205     *
     206     * @var int
     207     */
    102208    public $option_fread_buffer_size = 32768;
    103209
    104210    // Public variables
    105     public $filename;                         // Filename of file being analysed.
    106     public $fp;                               // Filepointer to file being analysed.
    107     public $info;                             // Result array.
     211
     212    /**
     213     * Filename of file being analysed.
     214     *
     215     * @var string
     216     */
     217    public $filename;
     218
     219    /**
     220     * Filepointer to file being analysed.
     221     *
     222     * @var resource
     223     */
     224    public $fp;
     225
     226    /**
     227     * Result array.
     228     *
     229     * @var array
     230     */
     231    public $info;
     232
     233    /**
     234     * @var string
     235     */
    108236    public $tempdir = GETID3_TEMP_DIR;
     237
     238    /**
     239     * @var int
     240     */
    109241    public $memory_limit = 0;
    110242
    111     // Protected variables
     243    /**
     244     * @var string
     245     */
    112246    protected $startup_error   = '';
     247
     248    /**
     249     * @var string
     250     */
    113251    protected $startup_warning = '';
    114252
    115     const VERSION           = '1.9.14-201706111222';
     253    const VERSION           = '1.9.17-201907240906';
    116254    const FREAD_BUFFER_SIZE = 32768;
    117255
     
    119257    const ATTACHMENTS_INLINE = true;
    120258
    121     // public: constructor
    122259    public function __construct() {
     260
     261        // Check for PHP version
     262        $required_php_version = '5.3.0';
     263        if (version_compare(PHP_VERSION, $required_php_version, '<')) {
     264            $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n";
     265            return;
     266        }
    123267
    124268        // Check memory
     
    177321        // Needed for Windows only:
    178322        // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
    179         //   as well as other helper functions such as head, tail, md5sum, etc
     323        //   as well as other helper functions such as head, etc
    180324        // This path cannot contain spaces, but the below code will attempt to get the
    181325        //   8.3-equivalent path automatically
     
    220364            throw new getid3_exception($this->startup_error);
    221365        }
    222 
    223         return true;
    224     }
    225 
     366    }
     367
     368    /**
     369     * @return string
     370     */
    226371    public function version() {
    227372        return self::VERSION;
    228373    }
    229374
     375    /**
     376     * @return int
     377     */
    230378    public function fread_buffer_size() {
    231379        return $this->option_fread_buffer_size;
    232380    }
    233381
    234 
    235     // public: setOption
     382    /**
     383     * @param array $optArray
     384     *
     385     * @return bool
     386     */
    236387    public function setOption($optArray) {
    237388        if (!is_array($optArray) || empty($optArray)) {
     
    247398    }
    248399
    249 
    250     public function openfile($filename, $filesize=null) {
     400    /**
     401     * @param string $filename
     402     * @param int    $filesize
     403     *
     404     * @return bool
     405     *
     406     * @throws getid3_exception
     407     */
     408    public function openfile($filename, $filesize=null, $fp=null) {
    251409        try {
    252410            if (!empty($this->startup_error)) {
     
    271429
    272430            $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
    273             $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
     431            //$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
    274432
    275433            // open local file
    276             //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
    277             if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
     434            //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720
     435            if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) {
     436                $this->fp = $fp;
     437            } elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
    278438                // great
    279439            } else {
     
    332492                            unset($this->info['filesize']);
    333493                            fclose($this->fp);
    334                             throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org');
     494                            throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org');
    335495                        }
    336496                        $this->info['filesize'] = $real_filesize;
    337                         $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.');
     497                        $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.');
    338498                }
    339499            }
     
    347507    }
    348508
    349     // public: analyze file
    350     public function analyze($filename, $filesize=null, $original_filename='') {
     509    /**
     510     * analyze file
     511     *
     512     * @param string $filename
     513     * @param int    $filesize
     514     * @param string $original_filename
     515     *
     516     * @return array
     517     */
     518    public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
    351519        try {
    352             if (!$this->openfile($filename, $filesize)) {
     520            if (!$this->openfile($filename, $filesize, $fp)) {
    353521                return $this->info;
    354522            }
     
    384552                if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
    385553                    $this->info['id3v2']['header']        = true;
    386                     $this->info['id3v2']['majorversion']  = ord($header{3});
    387                     $this->info['id3v2']['minorversion']  = ord($header{4});
     554                    $this->info['id3v2']['majorversion']  = ord($header[3]);
     555                    $this->info['id3v2']['minorversion']  = ord($header[4]);
    388556                    $this->info['avdataoffset']          += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
    389557                }
     
    498666
    499667
    500     // private: error handling
     668    /**
     669     * Error handling.
     670     *
     671     * @param string $message
     672     *
     673     * @return array
     674     */
    501675    public function error($message) {
    502676        $this->CleanUp();
     
    509683
    510684
    511     // private: warning handling
     685    /**
     686     * Warning handling.
     687     *
     688     * @param string $message
     689     *
     690     * @return bool
     691     */
    512692    public function warning($message) {
    513693        $this->info['warning'][] = $message;
     
    516696
    517697
    518     // private: CleanUp
     698    /**
     699     * @return bool
     700     */
    519701    private function CleanUp() {
    520702
     
    563745    }
    564746
    565 
    566     // return array containing information about all supported formats
     747    /**
     748     * Return array containing information about all supported formats.
     749     *
     750     * @return array
     751     */
    567752    public function GetFileFormatArray() {
    568753        static $format_info = array();
     
    585770                            'group'     => 'audio',
    586771                            'module'    => 'aac',
    587                             'mime_type' => 'application/octet-stream',
     772                            'mime_type' => 'audio/aac',
    588773                            'fail_ape'  => 'WARNING',
    589774                        ),
     
    603788                            'group'     => 'audio',
    604789                            'module'    => 'aac',
    605                             'mime_type' => 'application/octet-stream',
     790                            'mime_type' => 'audio/aac',
    606791                            'fail_ape'  => 'WARNING',
    607792                        ),
     
    650835                // DSS  - audio       - Digital Speech Standard
    651836                'dss'  => array(
    652                             'pattern'   => '^[\\x02-\\x06]ds[s2]',
     837                            'pattern'   => '^[\\x02-\\x08]ds[s2]',
    653838                            'group'     => 'audio',
    654839                            'module'    => 'dss',
     
    669854                            'group'     => 'audio',
    670855                            'module'    => 'flac',
    671                             'mime_type' => 'audio/x-flac',
     856                            'mime_type' => 'audio/flac',
    672857                        ),
    673858
     
    701886                            'group'     => 'audio',
    702887                            'module'    => 'monkey',
    703                             'mime_type' => 'application/octet-stream',
     888                            'mime_type' => 'audio/x-monkeys-audio',
    704889                        ),
    705890
     
    8901075                            'group'     => 'audio-video',
    8911076                            'module'    => 'riff',
    892                             'mime_type' => 'audio/x-wav',
     1077                            'mime_type' => 'audio/wav',
    8931078                            'fail_ape'  => 'WARNING',
    8941079                        ),
     
    10541239                            'group'     => 'archive',
    10551240                            'module'    => 'gzip',
    1056                             'mime_type' => 'application/x-gzip',
     1241                            'mime_type' => 'application/gzip',
    10571242                            'fail_id3'  => 'ERROR',
    10581243                            'fail_ape'  => 'ERROR',
     
    10691254                        ),
    10701255
     1256                // XZ   - data         - XZ compressed data
     1257                'xz'  => array(
     1258                            'pattern'   => '^\\xFD7zXZ\\x00',
     1259                            'group'     => 'archive',
     1260                            'module'    => 'xz',
     1261                            'mime_type' => 'application/x-xz',
     1262                            'fail_id3'  => 'ERROR',
     1263                            'fail_ape'  => 'ERROR',
     1264                        ),
     1265
    10711266
    10721267                // Misc other formats
     
    11161311    }
    11171312
    1118 
    1119 
     1313    /**
     1314     * @param string $filedata
     1315     * @param string $filename
     1316     *
     1317     * @return mixed|false
     1318     */
    11201319    public function GetFileFormat(&$filedata, $filename='') {
    11211320        // this function will determine the format of a file based on usually
     
    11361335
    11371336        if (preg_match('#\\.mp[123a]$#i', $filename)) {
    1138             // Too many mp3 encoders on the market put gabage in front of mpeg files
     1337            // Too many mp3 encoders on the market put garbage in front of mpeg files
    11391338            // use assume format on these if format detection failed
    11401339            $GetFileFormatArray = $this->GetFileFormatArray();
     
    11551354    }
    11561355
    1157 
    1158     // converts array to $encoding charset from $this->encoding
     1356    /**
     1357     * Converts array to $encoding charset from $this->encoding.
     1358     *
     1359     * @param array  $array
     1360     * @param string $encoding
     1361     */
    11591362    public function CharConvert(&$array, $encoding) {
    11601363
     
    11791382    }
    11801383
    1181 
     1384    /**
     1385     * @return bool
     1386     */
    11821387    public function HandleAllTags() {
    11831388
     
    12341439                    }
    12351440                    if ($tag_key == 'picture') {
     1441                        // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
    12361442                        unset($this->info[$comment_name]['comments'][$tag_key]);
    12371443                    }
     
    12471453                if ($this->option_tags_html) {
    12481454                    foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
     1455                        if ($tag_key == 'picture') {
     1456                            // Do not to try to convert binary picture data to HTML
     1457                            // https://github.com/JamesHeinrich/getID3/issues/178
     1458                            continue;
     1459                        }
    12491460                        $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
    12501461                    }
     
    12551466        }
    12561467
    1257         // pictures can take up a lot of space, and we don't need multiple copies of them
    1258         // let there be a single copy in [comments][picture], and not elsewhere
     1468        // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
    12591469        if (!empty($this->info['tags'])) {
    12601470            $unset_keys = array('tags', 'tags_html');
     
    13021512    }
    13031513
     1514    /**
     1515     * @param string $algorithm
     1516     *
     1517     * @return array|bool
     1518     */
    13041519    public function getHashdata($algorithm) {
    13051520        switch ($algorithm) {
     
    13661581                } else {
    13671582
    1368                     $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
    13691583                    $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
    13701584                    $VorbisCommentError = `$commandline`;
     
    14241638        return true;
    14251639    }
    1426 
    14271640
    14281641    public function ChannelsBitratePlaytimeCalculations() {
     
    14901703    }
    14911704
    1492 
     1705    /**
     1706     * @return bool
     1707     */
    14931708    public function CalculateCompressionRatioVideo() {
    14941709        if (empty($this->info['video'])) {
     
    15381753    }
    15391754
    1540 
     1755    /**
     1756     * @return bool
     1757     */
    15411758    public function CalculateCompressionRatioAudio() {
    15421759        if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
     
    15551772    }
    15561773
    1557 
     1774    /**
     1775     * @return bool
     1776     */
    15581777    public function CalculateReplayGain() {
    15591778        if (isset($this->info['replay_gain'])) {
    15601779            if (!isset($this->info['replay_gain']['reference_volume'])) {
    1561                 $this->info['replay_gain']['reference_volume'] = (double) 89.0;
     1780                $this->info['replay_gain']['reference_volume'] = 89.0;
    15621781            }
    15631782            if (isset($this->info['replay_gain']['track']['adjustment'])) {
     
    15781797    }
    15791798
     1799    /**
     1800     * @return bool
     1801     */
    15801802    public function ProcessAudioStreams() {
    15811803        if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
     
    15911813    }
    15921814
     1815    /**
     1816     * @return string|bool
     1817     */
    15931818    public function getid3_tempnam() {
    15941819        return tempnam($this->tempdir, 'gI3');
    15951820    }
    15961821
     1822    /**
     1823     * @param string $name
     1824     *
     1825     * @return bool
     1826     *
     1827     * @throws getid3_exception
     1828     */
    15971829    public function include_module($name) {
    15981830        //if (!file_exists($this->include_path.'module.'.$name.'.php')) {
     
    16041836    }
    16051837
    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     }
     1838    /**
     1839     * @param string $filename
     1840     *
     1841     * @return bool
     1842     */
     1843    public static function is_writable ($filename) {
     1844        $ret = is_writable($filename);
     1845        if (!$ret) {
     1846            $perms = fileperms($filename);
     1847            $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
     1848        }
     1849        return $ret;
     1850    }
    16161851
    16171852}
    16181853
    16191854
    1620 abstract class getid3_handler {
     1855abstract class getid3_handler
     1856{
    16211857
    16221858    /**
     
    16251861    protected $getid3;                       // pointer
    16261862
    1627     protected $data_string_flag     = false; // analyzing filepointer or string
    1628     protected $data_string          = '';    // string to analyze
    1629     protected $data_string_position = 0;     // seek position in string
    1630     protected $data_string_length   = 0;     // string length
    1631 
    1632     private $dependency_to = null;
    1633 
    1634 
     1863    /**
     1864     * Analyzing filepointer or string.
     1865     *
     1866     * @var bool
     1867     */
     1868    protected $data_string_flag     = false;
     1869
     1870    /**
     1871     * String to analyze.
     1872     *
     1873     * @var string
     1874     */
     1875    protected $data_string          = '';
     1876
     1877    /**
     1878     * Seek position in string.
     1879     *
     1880     * @var int
     1881     */
     1882    protected $data_string_position = 0;
     1883
     1884    /**
     1885     * String length.
     1886     *
     1887     * @var int
     1888     */
     1889    protected $data_string_length   = 0;
     1890
     1891    /**
     1892     * @var string
     1893     */
     1894    private $dependency_to;
     1895
     1896    /**
     1897     * getid3_handler constructor.
     1898     *
     1899     * @param getID3 $getid3
     1900     * @param string $call_module
     1901     */
    16351902    public function __construct(getID3 $getid3, $call_module=null) {
    16361903        $this->getid3 = $getid3;
     
    16411908    }
    16421909
    1643 
    1644     // Analyze from file pointer
     1910    /**
     1911     * Analyze from file pointer.
     1912     *
     1913     * @return bool
     1914     */
    16451915    abstract public function Analyze();
    16461916
    1647 
    1648     // Analyze from string instead
     1917    /**
     1918     * Analyze from string instead.
     1919     *
     1920     * @param string $string
     1921     */
    16491922    public function AnalyzeString($string) {
    16501923        // Enter string mode
     
    16721945    }
    16731946
     1947    /**
     1948     * @param string $string
     1949     */
    16741950    public function setStringMode($string) {
    16751951        $this->data_string_flag   = true;
     
    16781954    }
    16791955
     1956    /**
     1957     * @return int|bool
     1958     */
    16801959    protected function ftell() {
    16811960        if ($this->data_string_flag) {
     
    16851964    }
    16861965
     1966    /**
     1967     * @param int $bytes
     1968     *
     1969     * @return string|false
     1970     *
     1971     * @throws getid3_exception
     1972     */
    16871973    protected function fread($bytes) {
    16881974        if ($this->data_string_flag) {
     
    16971983        //return fread($this->getid3->fp, $bytes);
    16981984        /*
    1699         * http://www.getid3.org/phpBB3/viewtopic.php?t=1930
     1985        * https://www.getid3.org/phpBB3/viewtopic.php?t=1930
    17001986        * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
    17011987        * It seems to assume that fread() would always return as many bytes as were requested.
     
    17051991        $contents = '';
    17061992        do {
     1993            //if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
     1994            if (($this->getid3->memory_limit > 0) && (($bytes / $this->getid3->memory_limit) > 0.99)) { // enable a more-fuzzy match to prevent close misses generating errors like "PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554464 bytes)"
     1995                throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10);
     1996            }
    17071997            $part = fread($this->getid3->fp, $bytes);
    17081998            $partLength  = strlen($part);
     
    17132003    }
    17142004
     2005    /**
     2006     * @param int $bytes
     2007     * @param int $whence
     2008     *
     2009     * @return int
     2010     *
     2011     * @throws getid3_exception
     2012     */
    17152013    protected function fseek($bytes, $whence=SEEK_SET) {
    17162014        if ($this->data_string_flag) {
     
    17432041    }
    17442042
     2043    /**
     2044     * @return bool
     2045     */
    17452046    protected function feof() {
    17462047        if ($this->data_string_flag) {
     
    17502051    }
    17512052
     2053    /**
     2054     * @param string $module
     2055     *
     2056     * @return bool
     2057     */
    17522058    final protected function isDependencyFor($module) {
    17532059        return $this->dependency_to == $module;
    17542060    }
    17552061
     2062    /**
     2063     * @param string $text
     2064     *
     2065     * @return bool
     2066     */
    17562067    protected function error($text) {
    17572068        $this->getid3->info['error'][] = $text;
     
    17602071    }
    17612072
     2073    /**
     2074     * @param string $text
     2075     *
     2076     * @return bool
     2077     */
    17622078    protected function warning($text) {
    17632079        return $this->getid3->warning($text);
    17642080    }
    17652081
     2082    /**
     2083     * @param string $text
     2084     */
    17662085    protected function notice($text) {
    17672086        // does nothing for now
    17682087    }
    17692088
     2089    /**
     2090     * @param string $name
     2091     * @param int    $offset
     2092     * @param int    $length
     2093     * @param string $image_mime
     2094     *
     2095     * @return string|null
     2096     *
     2097     * @throws Exception
     2098     * @throws getid3_exception
     2099     */
    17702100    public function saveAttachment($name, $offset, $length, $image_mime=null) {
    17712101        try {
     
    18212151            if (isset($fp_dest) && is_resource($fp_dest)) {
    18222152                fclose($fp_dest);
     2153            }
     2154
     2155            if (isset($dest) && file_exists($dest)) {
    18232156                unlink($dest);
    18242157            }
  • trunk/src/wp-includes/ID3/license.txt

    r32979 r46112  
    22/// getID3() by James Heinrich <info@getid3.org>               //
    33//  available at http://getid3.sourceforge.net                 //
    4 //            or http://www.getid3.org                         //
     4//            or https://www.getid3.org                        //
    55//          also https://github.com/JamesHeinrich/getID3       //
    66/////////////////////////////////////////////////////////////////
     
    1919GNU LGPL: https://gnu.org/licenses/lgpl.html                 (v3)
    2020
    21 Mozilla MPL: http://www.mozilla.org/MPL/2.0/                 (v2)
     21Mozilla MPL: https://www.mozilla.org/MPL/2.0/                (v2)
    2222
    23 getID3 Commercial License: http://getid3.org/#gCL (payment required)
     23getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
    2424
    2525*****************************************************************
  • trunk/src/wp-includes/ID3/module.audio-video.asf.php

    r41196 r46112  
    22/////////////////////////////////////////////////////////////////
    33/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
    8 // See readme.txt for more details                             //
     4//  available at https://github.com/JamesHeinrich/getID3       //
     5//            or https://www.getid3.org                        //
     6//            or http://getid3.sourceforge.net                 //
     7//  see readme.txt for more details                            //
    98/////////////////////////////////////////////////////////////////
    109//                                                             //
     
    1716getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
    1817
    19 class getid3_asf extends getid3_handler {
    20 
     18class getid3_asf extends getid3_handler
     19{
     20    /**
     21     * @param getID3 $getid3
     22     */
    2123    public function __construct(getID3 $getid3) {
    2224        parent::__construct($getid3);  // extends getid3_handler::__construct()
     
    3133    }
    3234
     35    /**
     36     * @return bool
     37     */
    3338    public function Analyze() {
    3439        $info = &$this->getid3->info;
     
    8489        $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
    8590        $offset = 0;
     91        $thisfile_asf_streambitratepropertiesobject = array();
     92        $thisfile_asf_codeclistobject = array();
    8693
    8794        for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
     
    791798                            case 'tracknumber':
    792799                                // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
    793                                 $thisfile_asf_comments['track'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
    794                                 foreach ($thisfile_asf_comments['track'] as $key => $value) {
     800                                $thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
     801                                foreach ($thisfile_asf_comments['track_number'] as $key => $value) {
    795802                                    if (preg_match('/^[0-9\x00]+$/', $value)) {
    796                                         $thisfile_asf_comments['track'][$key] = intval(str_replace("\x00", '', $value));
     803                                        $thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value));
    797804                                    }
    798805                                }
     
    800807
    801808                            case 'wm/track':
    802                                 if (empty($thisfile_asf_comments['track'])) {
    803                                     $thisfile_asf_comments['track'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
     809                                if (empty($thisfile_asf_comments['track_number'])) {
     810                                    $thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
    804811                                }
    805812                                break;
     
    971978            }
    972979        }
    973         if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) {
     980        if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) {
    974981            $ASFbitrateAudio = 0;
    975982            $ASFbitrateVideo = 0;
    976             for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) {
     983            for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
    977984                if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
    978985                    switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
    979986                        case 1:
    980                             $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
     987                            $ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
    981988                            break;
    982989
    983990                        case 2:
    984                             $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
     991                            $ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
    985992                            break;
    986993
     
    14411448    }
    14421449
     1450    /**
     1451     * @param int $CodecListType
     1452     *
     1453     * @return string
     1454     */
    14431455    public static function codecListObjectTypeLookup($CodecListType) {
    14441456        static $lookup = array(
     
    14511463    }
    14521464
     1465    /**
     1466     * @return array
     1467     */
    14531468    public static function KnownGUIDs() {
    14541469        static $GUIDarray = array(
     
    15651580    }
    15661581
     1582    /**
     1583     * @param string $GUIDstring
     1584     *
     1585     * @return string|false
     1586     */
    15671587    public static function GUIDname($GUIDstring) {
    15681588        static $GUIDarray = array();
     
    15731593    }
    15741594
     1595    /**
     1596     * @param int $id
     1597     *
     1598     * @return string
     1599     */
    15751600    public static function ASFIndexObjectIndexTypeLookup($id) {
    15761601        static $ASFIndexObjectIndexTypeLookup = array();
     
    15831608    }
    15841609
     1610    /**
     1611     * @param string $GUIDstring
     1612     *
     1613     * @return string
     1614     */
    15851615    public static function GUIDtoBytestring($GUIDstring) {
    15861616        // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
     
    16181648    }
    16191649
     1650    /**
     1651     * @param string $Bytestring
     1652     *
     1653     * @return string
     1654     */
    16201655    public static function BytestringToGUID($Bytestring) {
    1621         $GUIDstring  = str_pad(dechex(ord($Bytestring{3})),  2, '0', STR_PAD_LEFT);
    1622         $GUIDstring .= str_pad(dechex(ord($Bytestring{2})),  2, '0', STR_PAD_LEFT);
    1623         $GUIDstring .= str_pad(dechex(ord($Bytestring{1})),  2, '0', STR_PAD_LEFT);
    1624         $GUIDstring .= str_pad(dechex(ord($Bytestring{0})),  2, '0', STR_PAD_LEFT);
     1656        $GUIDstring  = str_pad(dechex(ord($Bytestring[3])),  2, '0', STR_PAD_LEFT);
     1657        $GUIDstring .= str_pad(dechex(ord($Bytestring[2])),  2, '0', STR_PAD_LEFT);
     1658        $GUIDstring .= str_pad(dechex(ord($Bytestring[1])),  2, '0', STR_PAD_LEFT);
     1659        $GUIDstring .= str_pad(dechex(ord($Bytestring[0])),  2, '0', STR_PAD_LEFT);
    16251660        $GUIDstring .= '-';
    1626         $GUIDstring .= str_pad(dechex(ord($Bytestring{5})),  2, '0', STR_PAD_LEFT);
    1627         $GUIDstring .= str_pad(dechex(ord($Bytestring{4})),  2, '0', STR_PAD_LEFT);
     1661        $GUIDstring .= str_pad(dechex(ord($Bytestring[5])),  2, '0', STR_PAD_LEFT);
     1662        $GUIDstring .= str_pad(dechex(ord($Bytestring[4])),  2, '0', STR_PAD_LEFT);
    16281663        $GUIDstring .= '-';
    1629         $GUIDstring .= str_pad(dechex(ord($Bytestring{7})),  2, '0', STR_PAD_LEFT);
    1630         $GUIDstring .= str_pad(dechex(ord($Bytestring{6})),  2, '0', STR_PAD_LEFT);
     1664        $GUIDstring .= str_pad(dechex(ord($Bytestring[7])),  2, '0', STR_PAD_LEFT);
     1665        $GUIDstring .= str_pad(dechex(ord($Bytestring[6])),  2, '0', STR_PAD_LEFT);
    16311666        $GUIDstring .= '-';
    1632         $GUIDstring .= str_pad(dechex(ord($Bytestring{8})),  2, '0', STR_PAD_LEFT);
    1633         $GUIDstring .= str_pad(dechex(ord($Bytestring{9})),  2, '0', STR_PAD_LEFT);
     1667        $GUIDstring .= str_pad(dechex(ord($Bytestring[8])),  2, '0', STR_PAD_LEFT);
     1668        $GUIDstring .= str_pad(dechex(ord($Bytestring[9])),  2, '0', STR_PAD_LEFT);
    16341669        $GUIDstring .= '-';
    1635         $GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT);
    1636         $GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT);
    1637         $GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT);
    1638         $GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT);
    1639         $GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT);
    1640         $GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT);
     1670        $GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
     1671        $GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
     1672        $GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
     1673        $GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
     1674        $GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
     1675        $GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
    16411676
    16421677        return strtoupper($GUIDstring);
    16431678    }
    16441679
     1680    /**
     1681     * @param int  $FILETIME
     1682     * @param bool $round
     1683     *
     1684     * @return float|int
     1685     */
    16451686    public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
    16461687        // FILETIME is a 64-bit unsigned integer representing
     
    16541695    }
    16551696
     1697    /**
     1698     * @param int $WMpictureType
     1699     *
     1700     * @return string
     1701     */
    16561702    public static function WMpictureTypeLookup($WMpictureType) {
    16571703        static $lookup = null;
     
    16851731    }
    16861732
     1733    /**
     1734     * @param string $asf_header_extension_object_data
     1735     * @param int    $unhandled_sections
     1736     *
     1737     * @return array
     1738     */
    16871739    public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
    16881740        // http://msdn.microsoft.com/en-us/library/bb643323.aspx
     
    19311983    }
    19321984
    1933 
     1985    /**
     1986     * @param int $id
     1987     *
     1988     * @return string
     1989     */
    19341990    public static function metadataLibraryObjectDataTypeLookup($id) {
    19351991        static $lookup = array(
     
    19452001    }
    19462002
     2003    /**
     2004     * @param string $data
     2005     *
     2006     * @return array
     2007     */
    19472008    public function ASF_WMpicture(&$data) {
    19482009        //typedef struct _WMPicture{
     
    19952056    }
    19962057
    1997 
    1998     // Remove terminator 00 00 and convert UTF-16LE to Latin-1
     2058    /**
     2059     * Remove terminator 00 00 and convert UTF-16LE to Latin-1.
     2060     *
     2061     * @param string $string
     2062     *
     2063     * @return string
     2064     */
    19992065    public static function TrimConvert($string) {
    20002066        return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
    20012067    }
    20022068
    2003 
    2004     // Remove terminator 00 00
     2069    /**
     2070     * Remove terminator 00 00.
     2071     *
     2072     * @param string $string
     2073     *
     2074     * @return string
     2075     */
    20052076    public static function TrimTerm($string) {
    20062077        // remove terminator, only if present (it should be, but...)
  • trunk/src/wp-includes/ID3/module.audio-video.flv.php

    r41196 r46112  
    22/////////////////////////////////////////////////////////////////
    33/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
     4//  available at https://github.com/JamesHeinrich/getID3       //
     5//            or https://www.getid3.org                        //
     6//            or http://getid3.sourceforge.net                 //
     7//  see readme.txt for more details                            //
     8/////////////////////////////////////////////////////////////////
     9//                                                             //
     10// module.audio-video.flv.php                                  //
     11// module for analyzing Shockwave Flash Video files            //
     12// dependencies: NONE                                          //
     13//                                                             //
     14/////////////////////////////////////////////////////////////////
    715//                                                             //
    816//  FLV module by Seth Kaufman <sethØwhirl-i-gig*com>          //
    917//                                                             //
    1018//  * version 0.1 (26 June 2005)                               //
    11 //                                                             //
    1219//                                                             //
    1320//  * version 0.1.1 (15 July 2005)                             //
     
    4451//  improved AVCSequenceParameterSetReader::readData()         //
    4552//    by Xander Schouwerwou <schouwerwouØgmail*com>            //
    46 //                                                             //
    47 /////////////////////////////////////////////////////////////////
    48 //                                                             //
    49 // module.audio-video.flv.php                                  //
    50 // module for analyzing Shockwave Flash Video files            //
    51 // dependencies: NONE                                          //
    5253//                                                            ///
    5354/////////////////////////////////////////////////////////////////
     
    7475define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
    7576
    76 class getid3_flv extends getid3_handler {
    77 
     77class getid3_flv extends getid3_handler
     78{
    7879    const magic = 'FLV';
    7980
    80     public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration
    81 
     81    /**
     82     * Break out of the loop if too many frames have been scanned; only scan this
     83     * many if meta frame does not contain useful duration.
     84     *
     85     * @var int
     86     */
     87    public $max_frames = 100000;
     88
     89    /**
     90     * @return bool
     91     */
    8292    public function Analyze() {
    8393        $info = &$this->getid3->info;
     
    333343    }
    334344
    335 
     345    /**
     346     * @param int $id
     347     *
     348     * @return string|false
     349     */
    336350    public static function audioFormatLookup($id) {
    337351        static $lookup = array(
     
    356370    }
    357371
     372    /**
     373     * @param int $id
     374     *
     375     * @return int|false
     376     */
    358377    public static function audioRateLookup($id) {
    359378        static $lookup = array(
     
    366385    }
    367386
     387    /**
     388     * @param int $id
     389     *
     390     * @return int|false
     391     */
    368392    public static function audioBitDepthLookup($id) {
    369393        static $lookup = array(
     
    374398    }
    375399
     400    /**
     401     * @param int $id
     402     *
     403     * @return string|false
     404     */
    376405    public static function videoCodecLookup($id) {
    377406        static $lookup = array(
     
    387416}
    388417
    389 class AMFStream {
     418class AMFStream
     419{
     420    /**
     421     * @var string
     422     */
    390423    public $bytes;
     424
     425    /**
     426     * @var int
     427     */
    391428    public $pos;
    392429
     430    /**
     431     * @param string $bytes
     432     */
    393433    public function __construct(&$bytes) {
    394434        $this->bytes =& $bytes;
     
    396436    }
    397437
    398     public function readByte() {
    399         return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
    400     }
    401 
    402     public function readInt() {
     438    /**
     439     * @return int
     440     */
     441    public function readByte() { //  8-bit
     442        return ord(substr($this->bytes, $this->pos++, 1));
     443    }
     444
     445    /**
     446     * @return int
     447     */
     448    public function readInt() { // 16-bit
    403449        return ($this->readByte() << 8) + $this->readByte();
    404450    }
    405451
    406     public function readLong() {
     452    /**
     453     * @return int
     454     */
     455    public function readLong() { // 32-bit
    407456        return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
    408457    }
    409458
     459    /**
     460     * @return float|false
     461     */
    410462    public function readDouble() {
    411463        return getid3_lib::BigEndian2Float($this->read(8));
    412464    }
    413465
     466    /**
     467     * @return string
     468     */
    414469    public function readUTF() {
    415470        $length = $this->readInt();
     
    417472    }
    418473
     474    /**
     475     * @return string
     476     */
    419477    public function readLongUTF() {
    420478        $length = $this->readLong();
     
    422480    }
    423481
     482    /**
     483     * @param int $length
     484     *
     485     * @return string
     486     */
    424487    public function read($length) {
    425488        $val = substr($this->bytes, $this->pos, $length);
     
    428491    }
    429492
     493    /**
     494     * @return int
     495     */
    430496    public function peekByte() {
    431497        $pos = $this->pos;
     
    435501    }
    436502
     503    /**
     504     * @return int
     505     */
    437506    public function peekInt() {
    438507        $pos = $this->pos;
     
    442511    }
    443512
     513    /**
     514     * @return int
     515     */
    444516    public function peekLong() {
    445517        $pos = $this->pos;
     
    449521    }
    450522
     523    /**
     524     * @return float|false
     525     */
    451526    public function peekDouble() {
    452527        $pos = $this->pos;
     
    456531    }
    457532
     533    /**
     534     * @return string
     535     */
    458536    public function peekUTF() {
    459537        $pos = $this->pos;
     
    463541    }
    464542
     543    /**
     544     * @return string
     545     */
    465546    public function peekLongUTF() {
    466547        $pos = $this->pos;
     
    471552}
    472553
    473 class AMFReader {
     554class AMFReader
     555{
     556    /**
     557    * @var AMFStream
     558    */
    474559    public $stream;
    475560
    476     public function __construct(&$stream) {
    477         $this->stream =& $stream;
    478     }
    479 
     561    /**
     562     * @param AMFStream $stream
     563     */
     564    public function __construct(AMFStream $stream) {
     565        $this->stream = $stream;
     566    }
     567
     568    /**
     569     * @return mixed
     570     */
    480571    public function readData() {
    481572        $value = null;
     
    548639    }
    549640
     641    /**
     642     * @return float|false
     643     */
    550644    public function readDouble() {
    551645        return $this->stream->readDouble();
    552646    }
    553647
     648    /**
     649     * @return bool
     650     */
    554651    public function readBoolean() {
    555652        return $this->stream->readByte() == 1;
    556653    }
    557654
     655    /**
     656     * @return string
     657     */
    558658    public function readString() {
    559659        return $this->stream->readUTF();
    560660    }
    561661
     662    /**
     663     * @return array
     664     */
    562665    public function readObject() {
    563666        // Get highest numerical index - ignored
     
    565668
    566669        $data = array();
     670        $key = null;
    567671
    568672        while ($key = $this->stream->readUTF()) {
     
    577681    }
    578682
     683    /**
     684     * @return array
     685     */
    579686    public function readMixedArray() {
    580687        // Get highest numerical index - ignored
     
    582689
    583690        $data = array();
     691        $key = null;
    584692
    585693        while ($key = $this->stream->readUTF()) {
    586694            if (is_numeric($key)) {
    587                 $key = (float) $key;
     695                $key = (int) $key;
    588696            }
    589697            $data[$key] = $this->readData();
     
    598706    }
    599707
     708    /**
     709     * @return array
     710     */
    600711    public function readArray() {
    601712        $length = $this->stream->readLong();
     
    608719    }
    609720
     721    /**
     722     * @return float|false
     723     */
    610724    public function readDate() {
    611725        $timestamp = $this->stream->readDouble();
     
    614728    }
    615729
     730    /**
     731     * @return string
     732     */
    616733    public function readLongString() {
    617734        return $this->stream->readLongUTF();
    618735    }
    619736
     737    /**
     738     * @return string
     739     */
    620740    public function readXML() {
    621741        return $this->stream->readLongUTF();
    622742    }
    623743
     744    /**
     745     * @return array
     746     */
    624747    public function readTypedObject() {
    625748        $className = $this->stream->readUTF();
     
    628751}
    629752
    630 class AVCSequenceParameterSetReader {
     753class AVCSequenceParameterSetReader
     754{
     755    /**
     756     * @var string
     757     */
    631758    public $sps;
    632759    public $start = 0;
    633760    public $currentBytes = 0;
    634761    public $currentBits = 0;
     762
     763    /**
     764     * @var int
     765     */
    635766    public $width;
     767
     768    /**
     769     * @var int
     770     */
    636771    public $height;
    637772
     773    /**
     774     * @param string $sps
     775     */
    638776    public function __construct($sps) {
    639777        $this->sps = $sps;
     
    692830    }
    693831
     832    /**
     833     * @param int $bits
     834     */
    694835    public function skipBits($bits) {
    695836        $newBits = $this->currentBits + $bits;
     
    698839    }
    699840
     841    /**
     842     * @return int
     843     */
    700844    public function getBit() {
    701845        $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
     
    704848    }
    705849
     850    /**
     851     * @param int $bits
     852     *
     853     * @return int
     854     */
    706855    public function getBits($bits) {
    707856        $result = 0;
     
    712861    }
    713862
     863    /**
     864     * @return int
     865     */
    714866    public function expGolombUe() {
    715867        $significantBits = 0;
     
    727879    }
    728880
     881    /**
     882     * @return int
     883     */
    729884    public function expGolombSe() {
    730885        $result = $this->expGolombUe();
     
    736891    }
    737892
     893    /**
     894     * @return int
     895     */
    738896    public function getWidth() {
    739897        return $this->width;
    740898    }
    741899
     900    /**
     901     * @return int
     902     */
    742903    public function getHeight() {
    743904        return $this->height;
  • trunk/src/wp-includes/ID3/module.audio-video.matroska.php

    r41196 r46112  
    11<?php
     2
    23/////////////////////////////////////////////////////////////////
    34/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
    8 // See readme.txt for more details                             //
     5//  available at https://github.com/JamesHeinrich/getID3       //
     6//            or https://www.getid3.org                        //
     7//            or http://getid3.sourceforge.net                 //
     8//  see readme.txt for more details                            //
    99/////////////////////////////////////////////////////////////////
    1010//                                                             //
     
    7373define('EBML_ID_FILEUID',                       0x06AE); //         [46][AE] -- Unique ID representing the file, as random as possible.
    7474define('EBML_ID_CONTENTENCALGO',                0x07E1); //         [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values:
    75 define('EBML_ID_CONTENTENCKEYID',               0x07E2); //         [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with.
     75define('EBML_ID_CONTENTENCKEYID',               0x07E2); //         [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with.
    7676define('EBML_ID_CONTENTSIGNATURE',              0x07E3); //         [47][E3] -- A cryptographic signature of the contents.
    7777define('EBML_ID_CONTENTSIGKEYID',               0x07E4); //         [47][E4] -- This is the ID of the private key the data was signed with.
     
    216216class getid3_matroska extends getid3_handler
    217217{
    218     // public options
    219     public static $hide_clusters    = true;  // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE]
    220     public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
    221 
    222     // private parser settings/placeholders
     218    /**
     219     * If true, do not return information about CLUSTER chunks, since there's a lot of them
     220     * and they're not usually useful [default: TRUE].
     221     *
     222     * @var bool
     223     */
     224    public static $hide_clusters    = true;
     225
     226    /**
     227     * True to parse the whole file, not only header [default: FALSE].
     228     *
     229     * @var bool
     230     */
     231    public static $parse_whole_file = false;
     232
     233    /*
     234     * Private parser settings/placeholders.
     235     */
    223236    private $EBMLbuffer        = '';
    224237    private $EBMLbuffer_offset = 0;
     
    227240    private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
    228241
     242    /**
     243     * @return bool
     244     */
    229245    public function Analyze()
    230246    {
     
    367383                                    $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
    368384                                    if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
    369                                         foreach ($getid3_temp->info['audio'] as $key => $value) {
    370                                             $track_info[$key] = $value;
     385                                        foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
     386                                            $track_info[$sub_key] = $value;
    371387                                        }
    372388                                    }
     
    422438                                    $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
    423439                                    if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
    424                                         foreach ($getid3_temp->info['audio'] as $key => $value) {
    425                                             $track_info[$key] = $value;
     440                                        foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
     441                                            $track_info[$sub_key] = $value;
    426442                                        }
    427443                                    }
     
    450466
    451467                                $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
    452                                 foreach ($parsed as $key => $value) {
    453                                     if ($key != 'raw') {
    454                                         $track_info[$key] = $value;
     468                                foreach ($parsed as $sub_key => $value) {
     469                                    if ($sub_key != 'raw') {
     470                                        $track_info[$sub_key] = $value;
    455471                                    }
    456472                                }
     
    497513    }
    498514
     515    /**
     516     * @param array $info
     517     */
    499518    private function parseEBML(&$info) {
    500519        // http://www.matroska.org/technical/specs/index.html#EBMLBasics
     
    12291248    }
    12301249
     1250    /**
     1251     * @param int $min_data
     1252     *
     1253     * @return bool
     1254     */
    12311255    private function EnsureBufferHasEnoughData($min_data=1024) {
    12321256        if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
     
    12501274    }
    12511275
     1276    /**
     1277     * @return int|float|false
     1278     */
    12521279    private function readEBMLint() {
    12531280        $actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
     
    12821309    }
    12831310
     1311    /**
     1312     * @param int  $length
     1313     * @param bool $check_buffer
     1314     *
     1315     * @return string|false
     1316     */
    12841317    private function readEBMLelementData($length, $check_buffer=false) {
    12851318        if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
     
    12911324    }
    12921325
     1326    /**
     1327     * @param array      $element
     1328     * @param int        $parent_end
     1329     * @param array|bool $get_data
     1330     *
     1331     * @return bool
     1332     */
    12931333    private function getEBMLelement(&$element, $parent_end, $get_data=false) {
    12941334        if ($this->current_offset >= $parent_end) {
     
    13271367    }
    13281368
     1369    /**
     1370     * @param string $type
     1371     * @param int    $line
     1372     * @param array  $element
     1373     */
    13291374    private function unhandledElement($type, $line, $element) {
    13301375        // warn only about unknown and missed elements, not about unuseful
     
    13391384    }
    13401385
     1386    /**
     1387     * @param array $SimpleTagArray
     1388     *
     1389     * @return bool
     1390     */
    13411391    private function ExtractCommentsSimpleTag($SimpleTagArray) {
    13421392        if (!empty($SimpleTagArray['SimpleTag'])) {
     
    13541404    }
    13551405
     1406    /**
     1407     * @param int $parent_end
     1408     *
     1409     * @return array
     1410     */
    13561411    private function HandleEMBLSimpleTag($parent_end) {
    13571412        $simpletag_entry = array();
     
    13841439    }
    13851440
     1441    /**
     1442     * @param array $element
     1443     * @param int   $block_type
     1444     * @param array $info
     1445     *
     1446     * @return array
     1447     */
    13861448    private function HandleEMBLClusterBlock($element, $block_type, &$info) {
    13871449        // http://www.matroska.org/technical/specs/index.html#block_structure
     
    14471509    }
    14481510
     1511    /**
     1512     * @param string $EBMLstring
     1513     *
     1514     * @return int|float|false
     1515     */
    14491516    private static function EBML2Int($EBMLstring) {
    14501517        // http://matroska.org/specs/
     
    14891556    }
    14901557
     1558    /**
     1559     * @param int $EBMLdatestamp
     1560     *
     1561     * @return float
     1562     */
    14911563    private static function EBMLdate2unix($EBMLdatestamp) {
    14921564        // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
     
    14951567    }
    14961568
     1569    /**
     1570     * @param int $target_type
     1571     *
     1572     * @return string|int
     1573     */
    14971574    public static function TargetTypeValue($target_type) {
    14981575        // http://www.matroska.org/technical/specs/tagging/index.html
     
    15101587    }
    15111588
     1589    /**
     1590     * @param int $lacingtype
     1591     *
     1592     * @return string|int
     1593     */
    15121594    public static function BlockLacingType($lacingtype) {
    15131595        // http://matroska.org/technical/specs/index.html#block_structure
     
    15221604    }
    15231605
     1606    /**
     1607     * @param string $codecid
     1608     *
     1609     * @return string
     1610     */
    15241611    public static function CodecIDtoCommonName($codecid) {
    15251612        // http://www.matroska.org/technical/specs/codecid/index.html
     
    15581645    }
    15591646
     1647    /**
     1648     * @param int $value
     1649     *
     1650     * @return string
     1651     */
    15601652    private static function EBMLidName($value) {
    15611653        static $EBMLidList = array();
     
    17561848    }
    17571849
     1850    /**
     1851     * @param int $value
     1852     *
     1853     * @return string
     1854     */
    17581855    public static function displayUnit($value) {
    17591856        // http://www.matroska.org/technical/specs/index.html#DisplayUnit
     
    17671864    }
    17681865
     1866    /**
     1867     * @param array $streams
     1868     *
     1869     * @return array
     1870     */
    17691871    private static function getDefaultStreamInfo($streams)
    17701872    {
     1873        $stream = array();
    17711874        foreach (array_reverse($streams) as $stream) {
    17721875            if ($stream['default']) {
  • trunk/src/wp-includes/ID3/module.audio-video.quicktime.php

    r41196 r46112  
    11<?php
     2
    23/////////////////////////////////////////////////////////////////
    34/// getID3() by James Heinrich <info@getid3.org>               //
    4 //  available at http://getid3.sourceforge.net                 //
    5 //            or http://www.getid3.org                         //
    6 //          also https://github.com/JamesHeinrich/getID3       //
    7 /////////////////////////////////////////////////////////////////
    8 // See readme.txt for more details                             //
     5//  available at https://github.com/JamesHeinrich/getID3       //
     6//            or https://www.getid3.org                        //
     7//            or http://getid3.sourceforge.net                 //
     8//  see readme.txt for more details                            //
    99/////////////////////////////////////////////////////////////////
    1010//                                                             //
     
    2525    public $ParseAllPossibleAtoms = false;
    2626
     27    /**
     28     * @return bool
     29     */
    2730    public function Analyze() {
    2831        $info = &$this->getid3->info;
     
    3639        $offset      = 0;
    3740        $atomcounter = 0;
    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]
     41        $atom_data_read_buffer_size = $info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : $this->getid3->option_fread_buffer_size * 1024; // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
    3942        while ($offset < $info['avdataend']) {
    4043            if (!getid3_lib::intValueSupported($offset)) {
     
    163166            $info['audio']['bitrate'] = $info['bitrate'];
    164167        }
     168        if (!empty($info['bitrate']) && !empty($info['audio']['bitrate']) && empty($info['video']['bitrate']) && !empty($info['video']['frame_rate']) && !empty($info['video']['resolution_x']) && ($info['bitrate'] > $info['audio']['bitrate'])) {
     169            $info['video']['bitrate'] = $info['bitrate'] - $info['audio']['bitrate'];
     170        }
    165171        if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
    166172            foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
     
    194200            $info['video']['dataformat'] = 'quicktime';
    195201        }
     202        if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y']))  {
     203            unset($info['video']);
     204        }
    196205
    197206        return true;
    198207    }
    199208
     209    /**
     210     * @param string $atomname
     211     * @param int    $atomsize
     212     * @param string $atom_data
     213     * @param int    $baseoffset
     214     * @param array  $atomHierarchy
     215     * @param bool   $ParseAllPossibleAtoms
     216     *
     217     * @return array|false
     218     */
    200219    public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
    201220        // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
     
    204223        $info = &$this->getid3->info;
    205224
    206         $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
     225        $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717
    207226        array_push($atomHierarchy, $atomname);
    208227        $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
     
    210229        $atom_structure['size']      = $atomsize;
    211230        $atom_structure['offset']    = $baseoffset;
    212         switch ($atomname) {
    213             case 'moov': // MOVie container atom
    214             case 'trak': // TRAcK container atom
    215             case 'clip': // CLIPping container atom
    216             case 'matt': // track MATTe container atom
    217             case 'edts': // EDiTS container atom
    218             case 'tref': // Track REFerence container atom
    219             case 'mdia': // MeDIA container atom
    220             case 'minf': // Media INFormation container atom
    221             case 'dinf': // Data INFormation container atom
    222             case 'udta': // User DaTA container atom
    223             case 'cmov': // Compressed MOVie container atom
    224             case 'rmra': // Reference Movie Record Atom
    225             case 'rmda': // Reference Movie Descriptor Atom
    226             case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
    227                 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    228                 break;
    229 
    230             case 'ilst': // Item LiST container atom
    231                 if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
    232                     // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
    233                     $allnumericnames = true;
    234                     foreach ($atom_structure['subatoms'] as $subatomarray) {
    235                         if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
    236                             $allnumericnames = false;
    237                             break;
    238                         }
    239                     }
    240                     if ($allnumericnames) {
    241                         $newData = array();
     231        if (substr($atomname, 0, 3) == "\x00\x00\x00") {
     232            // https://github.com/JamesHeinrich/getID3/issues/139
     233            $atomname = getid3_lib::BigEndian2Int($atomname);
     234            $atom_structure['name'] = $atomname;
     235            $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
     236        } else {
     237            switch ($atomname) {
     238                case 'moov': // MOVie container atom
     239                case 'trak': // TRAcK container atom
     240                case 'clip': // CLIPping container atom
     241                case 'matt': // track MATTe container atom
     242                case 'edts': // EDiTS container atom
     243                case 'tref': // Track REFerence container atom
     244                case 'mdia': // MeDIA container atom
     245                case 'minf': // Media INFormation container atom
     246                case 'dinf': // Data INFormation container atom
     247                case 'udta': // User DaTA container atom
     248                case 'cmov': // Compressed MOVie container atom
     249                case 'rmra': // Reference Movie Record Atom
     250                case 'rmda': // Reference Movie Descriptor Atom
     251                case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
     252                    $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
     253                    break;
     254
     255                case 'ilst': // Item LiST container atom
     256                    if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
     257                        // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
     258                        $allnumericnames = true;
    242259                        foreach ($atom_structure['subatoms'] as $subatomarray) {
    243                             foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
    244                                 unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
    245                                 $newData[$subatomarray['name']] = $newData_subatomarray;
     260                            if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
     261                                $allnumericnames = false;
    246262                                break;
    247263                            }
    248264                        }
    249                         $atom_structure['data'] = $newData;
    250                         unset($atom_structure['subatoms']);
    251                     }
    252                 }
    253                 break;
    254 
    255             case "\x00\x00\x00\x01":
    256             case "\x00\x00\x00\x02":
    257             case "\x00\x00\x00\x03":
    258             case "\x00\x00\x00\x04":
    259             case "\x00\x00\x00\x05":
    260                 $atomname = getid3_lib::BigEndian2Int($atomname);
    261                 $atom_structure['name'] = $atomname;
    262                 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    263                 break;
    264 
    265             case 'stbl': // Sample TaBLe container atom
    266                 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
    267                 $isVideo = false;
    268                 $framerate  = 0;
    269                 $framecount = 0;
    270                 foreach ($atom_structure['subatoms'] as $key => $value_array) {
    271                     if (isset($value_array['sample_description_table'])) {
    272                         foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
    273                             if (isset($value_array2['data_format'])) {
    274                                 switch ($value_array2['data_format']) {
    275                                     case 'avc1':
    276                                     case 'mp4v':
    277                                         // video data
    278                                         $isVideo = true;
    279                                         break;
    280                                     case 'mp4a':
    281                                         // audio data
    282                                         break;
     265                        if ($allnumericnames) {
     266                            $newData = array();
     267                            foreach ($atom_structure['subatoms'] as $subatomarray) {
     268                                foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
     269                                    unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
     270                                    $newData[$subatomarray['name']] = $newData_subatomarray;
     271                                    break;
     272                                }
     273                            }
     274                            $atom_structure['data'] = $newData;
     275                            unset($atom_structure['subatoms']);
     276                        }
     277                    }
     278                    break;
     279
     280                case 'stbl': // Sample TaBLe container atom
     281                    $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
     282                    $isVideo = false;
     283                    $framerate  = 0;
     284                    $framecount = 0;
     285                    foreach ($atom_structure['subatoms'] as $key => $value_array) {
     286                        if (isset($value_array['sample_description_table'])) {
     287                            foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
     288                                if (isset($value_array2['data_format'])) {
     289                                    switch ($value_array2['data_format']) {
     290                                        case 'avc1':
     291                                        case 'mp4v':
     292                                            // video data
     293                                            $isVideo = true;
     294                                            break;
     295                                        case 'mp4a':
     296                                            // audio data
     297                                            break;
     298                                    }
     299                                }
     300                            }
     301                        } elseif (isset($value_array['time_to_sample_table'])) {
     302                            foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
     303                                if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
     304                                    $framerate  = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
     305                                    $framecount = $value_array2['sample_count'];
    283306                                }
    284307                            }
    285308                        }
    286                     } elseif (isset($value_array['time_to_sample_table'])) {
    287                         foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
    288                             if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
    289                                 $framerate  = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
    290                                 $framecount = $value_array2['sample_count'];
    291                             }
    292                         }
    293                     }
    294                 }
    295                 if ($isVideo && $framerate) {
    296                     $info['quicktime']['video']['frame_rate'] = $framerate;
    297                     $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
    298                 }
    299                 if ($isVideo && $framecount) {
    300                     $info['quicktime']['video']['frame_count'] = $framecount;
    301                 }
    302                 break;
    303 
    304 
    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
    345             case 'aART': // Album ARTist
    346             case 'akID': // iTunes store account type
    347             case 'apID': // Purchase Account
    348             case 'atID': //
    349             case 'catg': // CaTeGory
    350             case 'cmID': //
    351             case 'cnID': //
    352             case 'covr': // COVeR artwork
    353             case 'cpil': // ComPILation
    354             case 'cprt': // CoPyRighT
    355             case 'desc': // DESCription
    356             case 'disk': // DISK number
    357             case 'egid': // Episode Global ID
    358             case 'geID': //
    359             case 'gnre': // GeNRE
    360             case 'hdvd': // HD ViDeo
    361             case 'keyw': // KEYWord
    362             case 'ldes': // Long DEScription
    363             case 'pcst': // PodCaST
    364             case 'pgap': // GAPless Playback
    365             case 'plID': //
    366             case 'purd': // PURchase Date
    367             case 'purl': // Podcast URL
    368             case 'rati': //
    369             case 'rndu': //
    370             case 'rpdu': //
    371             case 'rtng': // RaTiNG
    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': //
    380             case 'tmpo': // TeMPO (BPM)
    381             case 'trkn': // TRacK Number
    382             case 'tven': // tvEpisodeID
    383             case 'tves': // TV EpiSode
    384             case 'tvnn': // TV Network Name
    385             case 'tvsh': // TV SHow Name
    386             case 'tvsn': // TV SeasoN
    387                 if ($atom_parent == 'udta') {
    388                     // User data atom handler
    389                     $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
    390                     $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
    391                     $atom_structure['data']        =                           substr($atom_data, 4);
    392 
    393                     $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
    394                     if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
    395                         $info['comments']['language'][] = $atom_structure['language'];
    396                     }
    397                 } else {
    398                     // Apple item list box atom handler
    399                     $atomoffset = 0;
    400                     if (substr($atom_data, 2, 2) == "\x10\xB5") {
    401                         // not sure what it means, but observed on iPhone4 data.
    402                         // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
    403                         while ($atomoffset < strlen($atom_data)) {
    404                             $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
    405                             $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
    406                             $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
    407                             if ($boxsmallsize <= 1) {
    408                                 $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
    409                                 $atom_structure['data'] = null;
    410                                 $atomoffset = strlen($atom_data);
    411                                 break;
    412                             }
    413                             switch ($boxsmalltype) {
    414                                 case "\x10\xB5":
    415                                     $atom_structure['data'] = $boxsmalldata;
    416                                     break;
    417                                 default:
    418                                     $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
    419                                     $atom_structure['data'] = $atom_data;
    420                                     break;
    421                             }
    422                             $atomoffset += (4 + $boxsmallsize);
     309                    }
     310                    if ($isVideo && $framerate) {
     311                        $info['quicktime']['video']['frame_rate'] = $framerate;
     312                        $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
     313                    }
     314                    if ($isVideo && $framecount) {
     315                        $info['quicktime']['video']['frame_count'] = $framecount;
     316                    }
     317                    break;
     318
     319
     320                case "\xA9".'alb': // ALBum
     321                case "\xA9".'ART': //
     322                case "\xA9".'art': // ARTist
     323                case "\xA9".'aut': //
     324                case "\xA9".'cmt': // CoMmenT
     325                case "\xA9".'com': // COMposer
     326                case "\xA9".'cpy': //
     327                case "\xA9".'day': // content created year
     328                case "\xA9".'dir': //
     329                case "\xA9".'ed1': //
     330                case "\xA9".'ed2': //
     331                case "\xA9".'ed3': //
     332                case "\xA9".'ed4': //
     333                case "\xA9".'ed5': //
     334                case "\xA9".'ed6': //
     335                case "\xA9".'ed7': //
     336                case "\xA9".'ed8': //
     337                case "\xA9".'ed9': //
     338                case "\xA9".'enc': //
     339                case "\xA9".'fmt': //
     340                case "\xA9".'gen': // GENre
     341                case "\xA9".'grp': // GRouPing
     342                case "\xA9".'hst': //
     343                case "\xA9".'inf': //
     344                case "\xA9".'lyr': // LYRics
     345                case "\xA9".'mak': //
     346                case "\xA9".'mod': //
     347                case "\xA9".'nam': // full NAMe
     348                case "\xA9".'ope': //
     349                case "\xA9".'PRD': //
     350                case "\xA9".'prf': //
     351                case "\xA9".'req': //
     352                case "\xA9".'src': //
     353                case "\xA9".'swr': //
     354                case "\xA9".'too': // encoder
     355                case "\xA9".'trk': // TRacK
     356                case "\xA9".'url': //
     357                case "\xA9".'wrn': //
     358                case "\xA9".'wrt': // WRiTer
     359                case '----': // itunes specific
     360                case 'aART': // Album ARTist
     361                case 'akID': // iTunes store account type
     362                case 'apID': // Purchase Account
     363                case 'atID': //
     364                case 'catg': // CaTeGory
     365                case 'cmID': //
     366                case 'cnID': //
     367                case 'covr': // COVeR artwork
     368                case 'cpil': // ComPILation
     369                case 'cprt': // CoPyRighT
     370                case 'desc': // DESCription
     371                case 'disk': // DISK number
     372                case 'egid': // Episode Global ID
     373                case 'geID': //
     374                case 'gnre': // GeNRE
     375                case 'hdvd': // HD ViDeo
     376                case 'keyw': // KEYWord
     377                case 'ldes': // Long DEScription
     378                case 'pcst': // PodCaST
     379                case 'pgap': // GAPless Playback
     380                case 'plID': //
     381                case 'purd': // PURchase Date
     382                case 'purl': // Podcast URL
     383                case 'rati': //
     384                case 'rndu': //
     385                case 'rpdu': //
     386                case 'rtng': // RaTiNG
     387                case 'sfID': // iTunes store country
     388                case 'soaa': // SOrt Album Artist
     389                case 'soal': // SOrt ALbum
     390                case 'soar': // SOrt ARtist
     391                case 'soco': // SOrt COmposer
     392                case 'sonm': // SOrt NaMe
     393                case 'sosn': // SOrt Show Name
     394                case 'stik': //
     395                case 'tmpo': // TeMPO (BPM)
     396                case 'trkn': // TRacK Number
     397                case 'tven': // tvEpisodeID
     398                case 'tves': // TV EpiSode
     399                case 'tvnn': // TV Network Name
     400                case 'tvsh': // TV SHow Name
     401                case 'tvsn': // TV SeasoN
     402                    if ($atom_parent == 'udta') {
     403                        // User data atom handler
     404                        $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
     405                        $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
     406                        $atom_structure['data']        =                           substr($atom_data, 4);
     407
     408                        $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
     409                        if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
     410                            $info['comments']['language'][] = $atom_structure['language'];
    423411                        }
    424412                    } else {
    425                         while ($atomoffset < strlen($atom_data)) {
    426                             $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
    427                             $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
    428                             $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
    429                             if ($boxsize <= 1) {
    430                                 $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
    431                                 $atom_structure['data'] = null;
    432                                 $atomoffset = strlen($atom_data);
    433                                 break;
     413                        // Apple item list box atom handler
     414                        $atomoffset = 0;
     415                        if (substr($atom_data, 2, 2) == "\x10\xB5") {
     416                            // not sure what it means, but observed on iPhone4 data.
     417                            // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
     418                            while ($atomoffset < strlen($atom_data)) {
     419                                $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
     420                                $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
     421                                $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
     422                                if ($boxsmallsize <= 1) {
     423                                    $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
     424                                    $atom_structure['data'] = null;
     425                                    $atomoffset = strlen($atom_data);
     426                                    break;
     427                                }
     428                                switch ($boxsmalltype) {
     429                                    case "\x10\xB5":
     430                                        $atom_structure['data'] = $boxsmalldata;
     431                                        break;
     432                                    default:
     433                                        $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
     434                                        $atom_structure['data'] = $atom_data;
     435                                        break;
     436                                }
     437                                $atomoffset += (4 + $boxsmallsize);
    434438                            }
    435                             $atomoffset += $boxsize;
    436 
    437                             switch ($boxtype) {
    438                                 case 'mean':
    439                                 case 'name':
    440                                     $atom_structure[$boxtype] = substr($boxdata, 4);
     439                        } else {
     440                            while ($atomoffset < strlen($atom_data)) {
     441                                $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
     442                                $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
     443                                $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
     444                                if ($boxsize <= 1) {
     445                                    $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
     446                                    $atom_structure['data'] = null;
     447                                    $atomoffset = strlen($atom_data);
    441448                                    break;
    442 
    443                                 case 'data':
    444                                     $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
    445                                     $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
    446                                     switch ($atom_structure['flags_raw']) {
    447                                         case  0: // data flag
    448                                         case 21: // tmpo/cpil flag
    449                                             switch ($atomname) {
    450                                                 case 'cpil':
    451                                                 case 'hdvd':
    452                                                 case 'pcst':
    453                                                 case 'pgap':
    454                                                     // 8-bit integer (boolean)
    455                                                     $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    456                                                     break;
    457 
    458                                                 case 'tmpo':
    459                                                     // 16-bit integer
    460                                                     $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
    461                                                     break;
    462 
    463                                                 case 'disk':
    464                                                 case 'trkn':
    465                                                     // binary
    466                                                     $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
    467                                                     $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
    468                                                     $atom_structure['data']  = empty($num) ? '' : $num;
    469                                                     $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
    470                                                     break;
    471 
    472                                                 case 'gnre':
    473                                                     // enum
    474                                                     $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    475                                                     $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
    476                                                     break;
    477 
    478                                                 case 'rtng':
    479                                                     // 8-bit integer
    480                                                     $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    481                                                     $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
    482                                                     break;
    483 
    484                                                 case 'stik':
    485                                                     // 8-bit integer (enum)
    486                                                     $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
    487                                                     $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
    488                                                     break;
    489 
    490                                                 case 'sfID':
    491                                                     // 32-bit integer
    492                                                     $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    493                                                     $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
    494                                                     break;
    495 
    496                                                 case 'egid':
    497                                                 case 'purl':
    498                                                     $atom_structure['data'] = substr($boxdata, 8);
    499                                                     break;
    500 
    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);
     449                                }
     450                                $atomoffset += $boxsize;
     451
     452                                switch ($boxtype) {
     453                                    case 'mean':
     454                                    case 'name':
     455                                        $atom_structure[$boxtype] = substr($boxdata, 4);
     456                                        break;
     457
     458                                    case 'data':
     459                                        $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
     460                                        $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
     461                                        switch ($atom_structure['flags_raw']) {
     462                                            case  0: // data flag
     463                                            case 21: // tmpo/cpil flag
     464                                                switch ($atomname) {
     465                                                    case 'cpil':
     466                                                    case 'hdvd':
     467                                                    case 'pcst':
     468                                                    case 'pgap':
     469                                                        // 8-bit integer (boolean)
     470                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
     471                                                        break;
     472
     473                                                    case 'tmpo':
     474                                                        // 16-bit integer
     475                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
     476                                                        break;
     477
     478                                                    case 'disk':
     479                                                    case 'trkn':
     480                                                        // binary
     481                                                        $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
     482                                                        $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
     483                                                        $atom_structure['data']  = empty($num) ? '' : $num;
     484                                                        $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
     485                                                        break;
     486
     487                                                    case 'gnre':
     488                                                        // enum
     489                                                        $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
     490                                                        $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
     491                                                        break;
     492
     493                                                    case 'rtng':
     494                                                        // 8-bit integer
     495                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
     496                                                        $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
     497                                                        break;
     498
     499                                                    case 'stik':
     500                                                        // 8-bit integer (enum)
     501                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
     502                                                        $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
     503                                                        break;
     504
     505                                                    case 'sfID':
     506                                                        // 32-bit integer
     507                                                        $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
     508                                                        $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
     509                                                        break;
     510
     511                                                    case 'egid':
     512                                                    case 'purl':
     513                                                        $atom_structure['data'] = substr($boxdata, 8);
     514                                                        break;
     515
     516                                                    case 'plID':
     517                                                        // 64-bit integer
     518                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
     519                                                        break;
     520
     521                                                    case 'covr':
     522                                                        $atom_structure['data'] = substr($boxdata, 8);
     523                                                        // not a foolproof check, but better than nothing
     524                                                        if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
     525                                                            $atom_structure['image_mime'] = 'image/jpeg';
     526                                                        } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
     527                                                            $atom_structure['image_mime'] = 'image/png';
     528                                                        } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
     529                                                            $atom_structure['image_mime'] = 'image/gif';
     530                                                        }
     531                                                        break;
     532
     533                                                    case 'atID':
     534                                                    case 'cnID':
     535                                                    case 'geID':
     536                                                    case 'tves':
     537                                                    case 'tvsn':
     538                                                    default:
     539                                                        // 32-bit integer
     540                                                        $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
     541                                                }
     542                                                break;
     543
     544                                            case  1: // text flag
     545                                            case 13: // image flag
     546                                            default:
     547                                                $atom_structure['data'] = substr($boxdata, 8);
     548                                                if ($atomname == 'covr') {
    508549                                                    // not a foolproof check, but better than nothing
    509550                                                    if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
     
    514555                                                        $atom_structure['image_mime'] = 'image/gif';
    515556                                                    }
    516                                                     break;
    517 
    518                                                 case 'atID':
    519                                                 case 'cnID':
    520                                                 case 'geID':
    521                                                 case 'tves':
    522                                                 case 'tvsn':
    523                                                 default:
    524                                                     // 32-bit integer
    525                                                     $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
    526                                             }
    527                                             break;
    528 
    529                                         case  1: // text flag
    530                                         case 13: // image flag
    531                                         default:
    532                                             $atom_structure['data'] = substr($boxdata, 8);
    533                                             if ($atomname == 'covr') {
    534                                                 // not a foolproof check, but better than nothing
    535                                                 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
    536                                                     $atom_structure['image_mime'] = 'image/jpeg';
    537                                                 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
    538                                                     $atom_structure['image_mime'] = 'image/png';
    539                                                 } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
    540                                                     $atom_structure['image_mime'] = 'image/gif';
    541557                                                }
    542                                             }
    543                                             break;
    544 
    545                                     }
    546                                     break;
    547 
    548                                 default:
    549                                     $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
    550                                     $atom_structure['data'] = $atom_data;
    551 
     558                                                break;
     559
     560                                        }
     561                                        break;
     562
     563                                    default:
     564                                        $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
     565                                        $atom_structure['data'] = $atom_data;
     566
     567                                }
    552568                            }
    553569                        }
    554570                    }
    555                 }
    556                 $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
    557                 break;
    558 
    559 
    560             case 'play': // auto-PLAY atom
    561                 $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    562 
    563                 $info['quicktime']['autoplay'] = $atom_structure['autoplay'];
    564                 break;
    565 
    566 
    567             case 'WLOC': // Window LOCation atom
    568                 $atom_structure['location_x']  = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2));
    569                 $atom_structure['location_y']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 2));
    570                 break;
    571 
    572 
    573             case 'LOOP': // LOOPing atom
    574             case 'SelO': // play SELection Only atom
    575             case 'AllF': // play ALL Frames atom
    576                 $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
    577                 break;
    578 
    579 
    580             case 'name': //
    581             case 'MCPS': // Media Cleaner PRo
    582             case '@PRM': // adobe PReMiere version
    583             case '@PRQ': // adobe PRemiere Quicktime version
    584                 $atom_structure['data'] = $atom_data;
    585                 break;
    586 
    587 
    588             case 'cmvd': // Compressed MooV Data atom
    589                 // Code by ubergeekØubergeek*tv based on information from
    590                 // http://developer.apple.com/quicktime/icefloe/dispatch012.html
    591                 $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
    592 
    593                 $CompressedFileData = substr($atom_data, 4);
    594                 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
    595                     $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
    596                 } else {
    597                     $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
    598                 }
    599                 break;
    600 
    601 
    602             case 'dcom': // Data COMpression atom
    603                 $atom_structure['compression_id']   = $atom_data;
    604                 $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
    605                 break;
    606 
    607 
    608             case 'rdrf': // Reference movie Data ReFerence atom
    609                 $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    610                 $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
    611                 $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
    612 
    613                 $atom_structure['reference_type_name']    =                           substr($atom_data,  4, 4);
    614                 $atom_structure['reference_length']       = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
    615                 switch ($atom_structure['reference_type_name']) {
    616                     case 'url ':
    617                         $atom_structure['url']            =       $this->NoNullString(substr($atom_data, 12));
    618                         break;
    619 
    620                     case 'alis':
    621                         $atom_structure['file_alias']     =                           substr($atom_data, 12);
    622                         break;
    623 
    624                     case 'rsrc':
    625                         $atom_structure['resource_alias'] =                           substr($atom_data, 12);
    626                         break;
    627 
    628                     default:
    629                         $atom_structure['data']           =                           substr($atom_data, 12);
    630                         break;
    631                 }
    632                 break;
    633 
    634 
    635             case 'rmqu': // Reference Movie QUality atom
    636                 $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
    637                 break;
    638 
    639 
    640             case 'rmcs': // Reference Movie Cpu Speed atom
    641                 $atom_structure['version']          = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    642                 $atom_structure['flags_raw']        = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    643                 $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
    644                 break;
    645 
    646 
    647             case 'rmvc': // Reference Movie Version Check atom
    648                 $atom_structure['version']            = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    649                 $atom_structure['flags_raw']          = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    650                 $atom_structure['gestalt_selector']   =                           substr($atom_data,  4, 4);
    651                 $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
    652                 $atom_structure['gestalt_value']      = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
    653                 $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
    654                 break;
    655 
    656 
    657             case 'rmcd': // Reference Movie Component check atom
    658                 $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    659                 $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    660                 $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
    661                 $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
    662                 $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
    663                 $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
    664                 $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
    665                 $atom_structure['component_min_version']  = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
    666                 break;
    667 
    668 
    669             case 'rmdr': // Reference Movie Data Rate atom
    670                 $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    671                 $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    672                 $atom_structure['data_rate']     = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
    673 
    674                 $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
    675                 break;
    676 
    677 
    678             case 'rmla': // Reference Movie Language Atom
    679                 $atom_structure['version']     = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    680                 $atom_structure['flags_raw']   = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    681                 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
    682 
    683                 $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
    684                 if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
    685                     $info['comments']['language'][] = $atom_structure['language'];
    686                 }
    687                 break;
    688 
    689 
    690             case 'rmla': // Reference Movie Language Atom
    691                 $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    692                 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    693                 $atom_structure['track_id']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
    694                 break;
    695 
    696 
    697             case 'ptv ': // Print To Video - defines a movie's full screen mode
    698                 // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
    699                 $atom_structure['display_size_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
    700                 $atom_structure['reserved_1']        = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
    701                 $atom_structure['reserved_2']        = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
    702                 $atom_structure['slide_show_flag']   = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
    703                 $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
    704 
    705                 $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
    706                 $atom_structure['flags']['slide_show']   = (bool) $atom_structure['slide_show_flag'];
    707 
    708                 $ptv_lookup[0] = 'normal';
    709                 $ptv_lookup[1] = 'double';
    710                 $ptv_lookup[2] = 'half';
    711                 $ptv_lookup[3] = 'full';
    712                 $ptv_lookup[4] = 'current';
    713                 if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
    714                     $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
    715                 } else {
    716                     $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
    717                 }
    718                 break;
    719 
    720 
    721             case 'stsd': // Sample Table Sample Description atom
    722                 $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    723                 $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    724                 $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);
     571                    $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
     572                    break;
     573
     574
     575                case 'play': // auto-PLAY atom
     576                    $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     577
     578                    $info['quicktime']['autoplay'] = $atom_structure['autoplay'];
     579                    break;
     580
     581
     582                case 'WLOC': // Window LOCation atom
     583                    $atom_structure['location_x']  = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2));
     584                    $atom_structure['location_y']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 2));
     585                    break;
     586
     587
     588                case 'LOOP': // LOOPing atom
     589                case 'SelO': // play SELection Only atom
     590                case 'AllF': // play ALL Frames atom
     591                    $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
     592                    break;
     593
     594
     595                case 'name': //
     596                case 'MCPS': // Media Cleaner PRo
     597                case '@PRM': // adobe PReMiere version
     598                case '@PRQ': // adobe PRemiere Quicktime version
     599                    $atom_structure['data'] = $atom_data;
     600                    break;
     601
     602
     603                case 'cmvd': // Compressed MooV Data atom
     604                    // Code by ubergeekØubergeek*tv based on information from
     605                    // http://developer.apple.com/quicktime/icefloe/dispatch012.html
     606                    $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
     607
     608                    $CompressedFileData = substr($atom_data, 4);
     609                    if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
     610                        $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
    734611                    } 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 
    739                 $stsdEntriesDataOffset = 8;
    740                 for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    741                     $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
    742                     $stsdEntriesDataOffset += 4;
    743                     $atom_structure['sample_description_table'][$i]['data_format']      =                           substr($atom_data, $stsdEntriesDataOffset, 4);
    744                     $stsdEntriesDataOffset += 4;
    745                     $atom_structure['sample_description_table'][$i]['reserved']         = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
    746                     $stsdEntriesDataOffset += 6;
    747                     $atom_structure['sample_description_table'][$i]['reference_index']  = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
    748                     $stsdEntriesDataOffset += 2;
    749                     $atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
    750                     $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
    751 
    752                     $atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
    753                     $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
    754                     $atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
    755 
    756                     switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
    757 
    758                         case "\x00\x00\x00\x00":
    759                             // audio tracks
    760                             $atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
    761                             $atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
    762                             $atom_structure['sample_description_table'][$i]['audio_compression_id'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  2));
    763                             $atom_structure['sample_description_table'][$i]['audio_packet_size']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14,  2));
    764                             $atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
    765 
    766                             // video tracks
    767                             // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
    768                             $atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
    769                             $atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
    770                             $atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
    771                             $atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
    772                             $atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
    773                             $atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
    774                             $atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
    775                             $atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
    776                             $atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
    777                             $atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
    778                             $atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
    779 
    780                             switch ($atom_structure['sample_description_table'][$i]['data_format']) {
    781                                 case '2vuY':
    782                                 case 'avc1':
    783                                 case 'cvid':
    784                                 case 'dvc ':
    785                                 case 'dvcp':
    786                                 case 'gif ':
    787                                 case 'h263':
    788                                 case 'jpeg':
    789                                 case 'kpcd':
    790                                 case 'mjpa':
    791                                 case 'mjpb':
    792                                 case 'mp4v':
    793                                 case 'png ':
    794                                 case 'raw ':
    795                                 case 'rle ':
    796                                 case 'rpza':
    797                                 case 'smc ':
    798                                 case 'SVQ1':
    799                                 case 'SVQ3':
    800                                 case 'tiff':
    801                                 case 'v210':
    802                                 case 'v216':
    803                                 case 'v308':
    804                                 case 'v408':
    805                                 case 'v410':
    806                                 case 'yuv2':
    807                                     $info['fileformat'] = 'mp4';
    808                                     $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
    809 // http://www.getid3.org/phpBB3/viewtopic.php?t=1550
    810 //if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
    811 if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
    812     // assume that values stored here are more important than values stored in [tkhd] atom
    813     $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
    814     $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
    815     $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
    816     $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
    817 }
    818                                     break;
    819 
    820                                 case 'qtvr':
    821                                     $info['video']['dataformat'] = 'quicktimevr';
    822                                     break;
    823 
    824                                 case 'mp4a':
    825                                 default:
    826                                     $info['quicktime']['audio']['codec']       = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
    827                                     $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
    828                                     $info['quicktime']['audio']['channels']    = $atom_structure['sample_description_table'][$i]['audio_channels'];
    829                                     $info['quicktime']['audio']['bit_depth']   = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
    830                                     $info['audio']['codec']                    = $info['quicktime']['audio']['codec'];
    831                                     $info['audio']['sample_rate']              = $info['quicktime']['audio']['sample_rate'];
    832                                     $info['audio']['channels']                 = $info['quicktime']['audio']['channels'];
    833                                     $info['audio']['bits_per_sample']          = $info['quicktime']['audio']['bit_depth'];
    834                                     switch ($atom_structure['sample_description_table'][$i]['data_format']) {
    835                                         case 'raw ': // PCM
    836                                         case 'alac': // Apple Lossless Audio Codec
    837                                             $info['audio']['lossless'] = true;
    838                                             break;
    839                                         default:
    840                                             $info['audio']['lossless'] = false;
    841                                             break;
    842                                     }
    843                                     break;
    844                             }
     612                        $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
     613                    }
     614                    break;
     615
     616
     617                case 'dcom': // Data COMpression atom
     618                    $atom_structure['compression_id']   = $atom_data;
     619                    $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
     620                    break;
     621
     622
     623                case 'rdrf': // Reference movie Data ReFerence atom
     624                    $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     625                    $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
     626                    $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
     627
     628                    $atom_structure['reference_type_name']    =                           substr($atom_data,  4, 4);
     629                    $atom_structure['reference_length']       = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
     630                    switch ($atom_structure['reference_type_name']) {
     631                        case 'url ':
     632                            $atom_structure['url']            =       $this->NoNullString(substr($atom_data, 12));
    845633                            break;
    846634
     635                        case 'alis':
     636                            $atom_structure['file_alias']     =                           substr($atom_data, 12);
     637                            break;
     638
     639                        case 'rsrc':
     640                            $atom_structure['resource_alias'] =                           substr($atom_data, 12);
     641                            break;
     642
    847643                        default:
    848                             switch ($atom_structure['sample_description_table'][$i]['data_format']) {
    849                                 case 'mp4s':
    850                                     $info['fileformat'] = 'mp4';
    851                                     break;
    852 
    853                                 default:
    854                                     // video atom
    855                                     $atom_structure['sample_description_table'][$i]['video_temporal_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
    856                                     $atom_structure['sample_description_table'][$i]['video_spatial_quality']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
    857                                     $atom_structure['sample_description_table'][$i]['video_frame_width']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
    858                                     $atom_structure['sample_description_table'][$i]['video_frame_height']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
    859                                     $atom_structure['sample_description_table'][$i]['video_resolution_x']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20,  4));
    860                                     $atom_structure['sample_description_table'][$i]['video_resolution_y']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
    861                                     $atom_structure['sample_description_table'][$i]['video_data_size']         =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
    862                                     $atom_structure['sample_description_table'][$i]['video_frame_count']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  2));
    863                                     $atom_structure['sample_description_table'][$i]['video_encoder_name_len']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34,  1));
    864                                     $atom_structure['sample_description_table'][$i]['video_encoder_name']      =                             substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']);
    865                                     $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66,  2));
    866                                     $atom_structure['sample_description_table'][$i]['video_color_table_id']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68,  2));
    867 
    868                                     $atom_structure['sample_description_table'][$i]['video_pixel_color_type']  = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
    869                                     $atom_structure['sample_description_table'][$i]['video_pixel_color_name']  = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
    870 
    871                                     if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
    872                                         $info['quicktime']['video']['codec_fourcc']        = $atom_structure['sample_description_table'][$i]['data_format'];
    873                                         $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
    874                                         $info['quicktime']['video']['codec']               = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
    875                                         $info['quicktime']['video']['color_depth']         = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
    876                                         $info['quicktime']['video']['color_depth_name']    = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
    877 
    878                                         $info['video']['codec']           = $info['quicktime']['video']['codec'];
    879                                         $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
    880                                     }
    881                                     $info['video']['lossless']           = false;
    882                                     $info['video']['pixel_aspect_ratio'] = (float) 1;
    883                                     break;
    884                             }
     644                            $atom_structure['data']           =                           substr($atom_data, 12);
    885645                            break;
    886646                    }
    887                     switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
    888                         case 'mp4a':
    889                             $info['audio']['dataformat']         = 'mp4';
    890                             $info['quicktime']['audio']['codec'] = 'mp4';
    891                             break;
    892 
    893                         case '3ivx':
    894                         case '3iv1':
    895                         case '3iv2':
    896                             $info['video']['dataformat'] = '3ivx';
    897                             break;
    898 
    899                         case 'xvid':
    900                             $info['video']['dataformat'] = 'xvid';
    901                             break;
    902 
    903                         case 'mp4v':
    904                             $info['video']['dataformat'] = 'mpeg4';
    905                             break;
    906 
    907                         case 'divx':
    908                         case 'div1':
    909                         case 'div2':
    910                         case 'div3':
    911                         case 'div4':
    912                         case 'div5':
    913                         case 'div6':
    914                             $info['video']['dataformat'] = 'divx';
    915                             break;
    916 
    917                         default:
    918                             // do nothing
    919                             break;
    920                     }
    921                     unset($atom_structure['sample_description_table'][$i]['data']);
    922                 }
    923                 break;
    924 
    925 
    926             case 'stts': // Sample Table Time-to-Sample atom
    927                 $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    928                 $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    929                 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
    930                 $sttsEntriesDataOffset = 8;
    931                 //$FrameRateCalculatorArray = array();
    932                 $frames_count = 0;
    933 
    934                 $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
    935                 if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
    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).');
    937                 }
    938                 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
    939                     $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
    940                     $sttsEntriesDataOffset += 4;
    941                     $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
    942                     $sttsEntriesDataOffset += 4;
    943 
    944                     $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
    945 
    946                     // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
    947                     //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
    948                     //  $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
    949                     //  if ($stts_new_framerate <= 60) {
    950                     //      // some atoms have durations of "1" giving a very large framerate, which probably is not right
    951                     //      $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
    952                     //  }
    953                     //}
    954                     //
    955                     //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
    956                 }
    957                 $info['quicktime']['stts_framecount'][] = $frames_count;
    958                 //$sttsFramesTotal  = 0;
    959                 //$sttsSecondsTotal = 0;
    960                 //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
    961                 //  if (($frames_per_second > 60) || ($frames_per_second < 1)) {
    962                 //      // not video FPS information, probably audio information
    963                 //      $sttsFramesTotal  = 0;
    964                 //      $sttsSecondsTotal = 0;
    965                 //      break;
    966                 //  }
    967                 //  $sttsFramesTotal  += $frame_count;
    968                 //  $sttsSecondsTotal += $frame_count / $frames_per_second;
    969                 //}
    970                 //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
    971                 //  if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
    972                 //      $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
    973                 //  }
    974                 //}
    975                 break;
    976 
    977 
    978             case 'stss': // Sample Table Sync Sample (key frames) atom
    979                 if ($ParseAllPossibleAtoms) {
     647                    break;
     648
     649
     650                case 'rmqu': // Reference Movie QUality atom
     651                    $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
     652                    break;
     653
     654
     655                case 'rmcs': // Reference Movie Cpu Speed atom
     656                    $atom_structure['version']          = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     657                    $atom_structure['flags_raw']        = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     658                    $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
     659                    break;
     660
     661
     662                case 'rmvc': // Reference Movie Version Check atom
     663                    $atom_structure['version']            = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     664                    $atom_structure['flags_raw']          = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     665                    $atom_structure['gestalt_selector']   =                           substr($atom_data,  4, 4);
     666                    $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
     667                    $atom_structure['gestalt_value']      = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
     668                    $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
     669                    break;
     670
     671
     672                case 'rmcd': // Reference Movie Component check atom
     673                    $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     674                    $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     675                    $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
     676                    $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
     677                    $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
     678                    $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
     679                    $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
     680                    $atom_structure['component_min_version']  = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
     681                    break;
     682
     683
     684                case 'rmdr': // Reference Movie Data Rate atom
     685                    $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     686                    $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     687                    $atom_structure['data_rate']     = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
     688
     689                    $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
     690                    break;
     691
     692
     693                case 'rmla': // Reference Movie Language Atom
     694                    $atom_structure['version']     = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     695                    $atom_structure['flags_raw']   = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     696                    $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
     697
     698                    $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
     699                    if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
     700                        $info['comments']['language'][] = $atom_structure['language'];
     701                    }
     702                    break;
     703
     704
     705                case 'ptv ': // Print To Video - defines a movie's full screen mode
     706                    // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
     707                    $atom_structure['display_size_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
     708                    $atom_structure['reserved_1']        = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
     709                    $atom_structure['reserved_2']        = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
     710                    $atom_structure['slide_show_flag']   = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
     711                    $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
     712
     713                    $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
     714                    $atom_structure['flags']['slide_show']   = (bool) $atom_structure['slide_show_flag'];
     715
     716                    $ptv_lookup[0] = 'normal';
     717                    $ptv_lookup[1] = 'double';
     718                    $ptv_lookup[2] = 'half';
     719                    $ptv_lookup[3] = 'full';
     720                    $ptv_lookup[4] = 'current';
     721                    if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
     722                        $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
     723                    } else {
     724                        $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
     725                    }
     726                    break;
     727
     728
     729                case 'stsd': // Sample Table Sample Description atom
    980730                    $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    981731                    $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    982732                    $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
    983                     $stssEntriesDataOffset = 8;
     733
     734                    // see: https://github.com/JamesHeinrich/getID3/issues/111
     735                    // Some corrupt files have been known to have high bits set in the number_entries field
     736                    // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
     737                    // Workaround: mask off the upper byte and throw a warning if it's nonzero
     738                    if ($atom_structure['number_entries'] > 0x000FFFFF) {
     739                        if ($atom_structure['number_entries'] > 0x00FFFFFF) {
     740                            $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));
     741                            $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
     742                        } else {
     743                            $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');
     744                        }
     745                    }
     746
     747                    $stsdEntriesDataOffset = 8;
    984748                    for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    985                         $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
    986                         $stssEntriesDataOffset += 4;
    987                     }
    988                 }
    989                 break;
    990 
    991 
    992             case 'stsc': // Sample Table Sample-to-Chunk atom
    993                 if ($ParseAllPossibleAtoms) {
     749                        $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
     750                        $stsdEntriesDataOffset += 4;
     751                        $atom_structure['sample_description_table'][$i]['data_format']      =                           substr($atom_data, $stsdEntriesDataOffset, 4);
     752                        $stsdEntriesDataOffset += 4;
     753                        $atom_structure['sample_description_table'][$i]['reserved']         = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
     754                        $stsdEntriesDataOffset += 6;
     755                        $atom_structure['sample_description_table'][$i]['reference_index']  = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
     756                        $stsdEntriesDataOffset += 2;
     757                        $atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
     758                        $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
     759
     760                        $atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
     761                        $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
     762                        $atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
     763
     764                        switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
     765
     766                            case "\x00\x00\x00\x00":
     767                                // audio tracks
     768                                $atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
     769                                $atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
     770                                $atom_structure['sample_description_table'][$i]['audio_compression_id'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  2));
     771                                $atom_structure['sample_description_table'][$i]['audio_packet_size']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14,  2));
     772                                $atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
     773
     774                                // video tracks
     775                                // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
     776                                $atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
     777                                $atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
     778                                $atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
     779                                $atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
     780                                $atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
     781                                $atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
     782                                $atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
     783                                $atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
     784                                $atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
     785                                $atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
     786                                $atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
     787
     788                                switch ($atom_structure['sample_description_table'][$i]['data_format']) {
     789                                    case '2vuY':
     790                                    case 'avc1':
     791                                    case 'cvid':
     792                                    case 'dvc ':
     793                                    case 'dvcp':
     794                                    case 'gif ':
     795                                    case 'h263':
     796                                    case 'jpeg':
     797                                    case 'kpcd':
     798                                    case 'mjpa':
     799                                    case 'mjpb':
     800                                    case 'mp4v':
     801                                    case 'png ':
     802                                    case 'raw ':
     803                                    case 'rle ':
     804                                    case 'rpza':
     805                                    case 'smc ':
     806                                    case 'SVQ1':
     807                                    case 'SVQ3':
     808                                    case 'tiff':
     809                                    case 'v210':
     810                                    case 'v216':
     811                                    case 'v308':
     812                                    case 'v408':
     813                                    case 'v410':
     814                                    case 'yuv2':
     815                                        $info['fileformat'] = 'mp4';
     816                                        $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
     817                                        if ($this->QuicktimeVideoCodecLookup($info['video']['fourcc'])) {
     818                                            $info['video']['fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($info['video']['fourcc']);
     819                                        }
     820
     821                                        // https://www.getid3.org/phpBB3/viewtopic.php?t=1550
     822                                        //if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
     823                                        if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
     824                                            // assume that values stored here are more important than values stored in [tkhd] atom
     825                                            $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
     826                                            $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
     827                                            $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
     828                                            $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
     829                                        }
     830                                        break;
     831
     832                                    case 'qtvr':
     833                                        $info['video']['dataformat'] = 'quicktimevr';
     834                                        break;
     835
     836                                    case 'mp4a':
     837                                    default:
     838                                        $info['quicktime']['audio']['codec']       = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
     839                                        $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
     840                                        $info['quicktime']['audio']['channels']    = $atom_structure['sample_description_table'][$i]['audio_channels'];
     841                                        $info['quicktime']['audio']['bit_depth']   = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
     842                                        $info['audio']['codec']                    = $info['quicktime']['audio']['codec'];
     843                                        $info['audio']['sample_rate']              = $info['quicktime']['audio']['sample_rate'];
     844                                        $info['audio']['channels']                 = $info['quicktime']['audio']['channels'];
     845                                        $info['audio']['bits_per_sample']          = $info['quicktime']['audio']['bit_depth'];
     846                                        switch ($atom_structure['sample_description_table'][$i]['data_format']) {
     847                                            case 'raw ': // PCM
     848                                            case 'alac': // Apple Lossless Audio Codec
     849                                            case 'sowt': // signed/two's complement (Little Endian)
     850                                            case 'twos': // signed/two's complement (Big Endian)
     851                                            case 'in24': // 24-bit Integer
     852                                            case 'in32': // 32-bit Integer
     853                                            case 'fl32': // 32-bit Floating Point
     854                                            case 'fl64': // 64-bit Floating Point
     855                                                $info['audio']['lossless'] = $info['quicktime']['audio']['lossless'] = true;
     856                                                $info['audio']['bitrate']  = $info['quicktime']['audio']['bitrate']  = $info['audio']['channels'] * $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'];
     857                                                break;
     858                                            default:
     859                                                $info['audio']['lossless'] = false;
     860                                                break;
     861                                        }
     862                                        break;
     863                                }
     864                                break;
     865
     866                            default:
     867                                switch ($atom_structure['sample_description_table'][$i]['data_format']) {
     868                                    case 'mp4s':
     869                                        $info['fileformat'] = 'mp4';
     870                                        break;
     871
     872                                    default:
     873                                        // video atom
     874                                        $atom_structure['sample_description_table'][$i]['video_temporal_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
     875                                        $atom_structure['sample_description_table'][$i]['video_spatial_quality']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
     876                                        $atom_structure['sample_description_table'][$i]['video_frame_width']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
     877                                        $atom_structure['sample_description_table'][$i]['video_frame_height']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
     878                                        $atom_structure['sample_description_table'][$i]['video_resolution_x']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20,  4));
     879                                        $atom_structure['sample_description_table'][$i]['video_resolution_y']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
     880                                        $atom_structure['sample_description_table'][$i]['video_data_size']         =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
     881                                        $atom_structure['sample_description_table'][$i]['video_frame_count']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  2));
     882                                        $atom_structure['sample_description_table'][$i]['video_encoder_name_len']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34,  1));
     883                                        $atom_structure['sample_description_table'][$i]['video_encoder_name']      =                             substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']);
     884                                        $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66,  2));
     885                                        $atom_structure['sample_description_table'][$i]['video_color_table_id']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68,  2));
     886
     887                                        $atom_structure['sample_description_table'][$i]['video_pixel_color_type']  = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
     888                                        $atom_structure['sample_description_table'][$i]['video_pixel_color_name']  = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
     889
     890                                        if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
     891                                            $info['quicktime']['video']['codec_fourcc']        = $atom_structure['sample_description_table'][$i]['data_format'];
     892                                            $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
     893                                            $info['quicktime']['video']['codec']               = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
     894                                            $info['quicktime']['video']['color_depth']         = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
     895                                            $info['quicktime']['video']['color_depth_name']    = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
     896
     897                                            $info['video']['codec']           = $info['quicktime']['video']['codec'];
     898                                            $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
     899                                        }
     900                                        $info['video']['lossless']           = false;
     901                                        $info['video']['pixel_aspect_ratio'] = (float) 1;
     902                                        break;
     903                                }
     904                                break;
     905                        }
     906                        switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
     907                            case 'mp4a':
     908                                $info['audio']['dataformat']         = 'mp4';
     909                                $info['quicktime']['audio']['codec'] = 'mp4';
     910                                break;
     911
     912                            case '3ivx':
     913                            case '3iv1':
     914                            case '3iv2':
     915                                $info['video']['dataformat'] = '3ivx';
     916                                break;
     917
     918                            case 'xvid':
     919                                $info['video']['dataformat'] = 'xvid';
     920                                break;
     921
     922                            case 'mp4v':
     923                                $info['video']['dataformat'] = 'mpeg4';
     924                                break;
     925
     926                            case 'divx':
     927                            case 'div1':
     928                            case 'div2':
     929                            case 'div3':
     930                            case 'div4':
     931                            case 'div5':
     932                            case 'div6':
     933                                $info['video']['dataformat'] = 'divx';
     934                                break;
     935
     936                            default:
     937                                // do nothing
     938                                break;
     939                        }
     940                        unset($atom_structure['sample_description_table'][$i]['data']);
     941                    }
     942                    break;
     943
     944
     945                case 'stts': // Sample Table Time-to-Sample atom
    994946                    $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    995947                    $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    996948                    $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
    997                     $stscEntriesDataOffset = 8;
    998                     for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    999                         $atom_structure['sample_to_chunk_table'][$i]['first_chunk']        = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
    1000                         $stscEntriesDataOffset += 4;
    1001                         $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk']  = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
    1002                         $stscEntriesDataOffset += 4;
    1003                         $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
    1004                         $stscEntriesDataOffset += 4;
    1005                     }
    1006                 }
    1007                 break;
    1008 
    1009 
    1010             case 'stsz': // Sample Table SiZe atom
    1011                 if ($ParseAllPossibleAtoms) {
    1012                     $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
    1013                     $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
    1014                     $atom_structure['sample_size']    = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
    1015                     $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
    1016                     $stszEntriesDataOffset = 12;
    1017                     if ($atom_structure['sample_size'] == 0) {
     949                    $sttsEntriesDataOffset = 8;
     950                    //$FrameRateCalculatorArray = array();
     951                    $frames_count = 0;
     952
     953                    $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
     954                    if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
     955                        $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($this->getid3->memory_limit / 1048576).'MB).');
     956                    }
     957                    for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
     958                        $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
     959                        $sttsEntriesDataOffset += 4;
     960                        $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
     961                        $sttsEntriesDataOffset += 4;
     962
     963                        $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
     964
     965                        // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
     966                        //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
     967                        //  $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
     968                        //  if ($stts_new_framerate <= 60) {
     969                        //      // some atoms have durations of "1" giving a very large framerate, which probably is not right
     970                        //      $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
     971                        //  }
     972                        //}
     973                        //
     974                        //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
     975                    }
     976                    $info['quicktime']['stts_framecount'][] = $frames_count;
     977                    //$sttsFramesTotal  = 0;
     978                    //$sttsSecondsTotal = 0;
     979                    //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
     980                    //  if (($frames_per_second > 60) || ($frames_per_second < 1)) {
     981                    //      // not video FPS information, probably audio information
     982                    //      $sttsFramesTotal  = 0;
     983                    //      $sttsSecondsTotal = 0;
     984                    //      break;
     985                    //  }
     986                    //  $sttsFramesTotal  += $frame_count;
     987                    //  $sttsSecondsTotal += $frame_count / $frames_per_second;
     988                    //}
     989                    //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
     990                    //  if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
     991                    //      $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
     992                    //  }
     993                    //}
     994                    break;
     995
     996
     997                case 'stss': // Sample Table Sync Sample (key frames) atom
     998                    if ($ParseAllPossibleAtoms) {
     999                        $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     1000                        $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     1001                        $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
     1002                        $stssEntriesDataOffset = 8;
    10181003                        for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
    1019                             $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
    1020                             $stszEntriesDataOffset += 4;
     1004                            $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
     1005                            $stssEntriesDataOffset += 4;
    10211006                        }
    10221007                    }
    1023                 }
    1024                 break;
    1025 
    1026 
    1027             case 'stco': // Sample Table Chunk Offset atom
    1028                 if ($ParseAllPossibleAtoms) {
     1008                    break;
     1009
     1010
     1011                case 'stsc': // Sample Table Sample-to-Chunk atom
     1012                    if ($ParseAllPossibleAtoms) {
     1013                        $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
     1014                        $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
     1015                        $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
     1016                        $stscEntriesDataOffset = 8;
     1017                        for ($i = 0; $i < $atom_structure['number_entries']; $i++) {