<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[46112] trunk/src/wp-includes/ID3: Update getID3 library to fix issues with PHP7.4</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/46112">46112</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/46112","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>jorbin</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-09-14 19:06:09 +0000 (Sat, 14 Sep 2019)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>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: <a href="https://core.trac.wordpress.org/ticket/47751">#47751</a>,<a href="https://core.trac.wordpress.org/ticket/47783">#47783</a>.
Fixes: <a href="https://core.trac.wordpress.org/ticket/48040">#48040</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesID3getid3libphp">trunk/src/wp-includes/ID3/getid3.lib.php</a></li>
<li><a href="#trunksrcwpincludesID3getid3php">trunk/src/wp-includes/ID3/getid3.php</a></li>
<li><a href="#trunksrcwpincludesID3licensetxt">trunk/src/wp-includes/ID3/license.txt</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiovideoasfphp">trunk/src/wp-includes/ID3/module.audio-video.asf.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiovideoflvphp">trunk/src/wp-includes/ID3/module.audio-video.flv.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiovideomatroskaphp">trunk/src/wp-includes/ID3/module.audio-video.matroska.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiovideoquicktimephp">trunk/src/wp-includes/ID3/module.audio-video.quicktime.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiovideoriffphp">trunk/src/wp-includes/ID3/module.audio-video.riff.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudioac3php">trunk/src/wp-includes/ID3/module.audio.ac3.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiodtsphp">trunk/src/wp-includes/ID3/module.audio.dts.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudioflacphp">trunk/src/wp-includes/ID3/module.audio.flac.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiomp3php">trunk/src/wp-includes/ID3/module.audio.mp3.php</a></li>
<li><a href="#trunksrcwpincludesID3moduleaudiooggphp">trunk/src/wp-includes/ID3/module.audio.ogg.php</a></li>
<li><a href="#trunksrcwpincludesID3moduletagapetagphp">trunk/src/wp-includes/ID3/module.tag.apetag.php</a></li>
<li><a href="#trunksrcwpincludesID3moduletagid3v1php">trunk/src/wp-includes/ID3/module.tag.id3v1.php</a></li>
<li><a href="#trunksrcwpincludesID3moduletagid3v2php">trunk/src/wp-includes/ID3/module.tag.id3v2.php</a></li>
<li><a href="#trunksrcwpincludesID3moduletaglyrics3php">trunk/src/wp-includes/ID3/module.tag.lyrics3.php</a></li>
<li><a href="#trunksrcwpincludesID3readmetxt">trunk/src/wp-includes/ID3/readme.txt</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesID3getid3libphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/getid3.lib.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/getid3.lib.php  2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/getid3.lib.php    2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,13 +1,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
-/////////////////////////////////////////////////////////////////
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
</ins><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // getid3.lib.php - part of getID3()                           //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> //                                                            ///
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -14,14 +14,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_lib
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $string
+        * @param bool   $hex
+        * @param bool   $spaces
+        * @param string $htmlencoding
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
</span><span class="cx" style="display: block; padding: 0 10px">                $returnstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < strlen($string); $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($hex) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤');
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($spaces) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $returnstring .= ' ';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -36,9 +43,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $returnstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Truncates a floating-point number at the decimal point.
+        *
+        * @param float $floatnumber
+        *
+        * @return float|int returns int (if possible, otherwise float)
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function trunc($floatnumber) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // truncates a floating-point number at the decimal point
-               // returns int (if possible, otherwise float)
</del><span class="cx" style="display: block; padding: 0 10px">                 if ($floatnumber >= 1) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $truncatednumber = floor($floatnumber);
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif ($floatnumber <= -1) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -52,7 +64,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $truncatednumber;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int|null $variable
+        * @param int      $increment
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function safe_inc(&$variable, $increment=1) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($variable)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $variable += $increment;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -62,6 +79,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int|float $floatnum
+        *
+        * @return int|float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function CastAsInt($floatnum) {
</span><span class="cx" style="display: block; padding: 0 10px">                // convert to float if not already
</span><span class="cx" style="display: block; padding: 0 10px">                $floatnum = (float) $floatnum;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -77,6 +99,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $floatnum;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $num
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function intValueSupported($num) {
</span><span class="cx" style="display: block; padding: 0 10px">                // check if integers are 64-bit
</span><span class="cx" style="display: block; padding: 0 10px">                static $hasINT64 = null;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -93,12 +120,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $fraction
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function DecimalizeFraction($fraction) {
</span><span class="cx" style="display: block; padding: 0 10px">                list($numerator, $denominator) = explode('/', $fraction);
</span><span class="cx" style="display: block; padding: 0 10px">                return $numerator / ($denominator ? $denominator : 1);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $binarynumerator
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function DecimalBinary2Float($binarynumerator) {
</span><span class="cx" style="display: block; padding: 0 10px">                $numerator   = self::Bin2Dec($binarynumerator);
</span><span class="cx" style="display: block; padding: 0 10px">                $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -105,16 +141,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ($numerator / $denominator);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
+        *
+        * @param string $binarypointnumber
+        * @param int    $maxbits
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
</del><span class="cx" style="display: block; padding: 0 10px">                 if (strpos($binarypointnumber, '.') === false) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $binarypointnumber = '0.'.$binarypointnumber;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif ($binarypointnumber{0} == '.') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif ($binarypointnumber[0] == '.') {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $binarypointnumber = '0'.$binarypointnumber;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $exponent = 0;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         if (substr($binarypointnumber, 1, 1) == '.') {
</span><span class="cx" style="display: block; padding: 0 10px">                                $exponent--;
</span><span class="cx" style="display: block; padding: 0 10px">                                $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -122,7 +164,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $pointpos = strpos($binarypointnumber, '.');
</span><span class="cx" style="display: block; padding: 0 10px">                                $exponent += ($pointpos - 1);
</span><span class="cx" style="display: block; padding: 0 10px">                                $binarypointnumber = str_replace('.', '', $binarypointnumber);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -129,9 +171,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
+        *
+        * @param float $floatvalue
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function Float2BinaryDecimal($floatvalue) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
</del><span class="cx" style="display: block; padding: 0 10px">                 $maxbits = 128; // to how many bits of precision should the calculations be taken?
</span><span class="cx" style="display: block; padding: 0 10px">                $intpart   = self::trunc($floatvalue);
</span><span class="cx" style="display: block; padding: 0 10px">                $floatpart = abs($floatvalue - $intpart);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,9 +192,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $binarypointnumber;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
+        *
+        * @param float $floatvalue
+        * @param int $bits
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function Float2String($floatvalue, $bits) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $exponentbits = 0;
+               $fractionbits = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">                 switch ($bits) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 32:
</span><span class="cx" style="display: block; padding: 0 10px">                                $exponentbits = 8;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -176,22 +231,34 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $byteword
+        *
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LittleEndian2Float($byteword) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2Float(strrev($byteword));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
+        *
+        * @link http://www.psc.edu/general/software/packages/ieee/ieee.html
+        * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
+        *
+        * @param string $byteword
+        *
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BigEndian2Float($byteword) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
-               // http://www.psc.edu/general/software/packages/ieee/ieee.html
-               // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
-
</del><span class="cx" style="display: block; padding: 0 10px">                 $bitword = self::BigEndian2Bin($byteword);
</span><span class="cx" style="display: block; padding: 0 10px">                if (!$bitword) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return 0;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $signbit = $bitword{0};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $signbit = $bitword[0];
+               $floatvalue = 0;
+               $exponentbits = 0;
+               $fractionbits = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                switch (strlen($byteword) * 8) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 32:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -208,7 +275,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                // 80-bit Apple SANE format
</span><span class="cx" style="display: block; padding: 0 10px">                                // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
</span><span class="cx" style="display: block; padding: 0 10px">                                $exponentstring = substr($bitword, 1, 15);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $isnormalized = intval($bitword{16});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $isnormalized = intval($bitword[16]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $fractionstring = substr($bitword, 17, 63);
</span><span class="cx" style="display: block; padding: 0 10px">                                $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
</span><span class="cx" style="display: block; padding: 0 10px">                                $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -259,7 +326,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (float) $floatvalue;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $byteword
+        * @param bool   $synchsafe
+        * @param bool   $signed
+        *
+        * @return int|float|false
+        * @throws Exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $intvalue = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $bytewordlen = strlen($byteword);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -269,9 +343,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < $bytewordlen; $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
</span><span class="cx" style="display: block; padding: 0 10px">                                //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
</ins><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                if ($signed && !$synchsafe) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -288,25 +362,48 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return self::CastAsInt($intvalue);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $byteword
+        * @param bool   $signed
+        *
+        * @return int|float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LittleEndian2Int($byteword, $signed=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2Int(strrev($byteword), false, $signed);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $byteword
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LittleEndian2Bin($byteword) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2Bin(strrev($byteword));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $byteword
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BigEndian2Bin($byteword) {
</span><span class="cx" style="display: block; padding: 0 10px">                $binvalue = '';
</span><span class="cx" style="display: block; padding: 0 10px">                $bytewordlen = strlen($byteword);
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < $bytewordlen; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                return $binvalue;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int  $number
+        * @param int  $minbytes
+        * @param bool $synchsafe
+        * @param bool $signed
+        *
+        * @return string
+        * @throws Exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($number < 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                        throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -327,7 +424,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $number
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function Dec2Bin($number) {
</span><span class="cx" style="display: block; padding: 0 10px">                while ($number >= 256) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -341,11 +442,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $binstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $binstring
+        * @param bool   $signed
+        *
+        * @return int|float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function Bin2Dec($binstring, $signed=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $signmult = 1;
</span><span class="cx" style="display: block; padding: 0 10px">                if ($signed) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ($binstring{0} == '1') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($binstring[0] == '1') {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $signmult = -1;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        $binstring = substr($binstring, 1);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -357,7 +463,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return self::CastAsInt($decvalue * $signmult);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $binstring
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function Bin2String($binstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // return 'hi' for input of '0110100001101001'
</span><span class="cx" style="display: block; padding: 0 10px">                $string = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -368,7 +478,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $string;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int  $number
+        * @param int  $minbytes
+        * @param bool $synchsafe
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $intstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                while ($number > 0) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -383,7 +499,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $array1
+        * @param array $array2
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function array_merge_clobber($array1, $array2) {
</span><span class="cx" style="display: block; padding: 0 10px">                // written by kcØhireability*com
</span><span class="cx" style="display: block; padding: 0 10px">                // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -401,7 +522,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newarray;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $array1
+        * @param array $array2
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function array_merge_noclobber($array1, $array2) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!is_array($array1) || !is_array($array2)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -417,6 +543,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newarray;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $array1
+        * @param array $array2
+        *
+        * @return array|false|null
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function flipped_array_merge_noclobber($array1, $array2) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!is_array($array1) || !is_array($array2)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -431,7 +563,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return array_flip($newarray);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $theArray
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ksort_recursive(&$theArray) {
</span><span class="cx" style="display: block; padding: 0 10px">                ksort($theArray);
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ($theArray as $key => $value) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -442,6 +578,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $filename
+        * @param int    $numextensions
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function fileextension($filename, $numextensions=1) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (strstr($filename, '.')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $reversedfilename = strrev($filename);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -457,7 +599,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return '';
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $seconds
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function PlaytimeString($seconds) {
</span><span class="cx" style="display: block; padding: 0 10px">                $sign = (($seconds < 0) ? '-' : '');
</span><span class="cx" style="display: block; padding: 0 10px">                $seconds = round(abs($seconds));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -467,7 +613,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $macdate
+        *
+        * @return int|float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function DateMac2Unix($macdate) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Macintosh timestamp: seconds since 00:00h January 1, 1904
</span><span class="cx" style="display: block; padding: 0 10px">                // UNIX timestamp:      seconds since 00:00h January 1, 1970
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -474,17 +624,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return self::CastAsInt($macdate - 2082844800);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $rawdata
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FixedPoint8_8($rawdata) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $rawdata
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FixedPoint16_16($rawdata) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $rawdata
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FixedPoint2_30($rawdata) {
</span><span class="cx" style="display: block; padding: 0 10px">                $binarystring = self::BigEndian2Bin($rawdata);
</span><span class="cx" style="display: block; padding: 0 10px">                return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -491,6 +653,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $ArrayPath
+        * @param string $Separator
+        * @param mixed $Value
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
</span><span class="cx" style="display: block; padding: 0 10px">                // assigns $Value to a nested array path:
</span><span class="cx" style="display: block; padding: 0 10px">                //   $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -507,6 +676,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $ReturnedArray;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $arraydata
+        * @param bool  $returnkey
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function array_max($arraydata, $returnkey=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $maxvalue = false;
</span><span class="cx" style="display: block; padding: 0 10px">                $maxkey = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -521,6 +696,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ($returnkey ? $maxkey : $maxvalue);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $arraydata
+        * @param bool  $returnkey
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function array_min($arraydata, $returnkey=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $minvalue = false;
</span><span class="cx" style="display: block; padding: 0 10px">                $minkey = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -535,6 +716,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ($returnkey ? $minkey : $minvalue);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $XMLstring
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function XML2array($XMLstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -548,11 +734,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+       * @param SimpleXMLElement|array $XMLobject
+       *
+       * @return array
+       */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function SimpleXMLelement2array($XMLobject) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!is_object($XMLobject) && !is_array($XMLobject)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return $XMLobject;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject;
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach ($XMLarray as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $XMLarray[$key] = self::SimpleXMLelement2array($value);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -559,95 +750,52 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $XMLarray;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // Allan Hansen <ahØartemis*dk>
-       // self::md5_data() - returns md5sum for a file from startuing position to absolute end position
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Returns checksum for a file from starting position to absolute end position.
+        *
+        * @param string $file
+        * @param int    $offset
+        * @param int    $end
+        * @param string $algorithm
+        *
+        * @return string|false
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function hash_data($file, $offset, $end, $algorithm) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                static $tempdir = '';
</del><span class="cx" style="display: block; padding: 0 10px">                 if (!self::intValueSupported($end)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                switch ($algorithm) {
-                       case 'md5':
-                               $hash_function = 'md5_file';
-                               $unix_call     = 'md5sum';
-                               $windows_call  = 'md5sum.exe';
-                               $hash_length   = 32;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (!in_array($algorithm, array('md5', 'sha1'))) {
+                       throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'sha1':
-                               $hash_function = 'sha1_file';
-                               $unix_call     = 'sha1sum';
-                               $windows_call  = 'sha1sum.exe';
-                               $hash_length   = 40;
-                               break;
-
-                       default:
-                               throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
-                               break;
-               }
</del><span class="cx" style="display: block; padding: 0 10px">                 $size = $end - $offset;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                while (true) {
-                       if (GETID3_OS_ISWINDOWS) {
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
-                               // Fall back to create-temp-file method:
-                               if ($algorithm == 'sha1') {
-                                       break;
-                               }
-
-                               $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
-                               foreach ($RequiredFiles as $required_file) {
-                                       if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
-                                               // helper apps not available - fall back to old method
-                                               break 2;
-                                       }
-                               }
-                               $commandline  = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | ';
-                               $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
-                               $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
-
-                       } else {
-
-                               $commandline  = 'head -c'.$end.' '.escapeshellarg($file).' | ';
-                               $commandline .= 'tail -c'.$size.' | ';
-                               $commandline .= $unix_call;
-
-                       }
-                       if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
-                               //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm');
-                               break;
-                       }
-                       return substr(`$commandline`, 0, $hash_length);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $fp = fopen($file, 'rb');
+               fseek($fp, $offset);
+               $ctx = hash_init($algorithm);
+               while ($size > 0) {
+                       $buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE));
+                       hash_update($ctx, $buffer);
+                       $size -= getID3::FREAD_BUFFER_SIZE;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $hash = hash_final($ctx);
+               fclose($fp);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (empty($tempdir)) {
-                       // yes this is ugly, feel free to suggest a better way
-                       require_once(dirname(__FILE__).'/getid3.php');
-                       $getid3_temp = new getID3();
-                       $tempdir = $getid3_temp->tempdir;
-                       unset($getid3_temp);
-               }
-               // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
-               if (($data_filename = tempnam($tempdir, 'gI3')) === false) {
-                       // can't find anywhere to create a temp file, just fail
-                       return false;
-               }
-
-               // Init
-               $result = false;
-
-               // copy parts of file
-               try {
-                       self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
-                       $result = $hash_function($data_filename);
-               } catch (Exception $e) {
-                       throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
-               }
-               unlink($data_filename);
-               return $result;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $hash;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $filename_source
+        * @param string $filename_dest
+        * @param int    $offset
+        * @param int    $length
+        *
+        * @return bool
+        * @throws Exception
+        *
+        * @deprecated Unused, may be removed in future versions of getID3
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!self::intValueSupported($offset + $length)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -660,21 +808,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $byteslefttowrite -= $byteswritten;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        fclose($fp_dest);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         return true;
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        fclose($fp_src);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                fclose($fp_dest);
</del><span class="cx" style="display: block; padding: 0 10px">                         } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                throw new Exception('failed to create file for writing '.$filename_dest);
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        fclose($fp_src);
</del><span class="cx" style="display: block; padding: 0 10px">                 } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        throw new Exception('failed to open file for reading '.$filename_source);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return false;
</del><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $charval
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_int_utf8($charval) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($charval < 128) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // 0bbbbbbb
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -698,7 +850,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // ISO-8859-1 => UTF-8
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * ISO-8859-1 => UTF-8
+        *
+        * @param string $string
+        * @param bool   $bom
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (function_exists('utf8_encode')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return utf8_encode($string);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -709,13 +868,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $newcharstring .= "\xEF\xBB\xBF";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < strlen($string); $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $charval = ord($string{$i});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $charval = ord($string[$i]);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $newcharstring .= self::iconv_fallback_int_utf8($charval);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // ISO-8859-1 => UTF-16BE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * ISO-8859-1 => UTF-16BE
+        *
+        * @param string $string
+        * @param bool   $bom
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $newcharstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -722,12 +888,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $newcharstring .= "\xFE\xFF";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < strlen($string); $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $newcharstring .= "\x00".$string{$i};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $newcharstring .= "\x00".$string[$i];
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // ISO-8859-1 => UTF-16LE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * ISO-8859-1 => UTF-16LE
+        *
+        * @param string $string
+        * @param bool   $bom
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $newcharstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -734,17 +907,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $newcharstring .= "\xFF\xFE";
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < strlen($string); $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $newcharstring .= $string{$i}."\x00";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $newcharstring .= $string[$i]."\x00";
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // ISO-8859-1 => UTF-16LE (BOM)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * ISO-8859-1 => UTF-16LE (BOM)
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_iso88591_utf16($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::iconv_fallback_iso88591_utf16le($string, true);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-8 => ISO-8859-1
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-8 => ISO-8859-1
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf8_iso88591($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (function_exists('utf8_decode')) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return utf8_decode($string);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -754,27 +939,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $stringlength = strlen($string);
</span><span class="cx" style="display: block; padding: 0 10px">                while ($offset < $stringlength) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ((ord($string[$offset]) | 0x07) == 0xF7) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 4;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 1110bbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 3;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 110bbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 2;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 0bbbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ord($string{$offset});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ord($string[$offset]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 1;
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                // error? throw some kind of warning here?
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -788,7 +973,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-8 => UTF-16BE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-8 => UTF-16BE
+        *
+        * @param string $string
+        * @param bool   $bom
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $newcharstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -797,27 +989,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $stringlength = strlen($string);
</span><span class="cx" style="display: block; padding: 0 10px">                while ($offset < $stringlength) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ((ord($string[$offset]) | 0x07) == 0xF7) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 4;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 1110bbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 3;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 110bbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 2;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 0bbbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ord($string{$offset});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ord($string[$offset]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 1;
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                // error? throw some kind of warning here?
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -831,7 +1023,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-8 => UTF-16LE
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-8 => UTF-16LE
+        *
+        * @param string $string
+        * @param bool   $bom
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $newcharstring = '';
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -840,27 +1039,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $stringlength = strlen($string);
</span><span class="cx" style="display: block; padding: 0 10px">                while ($offset < $stringlength) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ((ord($string[$offset]) | 0x07) == 0xF7) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 4;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 1110bbbb 10bbbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 3;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 110bbbbb 10bbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 2;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // 0bbbbbbb
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $charval = ord($string{$offset});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $charval = ord($string[$offset]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $offset += 1;
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                // error? maybe throw some warning here?
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -874,12 +1073,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-8 => UTF-16LE (BOM)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-8 => UTF-16LE (BOM)
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf8_utf16($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::iconv_fallback_utf8_utf16le($string, true);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16BE => UTF-8
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16BE => UTF-8
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16be_utf8($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($string, 0, 2) == "\xFE\xFF") {
</span><span class="cx" style="display: block; padding: 0 10px">                        // strip BOM
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -893,7 +1104,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16LE => UTF-8
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16LE => UTF-8
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16le_utf8($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($string, 0, 2) == "\xFF\xFE") {
</span><span class="cx" style="display: block; padding: 0 10px">                        // strip BOM
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -907,7 +1124,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16BE => ISO-8859-1
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16BE => ISO-8859-1
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16be_iso88591($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($string, 0, 2) == "\xFE\xFF") {
</span><span class="cx" style="display: block; padding: 0 10px">                        // strip BOM
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -921,7 +1144,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16LE => ISO-8859-1
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16LE => ISO-8859-1
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16le_iso88591($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($string, 0, 2) == "\xFF\xFE") {
</span><span class="cx" style="display: block; padding: 0 10px">                        // strip BOM
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -935,7 +1164,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $newcharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16 (BOM) => ISO-8859-1
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16 (BOM) => ISO-8859-1
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16_iso88591($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                $bom = substr($string, 0, 2);
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom == "\xFE\xFF") {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -946,7 +1181,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $string;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // UTF-16 (BOM) => UTF-8
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * UTF-16 (BOM) => UTF-8
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback_utf16_utf8($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                $bom = substr($string, 0, 2);
</span><span class="cx" style="display: block; padding: 0 10px">                if ($bom == "\xFE\xFF") {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -957,6 +1198,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $string;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $in_charset
+        * @param string $out_charset
+        * @param string $string
+        *
+        * @return string
+        * @throws Exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function iconv_fallback($in_charset, $out_charset, $string) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($in_charset == $out_charset) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -963,8 +1212,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return $string;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // mb_convert_encoding() availble
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // mb_convert_encoding() available
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (function_exists('mb_convert_encoding')) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) {
+                               // if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM
+                               $string = "\xFF\xFE".$string;
+                       }
+                       if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) {
+                               if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) {
+                                       // if string consists of only BOM, mb_convert_encoding will return the BOM unmodified
+                                       return '';
+                               }
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                switch ($out_charset) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        case 'ISO-8859-1':
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -974,9 +1233,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return $converted_string;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        return $string;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                }
-               // iconv() availble
-               else if (function_exists('iconv')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               // iconv() available
+               } elseif (function_exists('iconv')) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                switch ($out_charset) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        case 'ISO-8859-1':
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1017,6 +1276,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param mixed  $data
+        * @param string $charset
+        *
+        * @return mixed
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
</span><span class="cx" style="display: block; padding: 0 10px">                if (is_string($data)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return self::MultiByteCharString2HTML($data, $charset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1031,6 +1296,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string|int|float $string
+        * @param string           $charset
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
</span><span class="cx" style="display: block; padding: 0 10px">                $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
</span><span class="cx" style="display: block; padding: 0 10px">                $HTMLstring = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1069,22 +1340,22 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'utf-8':
</span><span class="cx" style="display: block; padding: 0 10px">                                $strlen = strlen($string);
</span><span class="cx" style="display: block; padding: 0 10px">                                for ($i = 0; $i < $strlen; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $char_ord_val = ord($string{$i});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $char_ord_val = ord($string[$i]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $charval = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($char_ord_val < 0x80) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $charval = $char_ord_val;
</span><span class="cx" style="display: block; padding: 0 10px">                                        } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F  &&  $i+3 < $strlen) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $charval  = (($char_ord_val & 0x07) << 18);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $charval += ((ord($string{++$i}) & 0x3F) << 12);
-                                               $charval += ((ord($string{++$i}) & 0x3F) << 6);
-                                               $charval +=  (ord($string{++$i}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $charval += ((ord($string[++$i]) & 0x3F) << 12);
+                                               $charval += ((ord($string[++$i]) & 0x3F) << 6);
+                                               $charval +=  (ord($string[++$i]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07  &&  $i+2 < $strlen) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $charval  = (($char_ord_val & 0x0F) << 12);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $charval += ((ord($string{++$i}) & 0x3F) << 6);
-                                               $charval +=  (ord($string{++$i}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $charval += ((ord($string[++$i]) & 0x3F) << 6);
+                                               $charval +=  (ord($string[++$i]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03  &&  $i+1 < $strlen) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $charval  = (($char_ord_val & 0x1F) << 6);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $charval += (ord($string{++$i}) & 0x3F);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $charval += (ord($string[++$i]) & 0x3F);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($charval >= 32) && ($charval <= 127)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $HTMLstring .= htmlentities(chr($charval));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1123,8 +1394,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $HTMLstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $namecode
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RGADnameLookup($namecode) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $RGADname = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($RGADname)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1136,7 +1410,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $originatorcode
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RGADoriginatorLookup($originatorcode) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $RGADoriginator = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($RGADoriginator)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1149,16 +1427,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $rawadjustment
+        * @param int $signbit
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RGADadjustmentLookup($rawadjustment, $signbit) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $adjustment = $rawadjustment / 10;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $adjustment = (float) $rawadjustment / 10;
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ($signbit == 1) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $adjustment *= -1;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return (float) $adjustment;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $adjustment;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $namecode
+        * @param int $originatorcode
+        * @param int $replaygain
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RGADgainString($namecode, $originatorcode, $replaygain) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($replaygain < 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $signbit = '1';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1174,11 +1463,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $gainstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param float $amplitude
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RGADamplitude2dB($amplitude) {
</span><span class="cx" style="display: block; padding: 0 10px">                return 20 * log10($amplitude);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $imgData
+        * @param array  $imageinfo
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function GetDataImageSize($imgData, &$imageinfo=array()) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $tempdir = '';
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($tempdir)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1213,32 +1512,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $GetDataImageSize;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $mime_type
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ImageExtFromMime($mime_type) {
</span><span class="cx" style="display: block; padding: 0 10px">                // temporary way, works OK for now, but should be reworked in the future
</span><span class="cx" style="display: block; padding: 0 10px">                return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public static function ImageTypesLookup($imagetypeid) {
-               static $ImageTypesLookup = array();
-               if (empty($ImageTypesLookup)) {
-                       $ImageTypesLookup[1]  = 'gif';
-                       $ImageTypesLookup[2]  = 'jpeg';
-                       $ImageTypesLookup[3]  = 'png';
-                       $ImageTypesLookup[4]  = 'swf';
-                       $ImageTypesLookup[5]  = 'psd';
-                       $ImageTypesLookup[6]  = 'bmp';
-                       $ImageTypesLookup[7]  = 'tiff (little-endian)';
-                       $ImageTypesLookup[8]  = 'tiff (big-endian)';
-                       $ImageTypesLookup[9]  = 'jpc';
-                       $ImageTypesLookup[10] = 'jp2';
-                       $ImageTypesLookup[11] = 'jpx';
-                       $ImageTypesLookup[12] = 'jb2';
-                       $ImageTypesLookup[13] = 'swc';
-                       $ImageTypesLookup[14] = 'iff';
-               }
-               return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
-       }
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $ThisFileInfo
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function CopyTagsToComments(&$ThisFileInfo) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Copy all entries from ['tags'] into common ['comments']
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1326,7 +1614,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $key
+        * @param int    $begin
+        * @param int    $end
+        * @param string $file
+        * @param string $name
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Cached
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1373,6 +1669,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $filename
+        * @param string $sourcefile
+        * @param bool   $DieOnFailure
+        *
+        * @return bool
+        * @throws Exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                global $GETID3_ERRORARRAY;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1393,10 +1697,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function trimNullByte($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                return trim($string, "\x00");
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $path
+        *
+        * @return float|bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function getFileSizeSyscall($path) {
</span><span class="cx" style="display: block; padding: 0 10px">                $filesize = false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1421,13 +1735,44 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $filesize;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $filename
+        *
+        * @return string|false
+        */
+       public static function truepath($filename) {
+               // 2017-11-08: this could use some improvement, patches welcome
+               if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) {
+                       // PHP's built-in realpath function does not work on UNC Windows shares
+                       $goodpath = array();
+                       foreach (explode('/', str_replace('\\', '/', $filename)) as $part) {
+                               if ($part == '.') {
+                                       continue;
+                               }
+                               if ($part == '..') {
+                                       if (count($goodpath)) {
+                                               array_pop($goodpath);
+                                       } else {
+                                               // cannot step above this level, already at top level
+                                               return false;
+                                       }
+                               } else {
+                                       $goodpath[] = $part;
+                               }
+                       }
+                       return implode(DIRECTORY_SEPARATOR, $goodpath);
+               }
+               return realpath($filename);
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
-       * @param string $path A path.
-       * @param string $suffix If the name component ends in suffix this will also be cut off.
-       * @return string
-       */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
+        *
+        * @param string $path A path.
+        * @param string $suffix If the name component ends in suffix this will also be cut off.
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function mb_basename($path, $suffix = null) {
</span><span class="cx" style="display: block; padding: 0 10px">                $splited = preg_split('#/#', rtrim($path, '/ '));
</span><span class="cx" style="display: block; padding: 0 10px">                return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
</span></span></pre></div>
<a id="trunksrcwpincludesID3getid3php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/getid3.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/getid3.php      2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/getid3.php        2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,10 +1,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
-/////////////////////////////////////////////////////////////////
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
</ins><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // Please see readme.txt for more information                  //
</span><span class="cx" style="display: block; padding: 0 10px"> //                                                            ///
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -26,6 +25,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">        define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8));
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*
+https://www.getid3.org/phpBB3/viewtopic.php?t=2114
+If you are running into a the problem where filenames with special characters are being handled
+incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed,
+and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line:
+*/
+//setlocale(LC_CTYPE, 'en_US.UTF-8');
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // attempt to define temp dir as something flexible but reliable
</span><span class="cx" style="display: block; padding: 0 10px"> $temp_dir = ini_get('upload_tmp_dir');
</span><span class="cx" style="display: block; padding: 0 10px"> if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -74,53 +81,190 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getID3
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Settings
-       public $encoding        = 'UTF-8';        // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples:  ISO-8859-1  UTF-8  UTF-16  UTF-16BE
-       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'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+        * Settings
+        */
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Optional tag checks - disable for speed.
-       public $option_tag_id3v1         = true;  // Read and process ID3v1 tags
-       public $option_tag_id3v2         = true;  // Read and process ID3v2 tags
-       public $option_tag_lyrics3       = true;  // Read and process Lyrics3 tags
-       public $option_tag_apetag        = true;  // Read and process APE tags
-       public $option_tags_process      = true;  // Copy tags to root key 'tags' and encode to $this->encoding
-       public $option_tags_html         = true;  // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples:  ISO-8859-1  UTF-8  UTF-16  UTF-16BE
+        *
+        * @var string
+        */
+       public $encoding        = 'UTF-8';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Optional tag/comment calucations
-       public $option_extra_info        = true;  // Calculate additional info such as bitrate, channelmode etc
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252'
+        *
+        * @var string
+        */
+       public $encoding_id3v1  = 'ISO-8859-1';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Optional handling of embedded attachments (e.g. images)
-       public $option_save_attachments  = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /*
+        * Optional tag checks - disable for speed.
+        */
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Optional calculations
-       public $option_md5_data          = false; // Get MD5 sum of data part - slow
-       public $option_md5_data_source   = false; // Use MD5 of source file if availble - only FLAC and OptimFROG
-       public $option_sha1_data         = false; // Get SHA1 sum of data part - slow
-       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)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Read and process ID3v1 tags
+        *
+        * @var bool
+        */
+       public $option_tag_id3v1         = true;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: Read buffer size in bytes
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Read and process ID3v2 tags
+        *
+        * @var bool
+        */
+       public $option_tag_id3v2         = true;
+
+       /**
+        * Read and process Lyrics3 tags
+        *
+        * @var bool
+        */
+       public $option_tag_lyrics3       = true;
+
+       /**
+        * Read and process APE tags
+        *
+        * @var bool
+        */
+       public $option_tag_apetag        = true;
+
+       /**
+        * Copy tags to root key 'tags' and encode to $this->encoding
+        *
+        * @var bool
+        */
+       public $option_tags_process      = true;
+
+       /**
+        * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities
+        *
+        * @var bool
+        */
+       public $option_tags_html         = true;
+
+       /*
+        * Optional tag/comment calculations
+        */
+
+       /**
+        * Calculate additional info such as bitrate, channelmode etc
+        *
+        * @var bool
+        */
+       public $option_extra_info        = true;
+
+       /*
+        * Optional handling of embedded attachments (e.g. images)
+        */
+
+       /**
+        * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility
+        *
+        * @var bool|string
+        */
+       public $option_save_attachments  = true;
+
+       /*
+        * Optional calculations
+        */
+
+       /**
+        * Get MD5 sum of data part - slow
+        *
+        * @var bool
+        */
+       public $option_md5_data          = false;
+
+       /**
+        * Use MD5 of source file if availble - only FLAC and OptimFROG
+        *
+        * @var bool
+        */
+       public $option_md5_data_source   = false;
+
+       /**
+        * Get SHA1 sum of data part - slow
+        *
+        * @var bool
+        */
+       public $option_sha1_data         = false;
+
+       /**
+        * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on
+        * PHP_INT_MAX)
+        *
+        * @var bool|null
+        */
+       public $option_max_2gb_check;
+
+       /**
+        * Read buffer size in bytes
+        *
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $option_fread_buffer_size = 32768;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Public variables
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public $filename;                         // Filename of file being analysed.
-       public $fp;                               // Filepointer to file being analysed.
-       public $info;                             // Result array.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * Filename of file being analysed.
+        *
+        * @var string
+        */
+       public $filename;
+
+       /**
+        * Filepointer to file being analysed.
+        *
+        * @var resource
+        */
+       public $fp;
+
+       /**
+        * Result array.
+        *
+        * @var array
+        */
+       public $info;
+
+       /**
+        * @var string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $tempdir = GETID3_TEMP_DIR;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $memory_limit = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Protected variables
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @var string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected $startup_error   = '';
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @var string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected $startup_warning = '';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        const VERSION           = '1.9.14-201706111222';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ const VERSION           = '1.9.17-201907240906';
</ins><span class="cx" style="display: block; padding: 0 10px">         const FREAD_BUFFER_SIZE = 32768;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        const ATTACHMENTS_NONE   = false;
</span><span class="cx" style="display: block; padding: 0 10px">        const ATTACHMENTS_INLINE = true;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: constructor
</del><span class="cx" style="display: block; padding: 0 10px">         public function __construct() {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Check for PHP version
+               $required_php_version = '5.3.0';
+               if (version_compare(PHP_VERSION, $required_php_version, '<')) {
+                       $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n";
+                       return;
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Check memory
</span><span class="cx" style="display: block; padding: 0 10px">                $this->memory_limit = ini_get('memory_limit');
</span><span class="cx" style="display: block; padding: 0 10px">                if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -176,7 +320,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Needed for Windows only:
</span><span class="cx" style="display: block; padding: 0 10px">                // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                //   as well as other helper functions such as head, tail, md5sum, etc
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         //   as well as other helper functions such as head, etc
</ins><span class="cx" style="display: block; padding: 0 10px">                 // This path cannot contain spaces, but the below code will attempt to get the
</span><span class="cx" style="display: block; padding: 0 10px">                //   8.3-equivalent path automatically
</span><span class="cx" style="display: block; padding: 0 10px">                // IMPORTANT: This path must include the trailing slash
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -219,20 +363,27 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        echo $this->startup_error;
</span><span class="cx" style="display: block; padding: 0 10px">                        throw new getid3_exception($this->startup_error);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-               return true;
</del><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function version() {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::VERSION;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function fread_buffer_size() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->option_fread_buffer_size;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // public: setOption
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $optArray
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function setOption($optArray) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!is_array($optArray) || empty($optArray)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -246,8 +397,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       public function openfile($filename, $filesize=null) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $filename
+        * @param int    $filesize
+        *
+        * @return bool
+        *
+        * @throws getid3_exception
+        */
+       public function openfile($filename, $filesize=null, $fp=null) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 try {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!empty($this->startup_error)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                throw new getid3_exception($this->startup_error);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -270,11 +428,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 //$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // open local file
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720
-                       if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720
+                       if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) {
+                               $this->fp = $fp;
+                       } elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // great
</span><span class="cx" style="display: block; padding: 0 10px">                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                $errormessagelist = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -331,10 +491,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                } elseif (getid3_lib::intValueSupported($real_filesize)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        unset($this->info['filesize']);
</span><span class="cx" style="display: block; padding: 0 10px">                                                        fclose($this->fp);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        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');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 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');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                $this->info['filesize'] = $real_filesize;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $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.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $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.');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -346,10 +506,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public: analyze file
-       public function analyze($filename, $filesize=null, $original_filename='') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * analyze file
+        *
+        * @param string $filename
+        * @param int    $filesize
+        * @param string $original_filename
+        *
+        * @return array
+        */
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 try {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (!$this->openfile($filename, $filesize)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (!$this->openfile($filename, $filesize, $fp)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return $this->info;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -383,8 +551,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $header = fread($this->fp, 10);
</span><span class="cx" style="display: block; padding: 0 10px">                                if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->info['id3v2']['header']        = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $this->info['id3v2']['majorversion']  = ord($header{3});
-                                       $this->info['id3v2']['minorversion']  = ord($header{4});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->info['id3v2']['majorversion']  = ord($header[3]);
+                                       $this->info['id3v2']['minorversion']  = ord($header[4]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $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
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -497,7 +665,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // private: error handling
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Error handling.
+        *
+        * @param string $message
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function error($message) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->CleanUp();
</span><span class="cx" style="display: block; padding: 0 10px">                if (!isset($this->info['error'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -508,7 +682,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // private: warning handling
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Warning handling.
+        *
+        * @param string $message
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function warning($message) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->info['warning'][] = $message;
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -515,7 +695,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // private: CleanUp
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function CleanUp() {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // remove possible empty keys
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -562,8 +744,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // return array containing information about all supported formats
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Return array containing information about all supported formats.
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function GetFileFormatArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $format_info = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($format_info)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -584,7 +769,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^ADIF',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'aac',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'application/octet-stream',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/aac',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'fail_ape'  => 'WARNING',
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -602,7 +787,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'aac',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'application/octet-stream',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/aac',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'fail_ape'  => 'WARNING',
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -649,7 +834,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // DSS  - audio       - Digital Speech Standard
</span><span class="cx" style="display: block; padding: 0 10px">                                'dss'  => array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'pattern'   => '^[\\x02-\\x06]ds[s2]',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'pattern'   => '^[\\x02-\\x08]ds[s2]',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'dss',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'mime_type' => 'application/octet-stream',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -668,7 +853,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^fLaC',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'flac',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'audio/x-flac',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/flac',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // LA   - audio       - Lossless Audio (LA)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -700,7 +885,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^MAC ',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'audio',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'monkey',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'application/octet-stream',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/x-monkeys-audio',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> // has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -889,7 +1074,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^(RIFF|SDSS|FORM)',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'audio-video',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'riff',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'audio/x-wav',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'audio/wav',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'fail_ape'  => 'WARNING',
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1053,7 +1238,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'pattern'   => '^\\x1F\\x8B\\x08',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'group'     => 'archive',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'module'    => 'gzip',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        'mime_type' => 'application/x-gzip',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 'mime_type' => 'application/gzip',
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         'fail_id3'  => 'ERROR',
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'fail_ape'  => 'ERROR',
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1068,7 +1253,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        'fail_ape'  => 'ERROR',
</span><span class="cx" style="display: block; padding: 0 10px">                                                ),
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // XZ   - data         - XZ compressed data
+                               'xz'  => array(
+                                                       'pattern'   => '^\\xFD7zXZ\\x00',
+                                                       'group'     => 'archive',
+                                                       'module'    => 'xz',
+                                                       'mime_type' => 'application/x-xz',
+                                                       'fail_id3'  => 'ERROR',
+                                                       'fail_ape'  => 'ERROR',
+                                               ),
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 // Misc other formats
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                // PAR2 - data        - Parity Volume Set Specification 2.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1115,8 +1310,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $format_info;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $filedata
+        * @param string $filename
+        *
+        * @return mixed|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function GetFileFormat(&$filedata, $filename='') {
</span><span class="cx" style="display: block; padding: 0 10px">                // this function will determine the format of a file based on usually
</span><span class="cx" style="display: block; padding: 0 10px">                // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1135,7 +1334,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (preg_match('#\\.mp[123a]$#i', $filename)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Too many mp3 encoders on the market put gabage in front of mpeg files
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Too many mp3 encoders on the market put garbage in front of mpeg files
</ins><span class="cx" style="display: block; padding: 0 10px">                         // use assume format on these if format detection failed
</span><span class="cx" style="display: block; padding: 0 10px">                        $GetFileFormatArray = $this->GetFileFormatArray();
</span><span class="cx" style="display: block; padding: 0 10px">                        $info = $GetFileFormatArray['mp3'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1154,8 +1353,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // converts array to $encoding charset from $this->encoding
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Converts array to $encoding charset from $this->encoding.
+        *
+        * @param array  $array
+        * @param string $encoding
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function CharConvert(&$array, $encoding) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // identical encoding - end here
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1178,7 +1381,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function HandleAllTags() {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // key name => array (tag name, character encoding)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1233,6 +1438,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($tag_key == 'picture') {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                // 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
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 unset($this->info[$comment_name]['comments'][$tag_key]);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1246,6 +1452,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($this->option_tags_html) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                if ($tag_key == 'picture') {
+                                                       // Do not to try to convert binary picture data to HTML
+                                                       // https://github.com/JamesHeinrich/getID3/issues/178
+                                                       continue;
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1254,8 +1465,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // 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
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // 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
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (!empty($this->info['tags'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $unset_keys = array('tags', 'tags_html');
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($this->info['tags'] as $tagtype => $tagarray) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1301,6 +1511,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $algorithm
+        *
+        * @return array|bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getHashdata($algorithm) {
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($algorithm) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'md5':
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1365,7 +1580,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';
</del><span class="cx" style="display: block; padding: 0 10px">                                         $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1';
</span><span class="cx" style="display: block; padding: 0 10px">                                        $VorbisCommentError = `$commandline`;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1424,7 +1638,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px">         public function ChannelsBitratePlaytimeCalculations() {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // set channelmode on audio
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1489,7 +1702,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function CalculateCompressionRatioVideo() {
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($this->info['video'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1537,7 +1752,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function CalculateCompressionRatioAudio() {
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1554,11 +1771,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function CalculateReplayGain() {
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($this->info['replay_gain'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!isset($this->info['replay_gain']['reference_volume'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->info['replay_gain']['reference_volume'] = (double) 89.0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->info['replay_gain']['reference_volume'] = 89.0;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        if (isset($this->info['replay_gain']['track']['adjustment'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1577,6 +1796,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ProcessAudioStreams() {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!isset($this->info['audio']['streams'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1590,10 +1812,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string|bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getid3_tempnam() {
</span><span class="cx" style="display: block; padding: 0 10px">                return tempnam($this->tempdir, 'gI3');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $name
+        *
+        * @return bool
+        *
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function include_module($name) {
</span><span class="cx" style="display: block; padding: 0 10px">                //if (!file_exists($this->include_path.'module.'.$name.'.php')) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1603,21 +1835,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    public static function is_writable ($filename) {
-        $ret = is_writable($filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $filename
+        *
+        * @return bool
+        */
+       public static function is_writable ($filename) {
+               $ret = is_writable($filename);
+               if (!$ret) {
+                       $perms = fileperms($filename);
+                       $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
+               }
+               return $ret;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if (!$ret) {
-            $perms = fileperms($filename);
-            $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
-        }
-
-        return $ret;
-    }
-
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-abstract class getid3_handler {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+abstract class getid3_handler
+{
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">        * @var getID3
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1624,14 +1860,45 @@
</span><span class="cx" style="display: block; padding: 0 10px">        */
</span><span class="cx" style="display: block; padding: 0 10px">        protected $getid3;                       // pointer
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        protected $data_string_flag     = false; // analyzing filepointer or string
-       protected $data_string          = '';    // string to analyze
-       protected $data_string_position = 0;     // seek position in string
-       protected $data_string_length   = 0;     // string length
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Analyzing filepointer or string.
+        *
+        * @var bool
+        */
+       protected $data_string_flag     = false;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        private $dependency_to = null;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * String to analyze.
+        *
+        * @var string
+        */
+       protected $data_string          = '';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Seek position in string.
+        *
+        * @var int
+        */
+       protected $data_string_position = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * String length.
+        *
+        * @var int
+        */
+       protected $data_string_length   = 0;
+
+       /**
+        * @var string
+        */
+       private $dependency_to;
+
+       /**
+        * getid3_handler constructor.
+        *
+        * @param getID3 $getid3
+        * @param string $call_module
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function __construct(getID3 $getid3, $call_module=null) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->getid3 = $getid3;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1640,12 +1907,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // Analyze from file pointer
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Analyze from file pointer.
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         abstract public function Analyze();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // Analyze from string instead
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Analyze from string instead.
+        *
+        * @param string $string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function AnalyzeString($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Enter string mode
</span><span class="cx" style="display: block; padding: 0 10px">                $this->setStringMode($string);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1671,6 +1944,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->data_string_flag = false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function setStringMode($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->data_string_flag   = true;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->data_string        = $string;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1677,6 +1953,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->data_string_length = strlen($string);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int|bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function ftell() {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->data_string_flag) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return $this->data_string_position;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1684,6 +1963,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ftell($this->getid3->fp);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $bytes
+        *
+        * @return string|false
+        *
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function fread($bytes) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->data_string_flag) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->data_string_position += $bytes;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1696,7 +1982,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                //return fread($this->getid3->fp, $bytes);
</span><span class="cx" style="display: block; padding: 0 10px">                /*
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                * http://www.getid3.org/phpBB3/viewtopic.php?t=1930
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * https://www.getid3.org/phpBB3/viewtopic.php?t=1930
</ins><span class="cx" style="display: block; padding: 0 10px">                 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread().
</span><span class="cx" style="display: block; padding: 0 10px">                * It seems to assume that fread() would always return as many bytes as were requested.
</span><span class="cx" style="display: block; padding: 0 10px">                * However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1704,6 +1990,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                */
</span><span class="cx" style="display: block; padding: 0 10px">                $contents = '';
</span><span class="cx" style="display: block; padding: 0 10px">                do {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        //if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
+                       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)"
+                               throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10);
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                         $part = fread($this->getid3->fp, $bytes);
</span><span class="cx" style="display: block; padding: 0 10px">                        $partLength  = strlen($part);
</span><span class="cx" style="display: block; padding: 0 10px">                        $bytes      -= $partLength;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1712,6 +2002,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $contents;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $bytes
+        * @param int $whence
+        *
+        * @return int
+        *
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function fseek($bytes, $whence=SEEK_SET) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->data_string_flag) {
</span><span class="cx" style="display: block; padding: 0 10px">                        switch ($whence) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1742,6 +2040,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return fseek($this->getid3->fp, $bytes, $whence);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function feof() {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->data_string_flag) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return $this->data_string_position >= $this->data_string_length;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1749,10 +2050,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return feof($this->getid3->fp);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $module
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         final protected function isDependencyFor($module) {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->dependency_to == $module;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $text
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function error($text) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->getid3->info['error'][] = $text;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1759,14 +2070,33 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $text
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function warning($text) {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->getid3->warning($text);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $text
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         protected function notice($text) {
</span><span class="cx" style="display: block; padding: 0 10px">                // does nothing for now
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $name
+        * @param int    $offset
+        * @param int    $length
+        * @param string $image_mime
+        *
+        * @return string|null
+        *
+        * @throws Exception
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function saveAttachment($name, $offset, $length, $image_mime=null) {
</span><span class="cx" style="display: block; padding: 0 10px">                try {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1820,6 +2150,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // close and remove dest file if created
</span><span class="cx" style="display: block; padding: 0 10px">                        if (isset($fp_dest) && is_resource($fp_dest)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                fclose($fp_dest);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        }
+
+                       if (isset($dest) && file_exists($dest)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 unlink($dest);
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpincludesID3licensetxt"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/license.txt</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/license.txt     2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/license.txt       2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,7 +1,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><span class="cx" style="display: block; padding: 0 10px"> //  available at http://getid3.sourceforge.net                 //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//            or http://www.getid3.org                         //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//            or https://www.getid3.org                        //
</ins><span class="cx" style="display: block; padding: 0 10px"> //          also https://github.com/JamesHeinrich/getID3       //
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18,9 +18,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> GNU LGPL: https://gnu.org/licenses/lgpl.html                 (v3)
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Mozilla MPL: http://www.mozilla.org/MPL/2.0/                 (v2)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+Mozilla MPL: https://www.mozilla.org/MPL/2.0/                (v2)
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-getID3 Commercial License: http://getid3.org/#gCL (payment required)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> *****************************************************************
</span><span class="cx" style="display: block; padding: 0 10px"> *****************************************************************
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiovideoasfphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio-video.asf.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio-video.asf.php      2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio-video.asf.php        2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio-video.asf.php                                  //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing ASF, WMA and WMV files                 //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16,8 +15,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class getid3_asf extends getid3_handler {
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class getid3_asf extends getid3_handler
+{
+       /**
+        * @param getID3 $getid3
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function __construct(getID3 $getid3) {
</span><span class="cx" style="display: block; padding: 0 10px">                parent::__construct($getid3);  // extends getid3_handler::__construct()
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -30,6 +32,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -83,6 +88,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $NextObjectOffset = $this->ftell();
</span><span class="cx" style="display: block; padding: 0 10px">                $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30);
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $thisfile_asf_streambitratepropertiesobject = array();
+               $thisfile_asf_codeclistobject = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $NextObjectGUID = substr($ASFHeaderData, $offset, 16);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -790,17 +797,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'wm/tracknumber':
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'tracknumber':
</span><span class="cx" style="display: block; padding: 0 10px">                                                                // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $thisfile_asf_comments['track'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
-                                                               foreach ($thisfile_asf_comments['track'] as $key => $value) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         $thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
+                                                               foreach ($thisfile_asf_comments['track_number'] as $key => $value) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         if (preg_match('/^[0-9\x00]+$/', $value)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                $thisfile_asf_comments['track'][$key] = intval(str_replace("\x00", '', $value));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value));
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                        case 'wm/track':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                if (empty($thisfile_asf_comments['track'])) {
-                                                                       $thisfile_asf_comments['track'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         if (empty($thisfile_asf_comments['track_number'])) {
+                                                                       $thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -970,18 +977,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $ASFbitrateAudio = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $ASFbitrateVideo = 0;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                case 1:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                case 2:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                default:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1440,6 +1447,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $CodecListType
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function codecListObjectTypeLookup($CodecListType) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x0001 => 'Video Codec',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1450,6 +1462,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function KnownGUIDs() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $GUIDarray = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'GETID3_ASF_Extended_Stream_Properties_Object'   => '14E6A5CB-C672-4332-8399-A96952065B5A',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1564,6 +1579,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $GUIDarray;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $GUIDstring
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function GUIDname($GUIDstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $GUIDarray = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($GUIDarray)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1572,6 +1592,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return array_search($GUIDstring, $GUIDarray);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $id
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ASFIndexObjectIndexTypeLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $ASFIndexObjectIndexTypeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($ASFIndexObjectIndexTypeLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1582,6 +1607,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $GUIDstring
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function GUIDtoBytestring($GUIDstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
</span><span class="cx" style="display: block; padding: 0 10px">                // first 4 bytes are in little-endian order
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1617,31 +1647,42 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $hexbytecharstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $Bytestring
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BytestringToGUID($Bytestring) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $GUIDstring  = str_pad(dechex(ord($Bytestring{3})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{2})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{1})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{0})),  2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $GUIDstring  = str_pad(dechex(ord($Bytestring[3])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[2])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[1])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[0])),  2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                 $GUIDstring .= '-';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $GUIDstring .= str_pad(dechex(ord($Bytestring{5})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{4})),  2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $GUIDstring .= str_pad(dechex(ord($Bytestring[5])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[4])),  2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                 $GUIDstring .= '-';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $GUIDstring .= str_pad(dechex(ord($Bytestring{7})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{6})),  2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $GUIDstring .= str_pad(dechex(ord($Bytestring[7])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[6])),  2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                 $GUIDstring .= '-';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $GUIDstring .= str_pad(dechex(ord($Bytestring{8})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{9})),  2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $GUIDstring .= str_pad(dechex(ord($Bytestring[8])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[9])),  2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px">                 $GUIDstring .= '-';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return strtoupper($GUIDstring);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int  $FILETIME
+        * @param bool $round
+        *
+        * @return float|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FILETIMEtoUNIXtime($FILETIME, $round=true) {
</span><span class="cx" style="display: block; padding: 0 10px">                // FILETIME is a 64-bit unsigned integer representing
</span><span class="cx" style="display: block; padding: 0 10px">                // the number of 100-nanosecond intervals since January 1, 1601
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1653,6 +1694,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ($FILETIME - 116444736000000000) / 10000000;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $WMpictureType
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function WMpictureTypeLookup($WMpictureType) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = null;
</span><span class="cx" style="display: block; padding: 0 10px">                if ($lookup === null) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1684,6 +1730,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $asf_header_extension_object_data
+        * @param int    $unhandled_sections
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://msdn.microsoft.com/en-us/library/bb643323.aspx
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1930,7 +1982,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $HeaderExtensionObjectParsed;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $id
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function metadataLibraryObjectDataTypeLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1944,6 +2000,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$id]) ? $lookup[$id] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $data
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ASF_WMpicture(&$data) {
</span><span class="cx" style="display: block; padding: 0 10px">                //typedef struct _WMPicture{
</span><span class="cx" style="display: block; padding: 0 10px">                //  LPWSTR  pwszMIMEType;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1994,14 +2055,24 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $WMpicture;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // Remove terminator 00 00 and convert UTF-16LE to Latin-1
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Remove terminator 00 00 and convert UTF-16LE to Latin-1.
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TrimConvert($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' ');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       // Remove terminator 00 00
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Remove terminator 00 00.
+        *
+        * @param string $string
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TrimTerm($string) {
</span><span class="cx" style="display: block; padding: 0 10px">                // remove terminator, only if present (it should be, but...)
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($string, -2) === "\x00\x00") {
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiovideoflvphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio-video.flv.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio-video.flv.php      2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio-video.flv.php        2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,15 +1,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
+/////////////////////////////////////////////////////////////////
</ins><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+// module.audio-video.flv.php                                  //
+// module for analyzing Shockwave Flash Video files            //
+// dependencies: NONE                                          //
+//                                                             //
+/////////////////////////////////////////////////////////////////
+//                                                             //
</ins><span class="cx" style="display: block; padding: 0 10px"> //  FLV module by Seth Kaufman <sethØwhirl-i-gig*com>          //
</span><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> //  * version 0.1 (26 June 2005)                               //
</span><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//                                                             //
</del><span class="cx" style="display: block; padding: 0 10px"> //  * version 0.1.1 (15 July 2005)                             //
</span><span class="cx" style="display: block; padding: 0 10px"> //  minor modifications by James Heinrich <info@getid3.org>    //
</span><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43,12 +50,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> //  handle GETID3_FLV_VIDEO_VP6FLV_ALPHA                       //
</span><span class="cx" style="display: block; padding: 0 10px"> //  improved AVCSequenceParameterSetReader::readData()         //
</span><span class="cx" style="display: block; padding: 0 10px"> //    by Xander Schouwerwou <schouwerwouØgmail*com>            //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//                                                             //
-/////////////////////////////////////////////////////////////////
-//                                                             //
-// module.audio-video.flv.php                                  //
-// module for analyzing Shockwave Flash Video files            //
-// dependencies: NONE                                          //
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                            ///
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -73,12 +74,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define('H264_PROFILE_HIGH444',            144);
</span><span class="cx" style="display: block; padding: 0 10px"> define('H264_PROFILE_HIGH444_PREDICTIVE', 244);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class getid3_flv extends getid3_handler {
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class getid3_flv extends getid3_handler
+{
</ins><span class="cx" style="display: block; padding: 0 10px">         const magic = 'FLV';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        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
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Break out of the loop if too many frames have been scanned; only scan this
+        * many if meta frame does not contain useful duration.
+        *
+        * @var int
+        */
+       public $max_frames = 100000;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -332,7 +342,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $id
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function audioFormatLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0  => 'Linear PCM, platform endian',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -355,6 +369,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$id]) ? $lookup[$id] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $id
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function audioRateLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 =>  5500,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -365,6 +384,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$id]) ? $lookup[$id] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $id
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function audioBitDepthLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 =>  8,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -373,6 +397,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$id]) ? $lookup[$id] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $id
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function videoCodecLookup($id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        GETID3_FLV_VIDEO_H263         => 'Sorenson H.263',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -386,41 +415,75 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class AMFStream {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class AMFStream
+{
+       /**
+        * @var string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $bytes;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $pos;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $bytes
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function __construct(&$bytes) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->bytes =& $bytes;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->pos = 0;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function readByte() {
-               return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return int
+        */
+       public function readByte() { //  8-bit
+               return ord(substr($this->bytes, $this->pos++, 1));
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function readInt() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return int
+        */
+       public function readInt() { // 16-bit
</ins><span class="cx" style="display: block; padding: 0 10px">                 return ($this->readByte() << 8) + $this->readByte();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function readLong() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return int
+        */
+       public function readLong() { // 32-bit
</ins><span class="cx" style="display: block; padding: 0 10px">                 return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readDouble() {
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::BigEndian2Float($this->read(8));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readUTF() {
</span><span class="cx" style="display: block; padding: 0 10px">                $length = $this->readInt();
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->read($length);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readLongUTF() {
</span><span class="cx" style="display: block; padding: 0 10px">                $length = $this->readLong();
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->read($length);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $length
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function read($length) {
</span><span class="cx" style="display: block; padding: 0 10px">                $val = substr($this->bytes, $this->pos, $length);
</span><span class="cx" style="display: block; padding: 0 10px">                $this->pos += $length;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -427,6 +490,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekByte() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readByte();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -434,6 +500,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekInt() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readInt();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -441,6 +510,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekLong() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readLong();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -448,6 +520,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekDouble() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readDouble();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -455,6 +530,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekUTF() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readUTF();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -462,6 +540,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $val;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function peekLongUTF() {
</span><span class="cx" style="display: block; padding: 0 10px">                $pos = $this->pos;
</span><span class="cx" style="display: block; padding: 0 10px">                $val = $this->readLongUTF();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -470,13 +551,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class AMFReader {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class AMFReader
+{
+       /**
+       * @var AMFStream
+       */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $stream;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public function __construct(&$stream) {
-               $this->stream =& $stream;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param AMFStream $stream
+        */
+       public function __construct(AMFStream $stream) {
+               $this->stream = $stream;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return mixed
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readData() {
</span><span class="cx" style="display: block; padding: 0 10px">                $value = null;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -547,23 +638,36 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $value;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readDouble() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->stream->readDouble();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readBoolean() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->stream->readByte() == 1;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readString() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->stream->readUTF();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readObject() {
</span><span class="cx" style="display: block; padding: 0 10px">                // Get highest numerical index - ignored
</span><span class="cx" style="display: block; padding: 0 10px"> //             $highestIndex = $this->stream->readLong();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $data = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $key = null;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                while ($key = $this->stream->readUTF()) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $data[$key] = $this->readData();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,15 +680,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readMixedArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                // Get highest numerical index - ignored
</span><span class="cx" style="display: block; padding: 0 10px">                $highestIndex = $this->stream->readLong();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $data = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $key = null;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                while ($key = $this->stream->readUTF()) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (is_numeric($key)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $key = (float) $key;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $key = (int) $key;
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        $data[$key] = $this->readData();
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -597,6 +705,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                $length = $this->stream->readLong();
</span><span class="cx" style="display: block; padding: 0 10px">                $data = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -607,6 +718,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readDate() {
</span><span class="cx" style="display: block; padding: 0 10px">                $timestamp = $this->stream->readDouble();
</span><span class="cx" style="display: block; padding: 0 10px">                $timezone = $this->stream->readInt();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -613,14 +727,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $timestamp;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readLongString() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->stream->readLongUTF();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readXML() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->stream->readLongUTF();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function readTypedObject() {
</span><span class="cx" style="display: block; padding: 0 10px">                $className = $this->stream->readUTF();
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->readObject();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -627,14 +750,29 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class AVCSequenceParameterSetReader {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class AVCSequenceParameterSetReader
+{
+       /**
+        * @var string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $sps;
</span><span class="cx" style="display: block; padding: 0 10px">        public $start = 0;
</span><span class="cx" style="display: block; padding: 0 10px">        public $currentBytes = 0;
</span><span class="cx" style="display: block; padding: 0 10px">        public $currentBits = 0;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $width;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public $height;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $sps
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function __construct($sps) {
</span><span class="cx" style="display: block; padding: 0 10px">                $this->sps = $sps;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -691,6 +829,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $bits
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function skipBits($bits) {
</span><span class="cx" style="display: block; padding: 0 10px">                $newBits = $this->currentBits + $bits;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->currentBytes += (int)floor($newBits / 8);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -697,6 +838,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $this->currentBits = $newBits % 8;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getBit() {
</span><span class="cx" style="display: block; padding: 0 10px">                $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01;
</span><span class="cx" style="display: block; padding: 0 10px">                $this->skipBits(1);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -703,6 +847,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $result;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $bits
+        *
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getBits($bits) {
</span><span class="cx" style="display: block; padding: 0 10px">                $result = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < $bits; $i++) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -711,6 +860,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $result;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function expGolombUe() {
</span><span class="cx" style="display: block; padding: 0 10px">                $significantBits = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $bit = $this->getBit();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -726,6 +878,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (1 << $significantBits) + $this->getBits($significantBits) - 1;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function expGolombSe() {
</span><span class="cx" style="display: block; padding: 0 10px">                $result = $this->expGolombUe();
</span><span class="cx" style="display: block; padding: 0 10px">                if (($result & 0x01) == 0) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -735,10 +890,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getWidth() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->width;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getHeight() {
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->height;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiovideomatroskaphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio-video.matroska.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio-video.matroska.php 2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio-video.matroska.php   2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio-video.matriska.php                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing Matroska containers                    //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -72,7 +72,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> define('EBML_ID_FILEDESCRIPTION',               0x067E); //         [46][7E] -- A human-friendly name for the attached file.
</span><span class="cx" style="display: block; padding: 0 10px"> define('EBML_ID_FILEUID',                       0x06AE); //         [46][AE] -- Unique ID representing the file, as random as possible.
</span><span class="cx" style="display: block; padding: 0 10px"> define('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:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-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.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+define('EBML_ID_CONTENTENCKEYID',               0x07E2); //         [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with.
</ins><span class="cx" style="display: block; padding: 0 10px"> define('EBML_ID_CONTENTSIGNATURE',              0x07E3); //         [47][E3] -- A cryptographic signature of the contents.
</span><span class="cx" style="display: block; padding: 0 10px"> define('EBML_ID_CONTENTSIGKEYID',               0x07E4); //         [47][E4] -- This is the ID of the private key the data was signed with.
</span><span class="cx" style="display: block; padding: 0 10px"> define('EBML_ID_CONTENTSIGALGO',                0x07E5); //         [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -215,11 +215,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_matroska extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // public options
-       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]
-       public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * If true, do not return information about CLUSTER chunks, since there's a lot of them
+        * and they're not usually useful [default: TRUE].
+        *
+        * @var bool
+        */
+       public static $hide_clusters    = true;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // private parser settings/placeholders
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * True to parse the whole file, not only header [default: FALSE].
+        *
+        * @var bool
+        */
+       public static $parse_whole_file = false;
+
+       /*
+        * Private parser settings/placeholders.
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private $EBMLbuffer        = '';
</span><span class="cx" style="display: block; padding: 0 10px">        private $EBMLbuffer_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">        private $EBMLbuffer_length = 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -226,6 +239,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        private $current_offset    = 0;
</span><span class="cx" style="display: block; padding: 0 10px">        private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze()
</span><span class="cx" style="display: block; padding: 0 10px">        {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -366,8 +382,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if (!empty($getid3_temp->info[$header_data_key])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                foreach ($getid3_temp->info['audio'] as $key => $value) {
-                                                                                       $track_info[$key] = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
+                                                                                       $track_info[$sub_key] = $value;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -421,8 +437,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if (!empty($getid3_temp->info['ogg'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                foreach ($getid3_temp->info['audio'] as $key => $value) {
-                                                                                       $track_info[$key] = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         foreach ($getid3_temp->info['audio'] as $sub_key => $value) {
+                                                                                       $track_info[$sub_key] = $value;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -449,9 +465,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                foreach ($parsed as $key => $value) {
-                                                                       if ($key != 'raw') {
-                                                                               $track_info[$key] = $value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         foreach ($parsed as $sub_key => $value) {
+                                                                       if ($sub_key != 'raw') {
+                                                                               $track_info[$sub_key] = $value;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -496,6 +512,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $info
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function parseEBML(&$info) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/index.html#EBMLBasics
</span><span class="cx" style="display: block; padding: 0 10px">                $this->current_offset = $info['avdataoffset'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1228,6 +1247,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $min_data
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function EnsureBufferHasEnoughData($min_data=1024) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $read_bytes = max($min_data, $this->getid3->fread_buffer_size());
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1249,6 +1273,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return int|float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function readEBMLint() {
</span><span class="cx" style="display: block; padding: 0 10px">                $actual_offset = $this->current_offset - $this->EBMLbuffer_offset;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1281,6 +1308,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $int_value;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int  $length
+        * @param bool $check_buffer
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function readEBMLelementData($length, $check_buffer=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1290,6 +1323,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array      $element
+        * @param int        $parent_end
+        * @param array|bool $get_data
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function getEBMLelement(&$element, $parent_end, $get_data=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->current_offset >= $parent_end) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1326,6 +1366,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $type
+        * @param int    $line
+        * @param array  $element
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function unhandledElement($type, $line, $element) {
</span><span class="cx" style="display: block; padding: 0 10px">                // warn only about unknown and missed elements, not about unuseful
</span><span class="cx" style="display: block; padding: 0 10px">                if (!in_array($element['id'], $this->unuseful_elements)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1338,6 +1383,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $SimpleTagArray
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function ExtractCommentsSimpleTag($SimpleTagArray) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (!empty($SimpleTagArray['SimpleTag'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1353,6 +1403,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $parent_end
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function HandleEMBLSimpleTag($parent_end) {
</span><span class="cx" style="display: block; padding: 0 10px">                $simpletag_entry = array();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1383,6 +1438,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $simpletag_entry;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $element
+        * @param int   $block_type
+        * @param array $info
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function HandleEMBLClusterBlock($element, $block_type, &$info) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/index.html#block_structure
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/index.html#simpleblock_structure
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1446,6 +1508,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $block_data;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $EBMLstring
+        *
+        * @return int|float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private static function EBML2Int($EBMLstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://matroska.org/specs/
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1488,6 +1555,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::BigEndian2Int($EBMLstring);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $EBMLdatestamp
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private static function EBMLdate2unix($EBMLdatestamp) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC)
</span><span class="cx" style="display: block; padding: 0 10px">                // 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1494,6 +1566,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return round(($EBMLdatestamp / 1000000000) + 978307200);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $target_type
+        *
+        * @return string|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TargetTypeValue($target_type) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/tagging/index.html
</span><span class="cx" style="display: block; padding: 0 10px">                static $TargetTypeValue = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1509,6 +1586,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $lacingtype
+        *
+        * @return string|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function BlockLacingType($lacingtype) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://matroska.org/technical/specs/index.html#block_structure
</span><span class="cx" style="display: block; padding: 0 10px">                static $BlockLacingType = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1521,6 +1603,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $codecid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function CodecIDtoCommonName($codecid) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/codecid/index.html
</span><span class="cx" style="display: block; padding: 0 10px">                static $CodecIDlist = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1557,6 +1644,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $value
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private static function EBMLidName($value) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $EBMLidList = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($EBMLidList)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1755,6 +1847,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $value
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function displayUnit($value) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.matroska.org/technical/specs/index.html#DisplayUnit
</span><span class="cx" style="display: block; padding: 0 10px">                static $units = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1766,8 +1863,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($units[$value]) ? $units[$value] : 'unknown');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $streams
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private static function getDefaultStreamInfo($streams)
</span><span class="cx" style="display: block; padding: 0 10px">        {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $stream = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach (array_reverse($streams) as $stream) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($stream['default']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiovideoquicktimephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio-video.quicktime.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio-video.quicktime.php        2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio-video.quicktime.php  2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio-video.quicktime.php                            //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing Quicktime and MP3-in-MP4 files         //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,6 +24,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public $ReturnAtomData        = true;
</span><span class="cx" style="display: block; padding: 0 10px">        public $ParseAllPossibleAtoms = false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -35,7 +38,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $offset      = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $atomcounter = 0;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $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]
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $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]
</ins><span class="cx" style="display: block; padding: 0 10px">                 while ($offset < $info['avdataend']) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!getid3_lib::intValueSupported($offset)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,6 +165,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $info['audio']['bitrate'] = $info['bitrate'];
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                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'])) {
+                       $info['video']['bitrate'] = $info['bitrate'] - $info['audio']['bitrate'];
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $samples_per_second = $samples_count / $info['playtime_seconds'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -193,10 +199,23 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $info['video']['dataformat'] = 'quicktime';
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y']))  {
+                       unset($info['video']);
+               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $atomname
+        * @param int    $atomsize
+        * @param string $atom_data
+        * @param int    $baseoffset
+        * @param array  $atomHierarchy
+        * @param bool   $ParseAllPossibleAtoms
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
</span><span class="cx" style="display: block; padding: 0 10px">                // https://code.google.com/p/mp4v2/wiki/iTunesMetadata
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -203,308 +222,330 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717
</ins><span class="cx" style="display: block; padding: 0 10px">                 array_push($atomHierarchy, $atomname);
</span><span class="cx" style="display: block; padding: 0 10px">                $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
</span><span class="cx" style="display: block; padding: 0 10px">                $atom_structure['name']      = $atomname;
</span><span class="cx" style="display: block; padding: 0 10px">                $atom_structure['size']      = $atomsize;
</span><span class="cx" style="display: block; padding: 0 10px">                $atom_structure['offset']    = $baseoffset;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                switch ($atomname) {
-                       case 'moov': // MOVie container atom
-                       case 'trak': // TRAcK container atom
-                       case 'clip': // CLIPping container atom
-                       case 'matt': // track MATTe container atom
-                       case 'edts': // EDiTS container atom
-                       case 'tref': // Track REFerence container atom
-                       case 'mdia': // MeDIA container atom
-                       case 'minf': // Media INFormation container atom
-                       case 'dinf': // Data INFormation container atom
-                       case 'udta': // User DaTA container atom
-                       case 'cmov': // Compressed MOVie container atom
-                       case 'rmra': // Reference Movie Record Atom
-                       case 'rmda': // Reference Movie Descriptor Atom
-                       case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
-                               $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (substr($atomname, 0, 3) == "\x00\x00\x00") {
+                       // https://github.com/JamesHeinrich/getID3/issues/139
+                       $atomname = getid3_lib::BigEndian2Int($atomname);
+                       $atom_structure['name'] = $atomname;
+                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+               } else {
+                       switch ($atomname) {
+                               case 'moov': // MOVie container atom
+                               case 'trak': // TRAcK container atom
+                               case 'clip': // CLIPping container atom
+                               case 'matt': // track MATTe container atom
+                               case 'edts': // EDiTS container atom
+                               case 'tref': // Track REFerence container atom
+                               case 'mdia': // MeDIA container atom
+                               case 'minf': // Media INFormation container atom
+                               case 'dinf': // Data INFormation container atom
+                               case 'udta': // User DaTA container atom
+                               case 'cmov': // Compressed MOVie container atom
+                               case 'rmra': // Reference Movie Record Atom
+                               case 'rmda': // Reference Movie Descriptor Atom
+                               case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
+                                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ilst': // Item LiST container atom
-                               if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
-                                       // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
-                                       $allnumericnames = true;
-                                       foreach ($atom_structure['subatoms'] as $subatomarray) {
-                                               if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
-                                                       $allnumericnames = false;
-                                                       break;
-                                               }
-                                       }
-                                       if ($allnumericnames) {
-                                               $newData = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'ilst': // Item LiST container atom
+                                       if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
+                                               // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
+                                               $allnumericnames = true;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 foreach ($atom_structure['subatoms'] as $subatomarray) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
-                                                               unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
-                                                               $newData[$subatomarray['name']] = $newData_subatomarray;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
+                                                               $allnumericnames = false;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 break;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $atom_structure['data'] = $newData;
-                                               unset($atom_structure['subatoms']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if ($allnumericnames) {
+                                                       $newData = array();
+                                                       foreach ($atom_structure['subatoms'] as $subatomarray) {
+                                                               foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
+                                                                       unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
+                                                                       $newData[$subatomarray['name']] = $newData_subatomarray;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       $atom_structure['data'] = $newData;
+                                                       unset($atom_structure['subatoms']);
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case "\x00\x00\x00\x01":
-                       case "\x00\x00\x00\x02":
-                       case "\x00\x00\x00\x03":
-                       case "\x00\x00\x00\x04":
-                       case "\x00\x00\x00\x05":
-                               $atomname = getid3_lib::BigEndian2Int($atomname);
-                               $atom_structure['name'] = $atomname;
-                               $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               break;
-
-                       case 'stbl': // Sample TaBLe container atom
-                               $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               $isVideo = false;
-                               $framerate  = 0;
-                               $framecount = 0;
-                               foreach ($atom_structure['subatoms'] as $key => $value_array) {
-                                       if (isset($value_array['sample_description_table'])) {
-                                               foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
-                                                       if (isset($value_array2['data_format'])) {
-                                                               switch ($value_array2['data_format']) {
-                                                                       case 'avc1':
-                                                                       case 'mp4v':
-                                                                               // video data
-                                                                               $isVideo = true;
-                                                                               break;
-                                                                       case 'mp4a':
-                                                                               // audio data
-                                                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stbl': // Sample TaBLe container atom
+                                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       $isVideo = false;
+                                       $framerate  = 0;
+                                       $framecount = 0;
+                                       foreach ($atom_structure['subatoms'] as $key => $value_array) {
+                                               if (isset($value_array['sample_description_table'])) {
+                                                       foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
+                                                               if (isset($value_array2['data_format'])) {
+                                                                       switch ($value_array2['data_format']) {
+                                                                               case 'avc1':
+                                                                               case 'mp4v':
+                                                                                       // video data
+                                                                                       $isVideo = true;
+                                                                                       break;
+                                                                               case 'mp4a':
+                                                                                       // audio data
+                                                                                       break;
+                                                                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                }
-                                       } elseif (isset($value_array['time_to_sample_table'])) {
-                                               foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
-                                                       if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
-                                                               $framerate  = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
-                                                               $framecount = $value_array2['sample_count'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         } elseif (isset($value_array['time_to_sample_table'])) {
+                                                       foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
+                                                               if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
+                                                                       $framerate  = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
+                                                                       $framecount = $value_array2['sample_count'];
+                                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               if ($isVideo && $framerate) {
-                                       $info['quicktime']['video']['frame_rate'] = $framerate;
-                                       $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
-                               }
-                               if ($isVideo && $framecount) {
-                                       $info['quicktime']['video']['frame_count'] = $framecount;
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($isVideo && $framerate) {
+                                               $info['quicktime']['video']['frame_rate'] = $framerate;
+                                               $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
+                                       }
+                                       if ($isVideo && $framecount) {
+                                               $info['quicktime']['video']['frame_count'] = $framecount;
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case "\xA9".'alb': // ALBum
-                       case "\xA9".'ART': //
-                       case "\xA9".'art': // ARTist
-                       case "\xA9".'aut': //
-                       case "\xA9".'cmt': // CoMmenT
-                       case "\xA9".'com': // COMposer
-                       case "\xA9".'cpy': //
-                       case "\xA9".'day': // content created year
-                       case "\xA9".'dir': //
-                       case "\xA9".'ed1': //
-                       case "\xA9".'ed2': //
-                       case "\xA9".'ed3': //
-                       case "\xA9".'ed4': //
-                       case "\xA9".'ed5': //
-                       case "\xA9".'ed6': //
-                       case "\xA9".'ed7': //
-                       case "\xA9".'ed8': //
-                       case "\xA9".'ed9': //
-                       case "\xA9".'enc': //
-                       case "\xA9".'fmt': //
-                       case "\xA9".'gen': // GENre
-                       case "\xA9".'grp': // GRouPing
-                       case "\xA9".'hst': //
-                       case "\xA9".'inf': //
-                       case "\xA9".'lyr': // LYRics
-                       case "\xA9".'mak': //
-                       case "\xA9".'mod': //
-                       case "\xA9".'nam': // full NAMe
-                       case "\xA9".'ope': //
-                       case "\xA9".'PRD': //
-                       case "\xA9".'prf': //
-                       case "\xA9".'req': //
-                       case "\xA9".'src': //
-                       case "\xA9".'swr': //
-                       case "\xA9".'too': // encoder
-                       case "\xA9".'trk': // TRacK
-                       case "\xA9".'url': //
-                       case "\xA9".'wrn': //
-                       case "\xA9".'wrt': // WRiTer
-                       case '----': // itunes specific
-                       case 'aART': // Album ARTist
-                       case 'akID': // iTunes store account type
-                       case 'apID': // Purchase Account
-                       case 'atID': //
-                       case 'catg': // CaTeGory
-                       case 'cmID': //
-                       case 'cnID': //
-                       case 'covr': // COVeR artwork
-                       case 'cpil': // ComPILation
-                       case 'cprt': // CoPyRighT
-                       case 'desc': // DESCription
-                       case 'disk': // DISK number
-                       case 'egid': // Episode Global ID
-                       case 'geID': //
-                       case 'gnre': // GeNRE
-                       case 'hdvd': // HD ViDeo
-                       case 'keyw': // KEYWord
-                       case 'ldes': // Long DEScription
-                       case 'pcst': // PodCaST
-                       case 'pgap': // GAPless Playback
-                       case 'plID': //
-                       case 'purd': // PURchase Date
-                       case 'purl': // Podcast URL
-                       case 'rati': //
-                       case 'rndu': //
-                       case 'rpdu': //
-                       case 'rtng': // RaTiNG
-                       case 'sfID': // iTunes store country
-                       case 'soaa': // SOrt Album Artist
-                       case 'soal': // SOrt ALbum
-                       case 'soar': // SOrt ARtist
-                       case 'soco': // SOrt COmposer
-                       case 'sonm': // SOrt NaMe
-                       case 'sosn': // SOrt Show Name
-                       case 'stik': //
-                       case 'tmpo': // TeMPO (BPM)
-                       case 'trkn': // TRacK Number
-                       case 'tven': // tvEpisodeID
-                       case 'tves': // TV EpiSode
-                       case 'tvnn': // TV Network Name
-                       case 'tvsh': // TV SHow Name
-                       case 'tvsn': // TV SeasoN
-                               if ($atom_parent == 'udta') {
-                                       // User data atom handler
-                                       $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
-                                       $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
-                                       $atom_structure['data']        =                           substr($atom_data, 4);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case "\xA9".'alb': // ALBum
+                               case "\xA9".'ART': //
+                               case "\xA9".'art': // ARTist
+                               case "\xA9".'aut': //
+                               case "\xA9".'cmt': // CoMmenT
+                               case "\xA9".'com': // COMposer
+                               case "\xA9".'cpy': //
+                               case "\xA9".'day': // content created year
+                               case "\xA9".'dir': //
+                               case "\xA9".'ed1': //
+                               case "\xA9".'ed2': //
+                               case "\xA9".'ed3': //
+                               case "\xA9".'ed4': //
+                               case "\xA9".'ed5': //
+                               case "\xA9".'ed6': //
+                               case "\xA9".'ed7': //
+                               case "\xA9".'ed8': //
+                               case "\xA9".'ed9': //
+                               case "\xA9".'enc': //
+                               case "\xA9".'fmt': //
+                               case "\xA9".'gen': // GENre
+                               case "\xA9".'grp': // GRouPing
+                               case "\xA9".'hst': //
+                               case "\xA9".'inf': //
+                               case "\xA9".'lyr': // LYRics
+                               case "\xA9".'mak': //
+                               case "\xA9".'mod': //
+                               case "\xA9".'nam': // full NAMe
+                               case "\xA9".'ope': //
+                               case "\xA9".'PRD': //
+                               case "\xA9".'prf': //
+                               case "\xA9".'req': //
+                               case "\xA9".'src': //
+                               case "\xA9".'swr': //
+                               case "\xA9".'too': // encoder
+                               case "\xA9".'trk': // TRacK
+                               case "\xA9".'url': //
+                               case "\xA9".'wrn': //
+                               case "\xA9".'wrt': // WRiTer
+                               case '----': // itunes specific
+                               case 'aART': // Album ARTist
+                               case 'akID': // iTunes store account type
+                               case 'apID': // Purchase Account
+                               case 'atID': //
+                               case 'catg': // CaTeGory
+                               case 'cmID': //
+                               case 'cnID': //
+                               case 'covr': // COVeR artwork
+                               case 'cpil': // ComPILation
+                               case 'cprt': // CoPyRighT
+                               case 'desc': // DESCription
+                               case 'disk': // DISK number
+                               case 'egid': // Episode Global ID
+                               case 'geID': //
+                               case 'gnre': // GeNRE
+                               case 'hdvd': // HD ViDeo
+                               case 'keyw': // KEYWord
+                               case 'ldes': // Long DEScription
+                               case 'pcst': // PodCaST
+                               case 'pgap': // GAPless Playback
+                               case 'plID': //
+                               case 'purd': // PURchase Date
+                               case 'purl': // Podcast URL
+                               case 'rati': //
+                               case 'rndu': //
+                               case 'rpdu': //
+                               case 'rtng': // RaTiNG
+                               case 'sfID': // iTunes store country
+                               case 'soaa': // SOrt Album Artist
+                               case 'soal': // SOrt ALbum
+                               case 'soar': // SOrt ARtist
+                               case 'soco': // SOrt COmposer
+                               case 'sonm': // SOrt NaMe
+                               case 'sosn': // SOrt Show Name
+                               case 'stik': //
+                               case 'tmpo': // TeMPO (BPM)
+                               case 'trkn': // TRacK Number
+                               case 'tven': // tvEpisodeID
+                               case 'tves': // TV EpiSode
+                               case 'tvnn': // TV Network Name
+                               case 'tvsh': // TV SHow Name
+                               case 'tvsn': // TV SeasoN
+                                       if ($atom_parent == 'udta') {
+                                               // User data atom handler
+                                               $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
+                                               $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
+                                               $atom_structure['data']        =                           substr($atom_data, 4);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
-                                       if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
-                                               $info['comments']['language'][] = $atom_structure['language'];
-                                       }
-                               } else {
-                                       // Apple item list box atom handler
-                                       $atomoffset = 0;
-                                       if (substr($atom_data, 2, 2) == "\x10\xB5") {
-                                               // not sure what it means, but observed on iPhone4 data.
-                                               // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
-                                               while ($atomoffset < strlen($atom_data)) {
-                                                       $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
-                                                       $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
-                                                       $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
-                                                       if ($boxsmallsize <= 1) {
-                                                               $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
-                                                               $atom_structure['data'] = null;
-                                                               $atomoffset = strlen($atom_data);
-                                                               break;
-                                                       }
-                                                       switch ($boxsmalltype) {
-                                                               case "\x10\xB5":
-                                                                       $atom_structure['data'] = $boxsmalldata;
-                                                                       break;
-                                                               default:
-                                                                       $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
-                                                                       $atom_structure['data'] = $atom_data;
-                                                                       break;
-                                                       }
-                                                       $atomoffset += (4 + $boxsmallsize);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+                                               if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+                                                       $info['comments']['language'][] = $atom_structure['language'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                        } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                while ($atomoffset < strlen($atom_data)) {
-                                                       $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
-                                                       $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
-                                                       $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
-                                                       if ($boxsize <= 1) {
-                                                               $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
-                                                               $atom_structure['data'] = null;
-                                                               $atomoffset = strlen($atom_data);
-                                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         // Apple item list box atom handler
+                                               $atomoffset = 0;
+                                               if (substr($atom_data, 2, 2) == "\x10\xB5") {
+                                                       // not sure what it means, but observed on iPhone4 data.
+                                                       // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
+                                                       while ($atomoffset < strlen($atom_data)) {
+                                                               $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
+                                                               $boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
+                                                               $boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
+                                                               if ($boxsmallsize <= 1) {
+                                                                       $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
+                                                                       $atom_structure['data'] = null;
+                                                                       $atomoffset = strlen($atom_data);
+                                                                       break;
+                                                               }
+                                                               switch ($boxsmalltype) {
+                                                                       case "\x10\xB5":
+                                                                               $atom_structure['data'] = $boxsmalldata;
+                                                                               break;
+                                                                       default:
+                                                                               $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
+                                                                               $atom_structure['data'] = $atom_data;
+                                                                               break;
+                                                               }
+                                                               $atomoffset += (4 + $boxsmallsize);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $atomoffset += $boxsize;
-
-                                                       switch ($boxtype) {
-                                                               case 'mean':
-                                                               case 'name':
-                                                                       $atom_structure[$boxtype] = substr($boxdata, 4);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         } else {
+                                                       while ($atomoffset < strlen($atom_data)) {
+                                                               $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
+                                                               $boxtype =                           substr($atom_data, $atomoffset + 4, 4);
+                                                               $boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
+                                                               if ($boxsize <= 1) {
+                                                                       $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
+                                                                       $atom_structure['data'] = null;
+                                                                       $atomoffset = strlen($atom_data);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         break;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                }
+                                                               $atomoffset += $boxsize;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                case 'data':
-                                                                       $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
-                                                                       $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
-                                                                       switch ($atom_structure['flags_raw']) {
-                                                                               case  0: // data flag
-                                                                               case 21: // tmpo/cpil flag
-                                                                                       switch ($atomname) {
-                                                                                               case 'cpil':
-                                                                                               case 'hdvd':
-                                                                                               case 'pcst':
-                                                                                               case 'pgap':
-                                                                                                       // 8-bit integer (boolean)
-                                                                                                       $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         switch ($boxtype) {
+                                                                       case 'mean':
+                                                                       case 'name':
+                                                                               $atom_structure[$boxtype] = substr($boxdata, 4);
+                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'tmpo':
-                                                                                                       // 16-bit integer
-                                                                                                       $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 case 'data':
+                                                                               $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
+                                                                               $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
+                                                                               switch ($atom_structure['flags_raw']) {
+                                                                                       case  0: // data flag
+                                                                                       case 21: // tmpo/cpil flag
+                                                                                               switch ($atomname) {
+                                                                                                       case 'cpil':
+                                                                                                       case 'hdvd':
+                                                                                                       case 'pcst':
+                                                                                                       case 'pgap':
+                                                                                                               // 8-bit integer (boolean)
+                                                                                                               $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'disk':
-                                                                                               case 'trkn':
-                                                                                                       // binary
-                                                                                                       $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
-                                                                                                       $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
-                                                                                                       $atom_structure['data']  = empty($num) ? '' : $num;
-                                                                                                       $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'tmpo':
+                                                                                                               // 16-bit integer
+                                                                                                               $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'gnre':
-                                                                                                       // enum
-                                                                                                       $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
-                                                                                                       $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'disk':
+                                                                                                       case 'trkn':
+                                                                                                               // binary
+                                                                                                               $num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
+                                                                                                               $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
+                                                                                                               $atom_structure['data']  = empty($num) ? '' : $num;
+                                                                                                               $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'rtng':
-                                                                                                       // 8-bit integer
-                                                                                                       $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
-                                                                                                       $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'gnre':
+                                                                                                               // enum
+                                                                                                               $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+                                                                                                               $atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'stik':
-                                                                                                       // 8-bit integer (enum)
-                                                                                                       $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
-                                                                                                       $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'rtng':
+                                                                                                               // 8-bit integer
+                                                                                                               $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+                                                                                                               $atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'sfID':
-                                                                                                       // 32-bit integer
-                                                                                                       $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
-                                                                                                       $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'stik':
+                                                                                                               // 8-bit integer (enum)
+                                                                                                               $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
+                                                                                                               $atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'egid':
-                                                                                               case 'purl':
-                                                                                                       $atom_structure['data'] = substr($boxdata, 8);
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'sfID':
+                                                                                                               // 32-bit integer
+                                                                                                               $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+                                                                                                               $atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'plID':
-                                                                                                       // 64-bit integer
-                                                                                                       $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
-                                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'egid':
+                                                                                                       case 'purl':
+                                                                                                               $atom_structure['data'] = substr($boxdata, 8);
+                                                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                case 'covr':
-                                                                                                       $atom_structure['data'] = substr($boxdata, 8);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                                 case 'plID':
+                                                                                                               // 64-bit integer
+                                                                                                               $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
+                                                                                                               break;
+
+                                                                                                       case 'covr':
+                                                                                                               $atom_structure['data'] = substr($boxdata, 8);
+                                                                                                               // not a foolproof check, but better than nothing
+                                                                                                               if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
+                                                                                                                       $atom_structure['image_mime'] = 'image/jpeg';
+                                                                                                               } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
+                                                                                                                       $atom_structure['image_mime'] = 'image/png';
+                                                                                                               } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
+                                                                                                                       $atom_structure['image_mime'] = 'image/gif';
+                                                                                                               }
+                                                                                                               break;
+
+                                                                                                       case 'atID':
+                                                                                                       case 'cnID':
+                                                                                                       case 'geID':
+                                                                                                       case 'tves':
+                                                                                                       case 'tvsn':
+                                                                                                       default:
+                                                                                                               // 32-bit integer
+                                                                                                               $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
+                                                                                               }
+                                                                                               break;
+
+                                                                                       case  1: // text flag
+                                                                                       case 13: // image flag
+                                                                                       default:
+                                                                                               $atom_structure['data'] = substr($boxdata, 8);
+                                                                                               if ($atomname == 'covr') {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                                         // not a foolproof check, but better than nothing
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $atom_structure['image_mime'] = 'image/jpeg';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -513,1214 +554,1312 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                                $atom_structure['image_mime'] = 'image/gif';
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                                        break;
-
-                                                                                               case 'atID':
-                                                                                               case 'cnID':
-                                                                                               case 'geID':
-                                                                                               case 'tves':
-                                                                                               case 'tvsn':
-                                                                                               default:
-                                                                                                       // 32-bit integer
-                                                                                                       $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
-                                                                                       }
-                                                                                       break;
-
-                                                                               case  1: // text flag
-                                                                               case 13: // image flag
-                                                                               default:
-                                                                                       $atom_structure['data'] = substr($boxdata, 8);
-                                                                                       if ($atomname == 'covr') {
-                                                                                               // not a foolproof check, but better than nothing
-                                                                                               if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
-                                                                                                       $atom_structure['image_mime'] = 'image/jpeg';
-                                                                                               } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
-                                                                                                       $atom_structure['image_mime'] = 'image/png';
-                                                                                               } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
-                                                                                                       $atom_structure['image_mime'] = 'image/gif';
</del><span class="cx" style="display: block; padding: 0 10px">                                                                                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                        }
-                                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                         break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                        }
-                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         }
+                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                default:
-                                                                       $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
-                                                                       $atom_structure['data'] = $atom_data;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 default:
+                                                                               $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
+                                                                               $atom_structure['data'] = $atom_data;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'play': // auto-PLAY atom
-                               $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'play': // auto-PLAY atom
+                                       $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['quicktime']['autoplay'] = $atom_structure['autoplay'];
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $info['quicktime']['autoplay'] = $atom_structure['autoplay'];
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'WLOC': // Window LOCation atom
-                               $atom_structure['location_x']  = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2));
-                               $atom_structure['location_y']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 2));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'WLOC': // Window LOCation atom
+                                       $atom_structure['location_x']  = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2));
+                                       $atom_structure['location_y']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 2));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'LOOP': // LOOPing atom
-                       case 'SelO': // play SELection Only atom
-                       case 'AllF': // play ALL Frames atom
-                               $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'LOOP': // LOOPing atom
+                               case 'SelO': // play SELection Only atom
+                               case 'AllF': // play ALL Frames atom
+                                       $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'name': //
-                       case 'MCPS': // Media Cleaner PRo
-                       case '@PRM': // adobe PReMiere version
-                       case '@PRQ': // adobe PRemiere Quicktime version
-                               $atom_structure['data'] = $atom_data;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'name': //
+                               case 'MCPS': // Media Cleaner PRo
+                               case '@PRM': // adobe PReMiere version
+                               case '@PRQ': // adobe PRemiere Quicktime version
+                                       $atom_structure['data'] = $atom_data;
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'cmvd': // Compressed MooV Data atom
-                               // Code by ubergeekØubergeek*tv based on information from
-                               // http://developer.apple.com/quicktime/icefloe/dispatch012.html
-                               $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'cmvd': // Compressed MooV Data atom
+                                       // Code by ubergeekØubergeek*tv based on information from
+                                       // http://developer.apple.com/quicktime/icefloe/dispatch012.html
+                                       $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $CompressedFileData = substr($atom_data, 4);
-                               if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
-                                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
-                               } else {
-                                       $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $CompressedFileData = substr($atom_data, 4);
+                                       if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
+                                               $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       } else {
+                                               $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'dcom': // Data COMpression atom
-                               $atom_structure['compression_id']   = $atom_data;
-                               $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'dcom': // Data COMpression atom
+                                       $atom_structure['compression_id']   = $atom_data;
+                                       $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rdrf': // Reference movie Data ReFerence atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
-                               $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rdrf': // Reference movie Data ReFerence atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
+                                       $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['reference_type_name']    =                           substr($atom_data,  4, 4);
-                               $atom_structure['reference_length']       = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               switch ($atom_structure['reference_type_name']) {
-                                       case 'url ':
-                                               $atom_structure['url']            =       $this->NoNullString(substr($atom_data, 12));
-                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['reference_type_name']    =                           substr($atom_data,  4, 4);
+                                       $atom_structure['reference_length']       = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       switch ($atom_structure['reference_type_name']) {
+                                               case 'url ':
+                                                       $atom_structure['url']            =       $this->NoNullString(substr($atom_data, 12));
+                                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        case 'alis':
-                                               $atom_structure['file_alias']     =                           substr($atom_data, 12);
-                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         case 'alis':
+                                                       $atom_structure['file_alias']     =                           substr($atom_data, 12);
+                                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        case 'rsrc':
-                                               $atom_structure['resource_alias'] =                           substr($atom_data, 12);
-                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         case 'rsrc':
+                                                       $atom_structure['resource_alias'] =                           substr($atom_data, 12);
+                                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        default:
-                                               $atom_structure['data']           =                           substr($atom_data, 12);
-                                               break;
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         default:
+                                                       $atom_structure['data']           =                           substr($atom_data, 12);
+                                                       break;
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmqu': // Reference Movie QUality atom
-                               $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmqu': // Reference Movie QUality atom
+                                       $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmcs': // Reference Movie Cpu Speed atom
-                               $atom_structure['version']          = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']        = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmcs': // Reference Movie Cpu Speed atom
+                                       $atom_structure['version']          = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']        = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmvc': // Reference Movie Version Check atom
-                               $atom_structure['version']            = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']          = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['gestalt_selector']   =                           substr($atom_data,  4, 4);
-                               $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               $atom_structure['gestalt_value']      = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
-                               $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmvc': // Reference Movie Version Check atom
+                                       $atom_structure['version']            = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']          = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['gestalt_selector']   =                           substr($atom_data,  4, 4);
+                                       $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       $atom_structure['gestalt_value']      = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+                                       $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmcd': // Reference Movie Component check atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
-                               $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
-                               $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
-                               $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
-                               $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
-                               $atom_structure['component_min_version']  = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmcd': // Reference Movie Component check atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
+                                       $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
+                                       $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
+                                       $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+                                       $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+                                       $atom_structure['component_min_version']  = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmdr': // Reference Movie Data Rate atom
-                               $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['data_rate']     = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmdr': // Reference Movie Data Rate atom
+                                       $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['data_rate']     = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmla': // Reference Movie Language Atom
-                               $atom_structure['version']     = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']   = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'rmla': // Reference Movie Language Atom
+                                       $atom_structure['version']     = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']   = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
-                               if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
-                                       $info['comments']['language'][] = $atom_structure['language'];
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+                                       if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+                                               $info['comments']['language'][] = $atom_structure['language'];
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'rmla': // Reference Movie Language Atom
-                               $atom_structure['version']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['track_id']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'ptv ': // Print To Video - defines a movie's full screen mode
+                                       // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
+                                       $atom_structure['display_size_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
+                                       $atom_structure['reserved_1']        = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
+                                       $atom_structure['reserved_2']        = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
+                                       $atom_structure['slide_show_flag']   = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
+                                       $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
+                                       $atom_structure['flags']['slide_show']   = (bool) $atom_structure['slide_show_flag'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ptv ': // Print To Video - defines a movie's full screen mode
-                               // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
-                               $atom_structure['display_size_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
-                               $atom_structure['reserved_1']        = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
-                               $atom_structure['reserved_2']        = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
-                               $atom_structure['slide_show_flag']   = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
-                               $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $ptv_lookup[0] = 'normal';
+                                       $ptv_lookup[1] = 'double';
+                                       $ptv_lookup[2] = 'half';
+                                       $ptv_lookup[3] = 'full';
+                                       $ptv_lookup[4] = 'current';
+                                       if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
+                                               $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
+                                       } else {
+                                               $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
-                               $atom_structure['flags']['slide_show']   = (bool) $atom_structure['slide_show_flag'];
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $ptv_lookup[0] = 'normal';
-                               $ptv_lookup[1] = 'double';
-                               $ptv_lookup[2] = 'half';
-                               $ptv_lookup[3] = 'full';
-                               $ptv_lookup[4] = 'current';
-                               if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
-                                       $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
-                               } else {
-                                       $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stsd': // Sample Table Sample Description atom
+                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        // see: https://github.com/JamesHeinrich/getID3/issues/111
+                                       // Some corrupt files have been known to have high bits set in the number_entries field
+                                       // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
+                                       // Workaround: mask off the upper byte and throw a warning if it's nonzero
+                                       if ($atom_structure['number_entries'] > 0x000FFFFF) {
+                                               if ($atom_structure['number_entries'] > 0x00FFFFFF) {
+                                                       $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));
+                                                       $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
+                                               } else {
+                                                       $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');
+                                               }
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stsd': // Sample Table Sample Description atom
-                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $stsdEntriesDataOffset = 8;
+                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+                                               $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
+                                               $stsdEntriesDataOffset += 4;
+                                               $atom_structure['sample_description_table'][$i]['data_format']      =                           substr($atom_data, $stsdEntriesDataOffset, 4);
+                                               $stsdEntriesDataOffset += 4;
+                                               $atom_structure['sample_description_table'][$i]['reserved']         = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
+                                               $stsdEntriesDataOffset += 6;
+                                               $atom_structure['sample_description_table'][$i]['reference_index']  = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
+                                               $stsdEntriesDataOffset += 2;
+                                               $atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
+                                               $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // see: https://github.com/JamesHeinrich/getID3/issues/111
-                               // Some corrupt files have been known to have high bits set in the number_entries field
-                               // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
-                               // Workaround: mask off the upper byte and throw a warning if it's nonzero
-                               if ($atom_structure['number_entries'] > 0x000FFFFF) {
-                                       if ($atom_structure['number_entries'] > 0x00FFFFFF) {
-                                               $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));
-                                               $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
-                                       } else {
-                                               $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');
-                                       }
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
+                                               $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
+                                               $atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $stsdEntriesDataOffset = 8;
-                               for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
-                                       $atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
-                                       $stsdEntriesDataOffset += 4;
-                                       $atom_structure['sample_description_table'][$i]['data_format']      =                           substr($atom_data, $stsdEntriesDataOffset, 4);
-                                       $stsdEntriesDataOffset += 4;
-                                       $atom_structure['sample_description_table'][$i]['reserved']         = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
-                                       $stsdEntriesDataOffset += 6;
-                                       $atom_structure['sample_description_table'][$i]['reference_index']  = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
-                                       $stsdEntriesDataOffset += 2;
-                                       $atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
-                                       $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
-                                       $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
-                                       $atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 case "\x00\x00\x00\x00":
+                                                               // audio tracks
+                                                               $atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
+                                                               $atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
+                                                               $atom_structure['sample_description_table'][$i]['audio_compression_id'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  2));
+                                                               $atom_structure['sample_description_table'][$i]['audio_packet_size']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14,  2));
+                                                               $atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         // video tracks
+                                                               // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
+                                                               $atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
+                                                               $atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
+                                                               $atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
+                                                               $atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
+                                                               $atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
+                                                               $atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
+                                                               $atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
+                                                               $atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
+                                                               $atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
+                                                               $atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
+                                                               $atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                case "\x00\x00\x00\x00":
-                                                       // audio tracks
-                                                       $atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
-                                                       $atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
-                                                       $atom_structure['sample_description_table'][$i]['audio_compression_id'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  2));
-                                                       $atom_structure['sample_description_table'][$i]['audio_packet_size']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14,  2));
-                                                       $atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+                                                                       case '2vuY':
+                                                                       case 'avc1':
+                                                                       case 'cvid':
+                                                                       case 'dvc ':
+                                                                       case 'dvcp':
+                                                                       case 'gif ':
+                                                                       case 'h263':
+                                                                       case 'jpeg':
+                                                                       case 'kpcd':
+                                                                       case 'mjpa':
+                                                                       case 'mjpb':
+                                                                       case 'mp4v':
+                                                                       case 'png ':
+                                                                       case 'raw ':
+                                                                       case 'rle ':
+                                                                       case 'rpza':
+                                                                       case 'smc ':
+                                                                       case 'SVQ1':
+                                                                       case 'SVQ3':
+                                                                       case 'tiff':
+                                                                       case 'v210':
+                                                                       case 'v216':
+                                                                       case 'v308':
+                                                                       case 'v408':
+                                                                       case 'v410':
+                                                                       case 'yuv2':
+                                                                               $info['fileformat'] = 'mp4';
+                                                                               $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
+                                                                               if ($this->QuicktimeVideoCodecLookup($info['video']['fourcc'])) {
+                                                                                       $info['video']['fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($info['video']['fourcc']);
+                                                                               }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        // video tracks
-                                                       // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
-                                                       $atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
-                                                       $atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
-                                                       $atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
-                                                       $atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
-                                                       $atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
-                                                       $atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
-                                                       $atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
-                                                       $atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
-                                                       $atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
-                                                       $atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
-                                                       $atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         // https://www.getid3.org/phpBB3/viewtopic.php?t=1550
+                                                                               //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
+                                                                               if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
+                                                                                       // assume that values stored here are more important than values stored in [tkhd] atom
+                                                                                       $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
+                                                                                       $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
+                                                                                       $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
+                                                                                       $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
+                                                                               }
+                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        switch ($atom_structure['sample_description_table'][$i]['data_format']) {
-                                                               case '2vuY':
-                                                               case 'avc1':
-                                                               case 'cvid':
-                                                               case 'dvc ':
-                                                               case 'dvcp':
-                                                               case 'gif ':
-                                                               case 'h263':
-                                                               case 'jpeg':
-                                                               case 'kpcd':
-                                                               case 'mjpa':
-                                                               case 'mjpb':
-                                                               case 'mp4v':
-                                                               case 'png ':
-                                                               case 'raw ':
-                                                               case 'rle ':
-                                                               case 'rpza':
-                                                               case 'smc ':
-                                                               case 'SVQ1':
-                                                               case 'SVQ3':
-                                                               case 'tiff':
-                                                               case 'v210':
-                                                               case 'v216':
-                                                               case 'v308':
-                                                               case 'v408':
-                                                               case 'v410':
-                                                               case 'yuv2':
-                                                                       $info['fileformat'] = 'mp4';
-                                                                       $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
-// http://www.getid3.org/phpBB3/viewtopic.php?t=1550
-//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
-if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
-       // assume that values stored here are more important than values stored in [tkhd] atom
-       $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
-       $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
-       $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
-       $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
-}
-                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 case 'qtvr':
+                                                                               $info['video']['dataformat'] = 'quicktimevr';
+                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                case 'qtvr':
-                                                                       $info['video']['dataformat'] = 'quicktimevr';
-                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 case 'mp4a':
+                                                                       default:
+                                                                               $info['quicktime']['audio']['codec']       = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
+                                                                               $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
+                                                                               $info['quicktime']['audio']['channels']    = $atom_structure['sample_description_table'][$i]['audio_channels'];
+                                                                               $info['quicktime']['audio']['bit_depth']   = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
+                                                                               $info['audio']['codec']                    = $info['quicktime']['audio']['codec'];
+                                                                               $info['audio']['sample_rate']              = $info['quicktime']['audio']['sample_rate'];
+                                                                               $info['audio']['channels']                 = $info['quicktime']['audio']['channels'];
+                                                                               $info['audio']['bits_per_sample']          = $info['quicktime']['audio']['bit_depth'];
+                                                                               switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+                                                                                       case 'raw ': // PCM
+                                                                                       case 'alac': // Apple Lossless Audio Codec
+                                                                                       case 'sowt': // signed/two's complement (Little Endian)
+                                                                                       case 'twos': // signed/two's complement (Big Endian)
+                                                                                       case 'in24': // 24-bit Integer
+                                                                                       case 'in32': // 32-bit Integer
+                                                                                       case 'fl32': // 32-bit Floating Point
+                                                                                       case 'fl64': // 64-bit Floating Point
+                                                                                               $info['audio']['lossless'] = $info['quicktime']['audio']['lossless'] = true;
+                                                                                               $info['audio']['bitrate']  = $info['quicktime']['audio']['bitrate']  = $info['audio']['channels'] * $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'];
+                                                                                               break;
+                                                                                       default:
+                                                                                               $info['audio']['lossless'] = false;
+                                                                                               break;
+                                                                               }
+                                                                               break;
+                                                               }
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                case 'mp4a':
-                                                               default:
-                                                                       $info['quicktime']['audio']['codec']       = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
-                                                                       $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
-                                                                       $info['quicktime']['audio']['channels']    = $atom_structure['sample_description_table'][$i]['audio_channels'];
-                                                                       $info['quicktime']['audio']['bit_depth']   = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
-                                                                       $info['audio']['codec']                    = $info['quicktime']['audio']['codec'];
-                                                                       $info['audio']['sample_rate']              = $info['quicktime']['audio']['sample_rate'];
-                                                                       $info['audio']['channels']                 = $info['quicktime']['audio']['channels'];
-                                                                       $info['audio']['bits_per_sample']          = $info['quicktime']['audio']['bit_depth'];
-                                                                       switch ($atom_structure['sample_description_table'][$i]['data_format']) {
-                                                                               case 'raw ': // PCM
-                                                                               case 'alac': // Apple Lossless Audio Codec
-                                                                                       $info['audio']['lossless'] = true;
-                                                                                       break;
-                                                                               default:
-                                                                                       $info['audio']['lossless'] = false;
-                                                                                       break;
-                                                                       }
-                                                                       break;
-                                                       }
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 default:
+                                                               switch ($atom_structure['sample_description_table'][$i]['data_format']) {
+                                                                       case 'mp4s':
+                                                                               $info['fileformat'] = 'mp4';
+                                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                default:
-                                                       switch ($atom_structure['sample_description_table'][$i]['data_format']) {
-                                                               case 'mp4s':
-                                                                       $info['fileformat'] = 'mp4';
-                                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 default:
+                                                                               // video atom
+                                                                               $atom_structure['sample_description_table'][$i]['video_temporal_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
+                                                                               $atom_structure['sample_description_table'][$i]['video_spatial_quality']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
+                                                                               $atom_structure['sample_description_table'][$i]['video_frame_width']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
+                                                                               $atom_structure['sample_description_table'][$i]['video_frame_height']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
+                                                                               $atom_structure['sample_description_table'][$i]['video_resolution_x']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20,  4));
+                                                                               $atom_structure['sample_description_table'][$i]['video_resolution_y']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
+                                                                               $atom_structure['sample_description_table'][$i]['video_data_size']         =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
+                                                                               $atom_structure['sample_description_table'][$i]['video_frame_count']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  2));
+                                                                               $atom_structure['sample_description_table'][$i]['video_encoder_name_len']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34,  1));
+                                                                               $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']);
+                                                                               $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66,  2));
+                                                                               $atom_structure['sample_description_table'][$i]['video_color_table_id']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68,  2));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                default:
-                                                                       // video atom
-                                                                       $atom_structure['sample_description_table'][$i]['video_temporal_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
-                                                                       $atom_structure['sample_description_table'][$i]['video_spatial_quality']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
-                                                                       $atom_structure['sample_description_table'][$i]['video_frame_width']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
-                                                                       $atom_structure['sample_description_table'][$i]['video_frame_height']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
-                                                                       $atom_structure['sample_description_table'][$i]['video_resolution_x']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20,  4));
-                                                                       $atom_structure['sample_description_table'][$i]['video_resolution_y']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
-                                                                       $atom_structure['sample_description_table'][$i]['video_data_size']         =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
-                                                                       $atom_structure['sample_description_table'][$i]['video_frame_count']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  2));
-                                                                       $atom_structure['sample_description_table'][$i]['video_encoder_name_len']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34,  1));
-                                                                       $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']);
-                                                                       $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66,  2));
-                                                                       $atom_structure['sample_description_table'][$i]['video_color_table_id']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68,  2));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $atom_structure['sample_description_table'][$i]['video_pixel_color_type']  = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
+                                                                               $atom_structure['sample_description_table'][$i]['video_pixel_color_name']  = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                        $atom_structure['sample_description_table'][$i]['video_pixel_color_type']  = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
-                                                                       $atom_structure['sample_description_table'][$i]['video_pixel_color_name']  = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
+                                                                                       $info['quicktime']['video']['codec_fourcc']        = $atom_structure['sample_description_table'][$i]['data_format'];
+                                                                                       $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
+                                                                                       $info['quicktime']['video']['codec']               = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
+                                                                                       $info['quicktime']['video']['color_depth']         = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
+                                                                                       $info['quicktime']['video']['color_depth_name']    = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                        if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
-                                                                               $info['quicktime']['video']['codec_fourcc']        = $atom_structure['sample_description_table'][$i]['data_format'];
-                                                                               $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
-                                                                               $info['quicktime']['video']['codec']               = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
-                                                                               $info['quicktime']['video']['color_depth']         = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
-                                                                               $info['quicktime']['video']['color_depth_name']    = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                 $info['video']['codec']           = $info['quicktime']['video']['codec'];
+                                                                                       $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
+                                                                               }
+                                                                               $info['video']['lossless']           = false;
+                                                                               $info['video']['pixel_aspect_ratio'] = (float) 1;
+                                                                               break;
+                                                               }
+                                                               break;
+                                               }
+                                               switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
+                                                       case 'mp4a':
+                                                               $info['audio']['dataformat']         = 'mp4';
+                                                               $info['quicktime']['audio']['codec'] = 'mp4';
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                $info['video']['codec']           = $info['quicktime']['video']['codec'];
-                                                                               $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
-                                                                       }
-                                                                       $info['video']['lossless']           = false;
-                                                                       $info['video']['pixel_aspect_ratio'] = (float) 1;
-                                                                       break;
-                                                       }
-                                                       break;
-                                       }
-                                       switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
-                                               case 'mp4a':
-                                                       $info['audio']['dataformat']         = 'mp4';
-                                                       $info['quicktime']['audio']['codec'] = 'mp4';
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 case '3ivx':
+                                                       case '3iv1':
+                                                       case '3iv2':
+                                                               $info['video']['dataformat'] = '3ivx';
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                case '3ivx':
-                                               case '3iv1':
-                                               case '3iv2':
-                                                       $info['video']['dataformat'] = '3ivx';
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 case 'xvid':
+                                                               $info['video']['dataformat'] = 'xvid';
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                case 'xvid':
-                                                       $info['video']['dataformat'] = 'xvid';
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 case 'mp4v':
+                                                               $info['video']['dataformat'] = 'mpeg4';
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                case 'mp4v':
-                                                       $info['video']['dataformat'] = 'mpeg4';
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 case 'divx':
+                                                       case 'div1':
+                                                       case 'div2':
+                                                       case 'div3':
+                                                       case 'div4':
+                                                       case 'div5':
+                                                       case 'div6':
+                                                               $info['video']['dataformat'] = 'divx';
+                                                               break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                case 'divx':
-                                               case 'div1':
-                                               case 'div2':
-                                               case 'div3':
-                                               case 'div4':
-                                               case 'div5':
-                                               case 'div6':
-                                                       $info['video']['dataformat'] = 'divx';
-                                                       break;
-
-                                               default:
-                                                       // do nothing
-                                                       break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 default:
+                                                               // do nothing
+                                                               break;
+                                               }
+                                               unset($atom_structure['sample_description_table'][$i]['data']);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        unset($atom_structure['sample_description_table'][$i]['data']);
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stts': // Sample Table Time-to-Sample atom
-                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $sttsEntriesDataOffset = 8;
-                               //$FrameRateCalculatorArray = array();
-                               $frames_count = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stts': // Sample Table Time-to-Sample atom
+                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $sttsEntriesDataOffset = 8;
+                                       //$FrameRateCalculatorArray = array();
+                                       $frames_count = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
-                               if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
-                                       $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).');
-                               }
-                               for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
-                                       $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
-                                       $sttsEntriesDataOffset += 4;
-                                       $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
-                                       $sttsEntriesDataOffset += 4;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
+                                       if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
+                                               $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).');
+                                       }
+                                       for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
+                                               $atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
+                                               $sttsEntriesDataOffset += 4;
+                                               $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
+                                               $sttsEntriesDataOffset += 4;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
-                                       //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
-                                       //      $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
-                                       //      if ($stts_new_framerate <= 60) {
-                                       //              // some atoms have durations of "1" giving a very large framerate, which probably is not right
-                                       //              $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
+                                               //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
+                                               //      $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
+                                               //      if ($stts_new_framerate <= 60) {
+                                               //              // some atoms have durations of "1" giving a very large framerate, which probably is not right
+                                               //              $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
+                                               //      }
+                                               //}
+                                               //
+                                               //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
+                                       }
+                                       $info['quicktime']['stts_framecount'][] = $frames_count;
+                                       //$sttsFramesTotal  = 0;
+                                       //$sttsSecondsTotal = 0;
+                                       //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
+                                       //      if (($frames_per_second > 60) || ($frames_per_second < 1)) {
+                                       //              // not video FPS information, probably audio information
+                                       //              $sttsFramesTotal  = 0;
+                                       //              $sttsSecondsTotal = 0;
+                                       //              break;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         //      }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        //      $sttsFramesTotal  += $frame_count;
+                                       //      $sttsSecondsTotal += $frame_count / $frames_per_second;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         //}
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        //
-                                       //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
-                               }
-                               $info['quicktime']['stts_framecount'][] = $frames_count;
-                               //$sttsFramesTotal  = 0;
-                               //$sttsSecondsTotal = 0;
-                               //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
-                               //      if (($frames_per_second > 60) || ($frames_per_second < 1)) {
-                               //              // not video FPS information, probably audio information
-                               //              $sttsFramesTotal  = 0;
-                               //              $sttsSecondsTotal = 0;
-                               //              break;
-                               //      }
-                               //      $sttsFramesTotal  += $frame_count;
-                               //      $sttsSecondsTotal += $frame_count / $frames_per_second;
-                               //}
-                               //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
-                               //      if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
-                               //              $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
-                               //      }
-                               //}
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
+                                       //      if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
+                                       //              $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
+                                       //      }
+                                       //}
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stss': // Sample Table Sync Sample (key frames) atom
-                               if ($ParseAllPossibleAtoms) {
-                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                                       $stssEntriesDataOffset = 8;
-                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
-                                               $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
-                                               $stssEntriesDataOffset += 4;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stss': // Sample Table Sync Sample (key frames) atom
+                                       if ($ParseAllPossibleAtoms) {
+                                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                               $stssEntriesDataOffset = 8;
+                                               for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+                                                       $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
+                                                       $stssEntriesDataOffset += 4;
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stsc': // Sample Table Sample-to-Chunk atom
-                               if ($ParseAllPossibleAtoms) {
-                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                                       $stscEntriesDataOffset = 8;
-                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
-                                               $atom_structure['sample_to_chunk_table'][$i]['first_chunk']        = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
-                                               $stscEntriesDataOffset += 4;
-                                               $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk']  = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
-                                               $stscEntriesDataOffset += 4;
-                                               $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
-                                               $stscEntriesDataOffset += 4;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stsc': // Sample Table Sample-to-Chunk atom
+                                       if ($ParseAllPossibleAtoms) {
+                                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                               $stscEntriesDataOffset = 8;
+                                               for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+                                                       $atom_structure['sample_to_chunk_table'][$i]['first_chunk']        = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+                                                       $stscEntriesDataOffset += 4;
+                                                       $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk']  = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+                                                       $stscEntriesDataOffset += 4;
+                                                       $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
+                                                       $stscEntriesDataOffset += 4;
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stsz': // Sample Table SiZe atom
-                               if ($ParseAllPossibleAtoms) {
-                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                                       $atom_structure['sample_size']    = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                                       $stszEntriesDataOffset = 12;
-                                       if ($atom_structure['sample_size'] == 0) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'stsz': // Sample Table SiZe atom
+                                       if ($ParseAllPossibleAtoms) {
+                                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                               $atom_structure['sample_size']    = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                               $stszEntriesDataOffset = 12;
+                                               if ($atom_structure['sample_size'] == 0) {
+                                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+                                                               $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
+                                                               $stszEntriesDataOffset += 4;
+                                                       }
+                                               }
+                                       }
+                                       break;
+
+
+                               case 'stco': // Sample Table Chunk Offset atom
+                                       if ($ParseAllPossibleAtoms) {
+                                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                               $stcoEntriesDataOffset = 8;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
-                                                       $stszEntriesDataOffset += 4;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4));
+                                                       $stcoEntriesDataOffset += 4;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'stco': // Sample Table Chunk Offset atom
-                               if ($ParseAllPossibleAtoms) {
-                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                                       $stcoEntriesDataOffset = 8;
-                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
-                                               $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4));
-                                               $stcoEntriesDataOffset += 4;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
+                                       if ($ParseAllPossibleAtoms) {
+                                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                               $stcoEntriesDataOffset = 8;
+                                               for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
+                                                       $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8));
+                                                       $stcoEntriesDataOffset += 8;
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
-                               if ($ParseAllPossibleAtoms) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'dref': // Data REFerence atom
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
</span><span class="cx" style="display: block; padding: 0 10px">                                        $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $stcoEntriesDataOffset = 8;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $drefDataOffset = 8;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8));
-                                               $stcoEntriesDataOffset += 8;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $atom_structure['data_references'][$i]['size']                    = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
+                                               $drefDataOffset += 4;
+                                               $atom_structure['data_references'][$i]['type']                    =                           substr($atom_data, $drefDataOffset, 4);
+                                               $drefDataOffset += 4;
+                                               $atom_structure['data_references'][$i]['version']                 = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 1));
+                                               $drefDataOffset += 1;
+                                               $atom_structure['data_references'][$i]['flags_raw']               = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 3)); // hardcoded: 0x0000
+                                               $drefDataOffset += 3;
+                                               $atom_structure['data_references'][$i]['data']                    =                           substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
+                                               $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
+
+                                               $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'dref': // Data REFerence atom
-                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $drefDataOffset = 8;
-                               for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
-                                       $atom_structure['data_references'][$i]['size']                    = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
-                                       $drefDataOffset += 4;
-                                       $atom_structure['data_references'][$i]['type']                    =                           substr($atom_data, $drefDataOffset, 4);
-                                       $drefDataOffset += 4;
-                                       $atom_structure['data_references'][$i]['version']                 = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 1));
-                                       $drefDataOffset += 1;
-                                       $atom_structure['data_references'][$i]['flags_raw']               = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 3)); // hardcoded: 0x0000
-                                       $drefDataOffset += 3;
-                                       $atom_structure['data_references'][$i]['data']                    =                           substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
-                                       $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'gmin': // base Media INformation atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
+                                       $atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
+                                       $atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
+                                       $atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
+                                       $atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
+                                       $atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
-                               }
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'smhd': // Sound Media information HeaDer atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
+                                       $atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'gmin': // base Media INformation atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
-                               $atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
-                               $atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
-                               $atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
-                               $atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
-                               $atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'vmhd': // Video Media information HeaDer atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
+                                       $atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
+                                       $atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
+                                       $atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
+                                       $atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'smhd': // Sound Media information HeaDer atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
-                               $atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'vmhd': // Video Media information HeaDer atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
-                               $atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
-                               $atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
-                               $atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
-                               $atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'hdlr': // HanDLeR reference atom
+                                       $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
+                                       $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
+                                       $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
+                                       $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+                                       $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+                                       $atom_structure['component_name']         =      $this->Pascal2String(substr($atom_data, 24));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
+                                               $info['video']['dataformat'] = 'quicktimevr';
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'hdlr': // HanDLeR reference atom
-                               $atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['component_type']         =                           substr($atom_data,  4, 4);
-                               $atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
-                               $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
-                               $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
-                               $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
-                               $atom_structure['component_name']         =      $this->Pascal2String(substr($atom_data, 24));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'mdhd': // MeDia HeaDer atom
+                                       $atom_structure['version']               = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']             = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['creation_time']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $atom_structure['modify_time']           = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       $atom_structure['time_scale']            = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+                                       $atom_structure['duration']              = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+                                       $atom_structure['language_id']           = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2));
+                                       $atom_structure['quality']               = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
-                                       $info['video']['dataformat'] = 'quicktimevr';
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($atom_structure['time_scale'] == 0) {
+                                               $this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
+                                               return false;
+                                       }
+                                       $info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        $atom_structure['creation_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+                                       $atom_structure['modify_time_unix']      = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+                                       $atom_structure['playtime_seconds']      = $atom_structure['duration'] / $atom_structure['time_scale'];
+                                       $atom_structure['language']              = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
+                                       if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
+                                               $info['comments']['language'][] = $atom_structure['language'];
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'mdhd': // MeDia HeaDer atom
-                               $atom_structure['version']               = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']             = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['creation_time']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $atom_structure['modify_time']           = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               $atom_structure['time_scale']            = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
-                               $atom_structure['duration']              = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
-                               $atom_structure['language_id']           = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2));
-                               $atom_structure['quality']               = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ($atom_structure['time_scale'] == 0) {
-                                       $this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
-                                       return false;
-                               }
-                               $info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'pnot': // Preview atom
+                                       $atom_structure['modification_date']      = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // "standard Macintosh format"
+                                       $atom_structure['version_number']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x00
+                                       $atom_structure['atom_type']              =                           substr($atom_data,  6, 4);        // usually: 'PICT'
+                                       $atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['creation_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
-                               $atom_structure['modify_time_unix']      = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
-                               $atom_structure['playtime_seconds']      = $atom_structure['duration'] / $atom_structure['time_scale'];
-                               $atom_structure['language']              = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
-                               if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
-                                       $info['comments']['language'][] = $atom_structure['language'];
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'pnot': // Preview atom
-                               $atom_structure['modification_date']      = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // "standard Macintosh format"
-                               $atom_structure['version_number']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x00
-                               $atom_structure['atom_type']              =                           substr($atom_data,  6, 4);        // usually: 'PICT'
-                               $atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'crgn': // Clipping ReGioN atom
+                                       $atom_structure['region_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2)); // The Region size, Region boundary box,
+                                       $atom_structure['boundary_box']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 8)); // and Clipping region data fields
+                                       $atom_structure['clipping_data'] =                           substr($atom_data, 10);           // constitute a QuickDraw region.
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'load': // track LOAD settings atom
+                                       $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
+                                       $atom_structure['preload_duration']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $atom_structure['preload_flags_raw']  = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       $atom_structure['default_hints_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'crgn': // Clipping ReGioN atom
-                               $atom_structure['region_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2)); // The Region size, Region boundary box,
-                               $atom_structure['boundary_box']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 8)); // and Clipping region data fields
-                               $atom_structure['clipping_data'] =                           substr($atom_data, 10);           // constitute a QuickDraw region.
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
+                                       $atom_structure['default_hints']['high_quality']  = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'load': // track LOAD settings atom
-                               $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
-                               $atom_structure['preload_duration']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $atom_structure['preload_flags_raw']  = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               $atom_structure['default_hints_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'tmcd': // TiMe CoDe atom
+                               case 'chap': // CHAPter list atom
+                               case 'sync': // SYNChronization atom
+                               case 'scpt': // tranSCriPT atom
+                               case 'ssrc': // non-primary SouRCe atom
+                                       for ($i = 0; $i < strlen($atom_data); $i += 4) {
+                                               @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
-                               $atom_structure['default_hints']['high_quality']  = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'elst': // Edit LiST atom
+                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
+                                               $atom_structure['edit_list'][$i]['track_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
+                                               $atom_structure['edit_list'][$i]['media_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
+                                               $atom_structure['edit_list'][$i]['media_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'tmcd': // TiMe CoDe atom
-                       case 'chap': // CHAPter list atom
-                       case 'sync': // SYNChronization atom
-                       case 'scpt': // tranSCriPT atom
-                       case 'ssrc': // non-primary SouRCe atom
-                               for ($i = 0; $i < strlen($atom_data); $i += 4) {
-                                       @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
-                               }
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'kmat': // compressed MATte atom
+                                       $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
+                                       $atom_structure['matte_data_raw'] =               substr($atom_data,  4);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'elst': // Edit LiST atom
-                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
-                                       $atom_structure['edit_list'][$i]['track_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
-                                       $atom_structure['edit_list'][$i]['media_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
-                                       $atom_structure['edit_list'][$i]['media_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
-                               }
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'ctab': // Color TABle atom
+                                       $atom_structure['color_table_seed']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // hardcoded: 0x00000000
+                                       $atom_structure['color_table_flags']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x8000
+                                       $atom_structure['color_table_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2)) + 1;
+                                       for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
+                                               $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
+                                               $atom_structure['color_table'][$colortableentry]['red']   = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
+                                               $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
+                                               $atom_structure['color_table'][$colortableentry]['blue']  = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'kmat': // compressed MATte atom
-                               $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
-                               $atom_structure['matte_data_raw'] =               substr($atom_data,  4);
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'mvhd': // MoVie HeaDer atom
+                                       $atom_structure['version']            =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']          =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
+                                       $atom_structure['creation_time']      =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $atom_structure['modify_time']        =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       $atom_structure['time_scale']         =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+                                       $atom_structure['duration']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+                                       $atom_structure['preferred_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
+                                       $atom_structure['preferred_volume']   =   getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
+                                       $atom_structure['reserved']           =                             substr($atom_data, 26, 10);
+                                       $atom_structure['matrix_a']           = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
+                                       $atom_structure['matrix_b']           = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
+                                       $atom_structure['matrix_u']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
+                                       $atom_structure['matrix_c']           = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
+                                       $atom_structure['matrix_d']           = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
+                                       $atom_structure['matrix_v']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
+                                       $atom_structure['matrix_x']           = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
+                                       $atom_structure['matrix_y']           = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
+                                       $atom_structure['matrix_w']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
+                                       $atom_structure['preview_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
+                                       $atom_structure['preview_duration']   =   getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
+                                       $atom_structure['poster_time']        =   getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
+                                       $atom_structure['selection_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
+                                       $atom_structure['selection_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
+                                       $atom_structure['current_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
+                                       $atom_structure['next_track_id']      =   getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ctab': // Color TABle atom
-                               $atom_structure['color_table_seed']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // hardcoded: 0x00000000
-                               $atom_structure['color_table_flags']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x8000
-                               $atom_structure['color_table_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2)) + 1;
-                               for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
-                                       $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
-                                       $atom_structure['color_table'][$colortableentry]['red']   = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
-                                       $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
-                                       $atom_structure['color_table'][$colortableentry]['blue']  = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($atom_structure['time_scale'] == 0) {
+                                               $this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
+                                               return false;
+                                       }
+                                       $atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+                                       $atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+                                       $info['quicktime']['time_scale']    = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
+                                       $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
+                                       $info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'mvhd': // MoVie HeaDer atom
-                               $atom_structure['version']            =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']          =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
-                               $atom_structure['creation_time']      =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $atom_structure['modify_time']        =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               $atom_structure['time_scale']         =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
-                               $atom_structure['duration']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
-                               $atom_structure['preferred_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
-                               $atom_structure['preferred_volume']   =   getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
-                               $atom_structure['reserved']           =                             substr($atom_data, 26, 10);
-                               $atom_structure['matrix_a']           = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
-                               $atom_structure['matrix_b']           = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
-                               $atom_structure['matrix_u']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
-                               $atom_structure['matrix_c']           = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
-                               $atom_structure['matrix_d']           = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
-                               $atom_structure['matrix_v']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
-                               $atom_structure['matrix_x']           = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
-                               $atom_structure['matrix_y']           = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
-                               $atom_structure['matrix_w']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
-                               $atom_structure['preview_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
-                               $atom_structure['preview_duration']   =   getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
-                               $atom_structure['poster_time']        =   getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
-                               $atom_structure['selection_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
-                               $atom_structure['selection_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
-                               $atom_structure['current_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
-                               $atom_structure['next_track_id']      =   getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'tkhd': // TracK HeaDer atom
+                                       $atom_structure['version']             =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']           =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
+                                       $atom_structure['creation_time']       =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $atom_structure['modify_time']         =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
+                                       $atom_structure['trackid']             =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
+                                       $atom_structure['reserved1']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
+                                       $atom_structure['duration']            =   getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
+                                       $atom_structure['reserved2']           =   getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
+                                       $atom_structure['layer']               =   getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
+                                       $atom_structure['alternate_group']     =   getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
+                                       $atom_structure['volume']              =   getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
+                                       $atom_structure['reserved3']           =   getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
+                                       // http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
+                                       // http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
+                                       $atom_structure['matrix_a']            = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
+                                       $atom_structure['matrix_b']            = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
+                                       $atom_structure['matrix_u']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
+                                       $atom_structure['matrix_c']            = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
+                                       $atom_structure['matrix_d']            = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
+                                       $atom_structure['matrix_v']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
+                                       $atom_structure['matrix_x']            = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
+                                       $atom_structure['matrix_y']            = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
+                                       $atom_structure['matrix_w']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
+                                       $atom_structure['width']               = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
+                                       $atom_structure['height']              = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
+                                       $atom_structure['flags']['enabled']    = (bool) ($atom_structure['flags_raw'] & 0x0001);
+                                       $atom_structure['flags']['in_movie']   = (bool) ($atom_structure['flags_raw'] & 0x0002);
+                                       $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
+                                       $atom_structure['flags']['in_poster']  = (bool) ($atom_structure['flags_raw'] & 0x0008);
+                                       $atom_structure['creation_time_unix']  = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
+                                       $atom_structure['modify_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ($atom_structure['time_scale'] == 0) {
-                                       $this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
-                                       return false;
-                               }
-                               $atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
-                               $atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
-                               $info['quicktime']['time_scale']    = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
-                               $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
-                               $info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // https://www.getid3.org/phpBB3/viewtopic.php?t=1908
+                                       // attempt to compute rotation from matrix values
+                                       // 2017-Dec-28: uncertain if 90/270 are correctly oriented; values returned by FixedPoint16_16 should perhaps be -1 instead of 65535(?)
+                                       $matrixRotation = 0;
+                                       switch ($atom_structure['matrix_a'].':'.$atom_structure['matrix_b'].':'.$atom_structure['matrix_c'].':'.$atom_structure['matrix_d']) {
+                                               case '1:0:0:1':         $matrixRotation =   0; break;
+                                               case '0:1:65535:0':     $matrixRotation =  90; break;
+                                               case '65535:0:0:65535': $matrixRotation = 180; break;
+                                               case '0:65535:1:0':     $matrixRotation = 270; break;
+                                               default: break;
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        // https://www.getid3.org/phpBB3/viewtopic.php?t=2468
+                                       // The rotation matrix can appear in the Quicktime file multiple times, at least once for each track,
+                                       // and it's possible that only the video track (or, in theory, one of the video tracks) is flagged as
+                                       // rotated while the other tracks (e.g. audio) is tagged as rotation=0 (behavior noted on iPhone 8 Plus)
+                                       // The correct solution would be to check if the TrackID associated with the rotation matrix is indeed
+                                       // a video track (or the main video track) and only set the rotation then, but since information about
+                                       // what track is what is not trivially there to be examined, the lazy solution is to set the rotation
+                                       // if it is found to be nonzero, on the assumption that tracks that don't need it will have rotation set
+                                       // to zero (and be effectively ignored) and the video track will have rotation set correctly, which will
+                                       // either be zero and automatically correct, or nonzero and be set correctly.
+                                       if (!isset($info['video']['rotate']) || (($info['video']['rotate'] == 0) && ($matrixRotation > 0))) {
+                                               $info['quicktime']['video']['rotate'] = $info['video']['rotate'] = $matrixRotation;
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'tkhd': // TracK HeaDer atom
-                               $atom_structure['version']             =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']           =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
-                               $atom_structure['creation_time']       =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $atom_structure['modify_time']         =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
-                               $atom_structure['trackid']             =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
-                               $atom_structure['reserved1']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
-                               $atom_structure['duration']            =   getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
-                               $atom_structure['reserved2']           =   getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
-                               $atom_structure['layer']               =   getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
-                               $atom_structure['alternate_group']     =   getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
-                               $atom_structure['volume']              =   getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
-                               $atom_structure['reserved3']           =   getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
-// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
-// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
-                               $atom_structure['matrix_a']            = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
-                               $atom_structure['matrix_b']            = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
-                               $atom_structure['matrix_u']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
-                               $atom_structure['matrix_c']            = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
-                               $atom_structure['matrix_d']            = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
-                               $atom_structure['matrix_v']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
-                               $atom_structure['matrix_x']            = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
-                               $atom_structure['matrix_y']            = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
-                               $atom_structure['matrix_w']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
-                               $atom_structure['width']               = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
-                               $atom_structure['height']              = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
-                               $atom_structure['flags']['enabled']    = (bool) ($atom_structure['flags_raw'] & 0x0001);
-                               $atom_structure['flags']['in_movie']   = (bool) ($atom_structure['flags_raw'] & 0x0002);
-                               $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
-                               $atom_structure['flags']['in_poster']  = (bool) ($atom_structure['flags_raw'] & 0x0008);
-                               $atom_structure['creation_time_unix']  = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
-                               $atom_structure['modify_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
-
-                               if ($atom_structure['flags']['enabled'] == 1) {
-                                       if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
-                                               $info['video']['resolution_x'] = $atom_structure['width'];
-                                               $info['video']['resolution_y'] = $atom_structure['height'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($atom_structure['flags']['enabled'] == 1) {
+                                               if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
+                                                       $info['video']['resolution_x'] = $atom_structure['width'];
+                                                       $info['video']['resolution_y'] = $atom_structure['height'];
+                                               }
+                                               $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
+                                               $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
+                                               $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
+                                               $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
+                                       } else {
+                                               // see: https://www.getid3.org/phpBB3/viewtopic.php?t=1295
+                                               //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
+                                               //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
+                                               //if (isset($info['quicktime']['video']))    { unset($info['quicktime']['video']);    }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
-                                       $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
-                                       $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
-                                       $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
-                               } else {
-                                       // see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295
-                                       //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
-                                       //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
-                                       //if (isset($info['quicktime']['video']))    { unset($info['quicktime']['video']);    }
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'iods': // Initial Object DeScriptor atom
-                               // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
-                               // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
-                               $offset = 0;
-                               $atom_structure['version']                =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['flags_raw']              =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
-                               $offset += 3;
-                               $atom_structure['mp4_iod_tag']            =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['length']                 = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
-                               //$offset already adjusted by quicktime_read_mp4_descr_length()
-                               $atom_structure['object_descriptor_id']   =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
-                               $offset += 2;
-                               $atom_structure['od_profile_level']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['scene_profile_level']    =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['audio_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['video_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-                               $atom_structure['graphics_profile_level'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
-                               $offset += 1;
-
-                               $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
-                               for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
-                                       $atom_structure['track'][$i]['ES_ID_IncTag'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'iods': // Initial Object DeScriptor atom
+                                       // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
+                                       // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
+                                       $offset = 0;
+                                       $atom_structure['version']                =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $offset += 1;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['track'][$i]['length']       = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['flags_raw']              =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
+                                       $offset += 3;
+                                       $atom_structure['mp4_iod_tag']            =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
+                                       $atom_structure['length']                 = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         //$offset already adjusted by quicktime_read_mp4_descr_length()
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['track'][$i]['track_id']     =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
-                                       $offset += 4;
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['object_descriptor_id']   =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
+                                       $offset += 2;
+                                       $atom_structure['od_profile_level']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
+                                       $atom_structure['scene_profile_level']    =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
+                                       $atom_structure['audio_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
+                                       $atom_structure['video_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
+                                       $atom_structure['graphics_profile_level'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                       $offset += 1;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
-                               $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
+                                       for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
+                                               $atom_structure['track'][$i]['ES_ID_IncTag'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
+                                               $offset += 1;
+                                               $atom_structure['track'][$i]['length']       = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
+                                               //$offset already adjusted by quicktime_read_mp4_descr_length()
+                                               $atom_structure['track'][$i]['track_id']     =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
+                                               $offset += 4;
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ftyp': // FileTYPe (?) atom (for MP4 it seems)
-                               $atom_structure['signature'] =                           substr($atom_data,  0, 4);
-                               $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $atom_structure['fourcc']    =                           substr($atom_data,  8, 4);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
+                                       $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'mdat': // Media DATa atom
-                               // 'mdat' contains the actual data for the audio/video, possibly also subtitles
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'ftyp': // FileTYPe (?) atom (for MP4 it seems)
+                                       $atom_structure['signature'] =                           substr($atom_data,  0, 4);
+                                       $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $atom_structure['fourcc']    =                           substr($atom_data,  8, 4);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-/* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'mdat': // Media DATa atom
+                                       // 'mdat' contains the actual data for the audio/video, possibly also subtitles
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
-                               $mdat_offset = 0;
-                               while (true) {
-                                       if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
-                                               $mdat_offset += 8;
-                                       } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
-                                               $mdat_offset += 8;
-                                       } else {
-                                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
+
+                                       // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
+                                       $mdat_offset = 0;
+                                       while (true) {
+                                               if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
+                                                       $mdat_offset += 8;
+                                               } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
+                                                       $mdat_offset += 8;
+                                               } else {
+                                                       break;
+                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (substr($atom_data, $mdat_offset, 4) == 'GPRO') {
+                                               $GOPRO_chunk_length = getid3_lib::LittleEndian2Int(substr($atom_data, $mdat_offset + 4, 4));
+                                               $GOPRO_offset = 8;
+                                               $atom_structure['GPRO']['raw'] = substr($atom_data, $mdat_offset + 8, $GOPRO_chunk_length - 8);
+                                               $atom_structure['GPRO']['firmware'] = substr($atom_structure['GPRO']['raw'],  0, 15);
+                                               $atom_structure['GPRO']['unknown1'] = substr($atom_structure['GPRO']['raw'], 15, 16);
+                                               $atom_structure['GPRO']['unknown2'] = substr($atom_structure['GPRO']['raw'], 31, 32);
+                                               $atom_structure['GPRO']['unknown3'] = substr($atom_structure['GPRO']['raw'], 63, 16);
+                                               $atom_structure['GPRO']['camera']   = substr($atom_structure['GPRO']['raw'], 79, 32);
+                                               $info['quicktime']['camera']['model'] = rtrim($atom_structure['GPRO']['camera'], "\x00");
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
-                               while (($mdat_offset < (strlen($atom_data) - 8))
-                                       && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
-                                       && ($chapter_string_length < 1000)
-                                       && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
-                                       && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
-                                               list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
-                                               $mdat_offset += (2 + $chapter_string_length);
-                                               @$info['quicktime']['comments']['chapters'][] = $chapter_string;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
+                                       while (($mdat_offset < (strlen($atom_data) - 8))
+                                               && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
+                                               && ($chapter_string_length < 1000)
+                                               && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
+                                               && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
+                                                       list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
+                                                       $mdat_offset += (2 + $chapter_string_length);
+                                                       @$info['quicktime']['comments']['chapters'][] = $chapter_string;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
-                                               if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
-                                                       $mdat_offset += 12;
-                                               }
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
+                                                       if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
+                                                               $mdat_offset += 12;
+                                                       }
+                                       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
+                                               $OldAVDataEnd         = $info['avdataend'];
+                                               $info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
-                                       $OldAVDataEnd         = $info['avdataend'];
-                                       $info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
-
-                                       $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
-                                       $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
-                                       $getid3_temp->info['avdataend']    = $info['avdataend'];
-                                       $getid3_mp3 = new getid3_mp3($getid3_temp);
-                                       if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
-                                               $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
-                                               if (!empty($getid3_temp->info['warning'])) {
-                                                       foreach ($getid3_temp->info['warning'] as $value) {
-                                                               $this->warning($value);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $getid3_temp = new getID3();
+                                               $getid3_temp->openfile($this->getid3->filename);
+                                               $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
+                                               $getid3_temp->info['avdataend']    = $info['avdataend'];
+                                               $getid3_mp3 = new getid3_mp3($getid3_temp);
+                                               if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
+                                                       $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
+                                                       if (!empty($getid3_temp->info['warning'])) {
+                                                               foreach ($getid3_temp->info['warning'] as $value) {
+                                                                       $this->warning($value);
+                                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                }
-                                               if (!empty($getid3_temp->info['mpeg'])) {
-                                                       $info['mpeg'] = $getid3_temp->info['mpeg'];
-                                                       if (isset($info['mpeg']['audio'])) {
-                                                               $info['audio']['dataformat']   = 'mp3';
-                                                               $info['audio']['codec']        = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
-                                                               $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
-                                                               $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
-                                                               $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
-                                                               $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
-                                                               $info['bitrate']               = $info['audio']['bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 if (!empty($getid3_temp->info['mpeg'])) {
+                                                               $info['mpeg'] = $getid3_temp->info['mpeg'];
+                                                               if (isset($info['mpeg']['audio'])) {
+                                                                       $info['audio']['dataformat']   = 'mp3';
+                                                                       $info['audio']['codec']        = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
+                                                                       $info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
+                                                                       $info['audio']['channels']     = $info['mpeg']['audio']['channels'];
+                                                                       $info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
+                                                                       $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
+                                                                       $info['bitrate']               = $info['audio']['bitrate'];
+                                                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                unset($getid3_mp3, $getid3_temp);
+                                               $info['avdataend'] = $OldAVDataEnd;
+                                               unset($OldAVDataEnd);
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        unset($getid3_mp3, $getid3_temp);
-                                       $info['avdataend'] = $OldAVDataEnd;
-                                       unset($OldAVDataEnd);
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 unset($mdat_offset, $chapter_string_length, $chapter_matches);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                unset($mdat_offset, $chapter_string_length, $chapter_matches);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'free': // FREE space atom
+                               case 'skip': // SKIP atom
+                               case 'wide': // 64-bit expansion placeholder atom
+                                       // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'free': // FREE space atom
-                       case 'skip': // SKIP atom
-                       case 'wide': // 64-bit expansion placeholder atom
-                               // 'free', 'skip' and 'wide' are just padding, contains no useful data at all
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // When writing QuickTime files, it is sometimes necessary to update an atom's size.
+                                       // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
+                                       // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
+                                       // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
+                                       // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
+                                       // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
+                                       // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                // When writing QuickTime files, it is sometimes necessary to update an atom's size.
-                               // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
-                               // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
-                               // puts an 8-byte placeholder atom before any atoms it may have to update the size of.
-                               // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
-                               // placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
-                               // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                case 'nsav': // NoSAVe atom
+                                       // http://developer.apple.com/technotes/tn/tn2038.html
+                                       $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'nsav': // NoSAVe atom
-                               // http://developer.apple.com/technotes/tn/tn2038.html
-                               $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'ctyp': // Controller TYPe atom (seen on QTVR)
+                                       // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
+                                       // some controller names are:
+                                       //   0x00 + 'std' for linear movie
+                                       //   'none' for no controls
+                                       $atom_structure['ctyp'] = substr($atom_data, 0, 4);
+                                       $info['quicktime']['controller'] = $atom_structure['ctyp'];
+                                       switch ($atom_structure['ctyp']) {
+                                               case 'qtvr':
+                                                       $info['video']['dataformat'] = 'quicktimevr';
+                                                       break;
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'ctyp': // Controller TYPe atom (seen on QTVR)
-                               // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
-                               // some controller names are:
-                               //   0x00 + 'std' for linear movie
-                               //   'none' for no controls
-                               $atom_structure['ctyp'] = substr($atom_data, 0, 4);
-                               $info['quicktime']['controller'] = $atom_structure['ctyp'];
-                               switch ($atom_structure['ctyp']) {
-                                       case 'qtvr':
-                                               $info['video']['dataformat'] = 'quicktimevr';
-                                               break;
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'pano': // PANOrama track (seen on QTVR)
+                                       $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'pano': // PANOrama track (seen on QTVR)
-                               $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'hint': // HINT track
+                               case 'hinf': //
+                               case 'hinv': //
+                               case 'hnti': //
+                                       $info['quicktime']['hinting'] = true;
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'hint': // HINT track
-                       case 'hinf': //
-                       case 'hinv': //
-                       case 'hnti': //
-                               $info['quicktime']['hinting'] = true;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
+                                       for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) {
+                                               $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
-                               for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) {
-                                       $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
-                               }
-                               break;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
+                               case 'FXTC': // Something to do with Adobe After Effects (?)
+                               case 'PrmA':
+                               case 'code':
+                               case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
+                               case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
+                                                       // tapt seems to be used to compute the video size [https://www.getid3.org/phpBB3/viewtopic.php?t=838]
+                                                       // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
+                                                       // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
+                               case 'ctts'://  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+                               case 'cslg'://  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+                               case 'sdtp'://  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+                               case 'stps'://  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
+                                       //$atom_structure['data'] = $atom_data;
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // Observed-but-not-handled atom types are just listed here to prevent warnings being generated
-                       case 'FXTC': // Something to do with Adobe After Effects (?)
-                       case 'PrmA':
-                       case 'code':
-                       case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
-                       case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
-                                               // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
-                                               // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
-                                               // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
-                       case 'ctts'://  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
-                       case 'cslg'://  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
-                       case 'sdtp'://  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
-                       case 'stps'://  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
-                               //$atom_structure['data'] = $atom_data;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case "\xA9".'xyz':  // GPS latitude+longitude+altitude
+                                       $atom_structure['data'] = $atom_data;
+                                       if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
+                                               @list($all, $latitude, $longitude, $altitude) = $matches;
+                                               $info['quicktime']['comments']['gps_latitude'][]  = floatval($latitude);
+                                               $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
+                                               if (!empty($altitude)) {
+                                                       $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
+                                               }
+                                       } else {
+                                               $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case "\xA9".'xyz':  // GPS latitude+longitude+altitude
-                               $atom_structure['data'] = $atom_data;
-                               if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
-                                       @list($all, $latitude, $longitude, $altitude) = $matches;
-                                       $info['quicktime']['comments']['gps_latitude'][]  = floatval($latitude);
-                                       $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
-                                       if (!empty($altitude)) {
-                                               $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'NCDT':
+                                       // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+                                       // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
+                                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       break;
+                               case 'NCTH': // Nikon Camera THumbnail image
+                               case 'NCVW': // Nikon Camera preVieW image
+                                       // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+                                       if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) {
+                                               $atom_structure['data'] = $atom_data;
+                                               $atom_structure['image_mime'] = 'image/jpeg';
+                                               $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
+                                               $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else {
-                                       $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
-                               }
-                               break;
-
-                       case 'NCDT':
-                               // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
-                               // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
-                               $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
-                               break;
-                       case 'NCTH': // Nikon Camera THumbnail image
-                       case 'NCVW': // Nikon Camera preVieW image
-                               // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
-                               if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
+                               case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
+                                       $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
+                                       break;
+                               case 'NCHD': // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+                               case 'NCDB': // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+                               case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $atom_structure['data'] = $atom_data;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $atom_structure['image_mime'] = 'image/jpeg';
-                                       $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
-                                       $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
-                               }
-                               break;
-                       case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
-                               $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
-                               break;
-                       case 'NCHD': // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
-                       case 'NCDB': // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
-                       case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
-                               $atom_structure['data'] = $atom_data;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case "\x00\x00\x00\x00":
-                               // some kind of metacontainer, may contain a big data dump such as:
-                               // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
-                               // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case "\x00\x00\x00\x00":
+                                       // some kind of metacontainer, may contain a big data dump such as:
+                                       // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
+                                       // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
-                               $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
-                               $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               //$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+                                       $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+                                       $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       //$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'meta': // METAdata atom
-                               // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'meta': // METAdata atom
+                                       // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
-                               $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
-                               $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
+                                       $atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
+                                       $atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'data': // metaDATA atom
-                               static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
-                               // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
-                               $atom_structure['language'] =                           substr($atom_data, 4 + 0, 2);
-                               $atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
-                               $atom_structure['data']     =                           substr($atom_data, 4 + 4);
-                               $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'data': // metaDATA atom
+                                       static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
+                                       // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
+                                       $atom_structure['language'] =                           substr($atom_data, 4 + 0, 2);
+                                       $atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
+                                       $atom_structure['data']     =                           substr($atom_data, 4 + 4);
+                                       $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ($atom_structure['key_name'] && $atom_structure['data']) {
-                                       @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($atom_structure['key_name'] && $atom_structure['data']) {
+                                               @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'keys': // KEYS that may be present in the metadata atom.
-                               // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
-                               // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
-                               // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
-                               $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
-                               $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
-                               $atom_structure['entry_count']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
-                               $keys_atom_offset = 8;
-                               for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
-                                       $atom_structure['keys'][$i]['key_size']      = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
-                                       $atom_structure['keys'][$i]['key_namespace'] =                           substr($atom_data, $keys_atom_offset + 4, 4);
-                                       $atom_structure['keys'][$i]['key_value']     =                           substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
-                                       $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'keys': // KEYS that may be present in the metadata atom.
+                                       // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
+                                       // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
+                                       // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
+                                       $atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
+                                       $atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
+                                       $atom_structure['entry_count']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
+                                       $keys_atom_offset = 8;
+                                       for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
+                                               $atom_structure['keys'][$i]['key_size']      = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
+                                               $atom_structure['keys'][$i]['key_namespace'] =                           substr($atom_data, $keys_atom_offset + 4, 4);
+                                               $atom_structure['keys'][$i]['key_value']     =                           substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
+                                               $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'gps ':
-                               // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
-                               // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
-                               // The first row is version/metadata/notsure, I skip that.
-                               // The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'gps ':
+                                       // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
+                                       // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
+                                       // The first row is version/metadata/notsure, I skip that.
+                                       // The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file.
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size
-                               if (strlen($atom_data) > 0) {
-                                       if ((strlen($atom_data) % $GPS_rowsize) == 0) {
-                                               $atom_structure['gps_toc'] = array();
-                                               foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) {
-                                                       $atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize));
-                                               }
-
-                                               $atom_structure['gps_entries'] = array();
-                                               $previous_offset = $this->ftell();
-                                               foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) {
-                                                       if ($key == 0) {
-                                                               // "The first row is version/metadata/notsure, I skip that."
-                                                               continue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size
+                                       if (strlen($atom_data) > 0) {
+                                               if ((strlen($atom_data) % $GPS_rowsize) == 0) {
+                                                       $atom_structure['gps_toc'] = array();
+                                                       foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) {
+                                                               $atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize));
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $this->fseek($gps_pointer['offset']);
-                                                       $GPS_free_data = $this->fread($gps_pointer['size']);
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        /*
-                                                       // 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $atom_structure['gps_entries'] = array();
+                                                       $previous_offset = $this->ftell();
+                                                       foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) {
+                                                               if ($key == 0) {
+                                                                       // "The first row is version/metadata/notsure, I skip that."
+                                                                       continue;
+                                                               }
+                                                               $this->fseek($gps_pointer['offset']);
+                                                               $GPS_free_data = $this->fread($gps_pointer['size']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
-                                                       // The structure of the GPS data atom (the 'free' atoms mentioned above) is following:
-                                                       // hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48)
-                                                       // For those unfamiliar with python struct:
-                                                       // I = int
-                                                       // s = is string (size 1, in this case)
-                                                       // f = float
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         /*
+                                                               // 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        //$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48));
-                                                       */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
+                                                               // The structure of the GPS data atom (the 'free' atoms mentioned above) is following:
+                                                               // hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48)
+                                                               // For those unfamiliar with python struct:
+                                                               // I = int
+                                                               // s = is string (size 1, in this case)
+                                                               // f = float
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
-                                                       // $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67
-                                                       // $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F
-                                                       // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
-                                                       if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
-                                                               $GPS_this_GPRMC = array();
-                                                               list(
-                                                                       $GPS_this_GPRMC['raw']['gprmc'],
-                                                                       $GPS_this_GPRMC['raw']['timestamp'],
-                                                                       $GPS_this_GPRMC['raw']['status'],
-                                                                       $GPS_this_GPRMC['raw']['latitude'],
-                                                                       $GPS_this_GPRMC['raw']['latitude_direction'],
-                                                                       $GPS_this_GPRMC['raw']['longitude'],
-                                                                       $GPS_this_GPRMC['raw']['longitude_direction'],
-                                                                       $GPS_this_GPRMC['raw']['knots'],
-                                                                       $GPS_this_GPRMC['raw']['angle'],
-                                                                       $GPS_this_GPRMC['raw']['datestamp'],
-                                                                       $GPS_this_GPRMC['raw']['variation'],
-                                                                       $GPS_this_GPRMC['raw']['variation_direction'],
-                                                                       $dummy,
-                                                                       $GPS_this_GPRMC['raw']['checksum'],
-                                                               ) = $matches;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         //$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48));
+                                                               */
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $hour   = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
-                                                               $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
-                                                               $second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2);
-                                                               $ms     = substr($GPS_this_GPRMC['raw']['timestamp'], 6);    // may contain decimal seconds
-                                                               $day   = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
-                                                               $month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
-                                                               $year  = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
-                                                               $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
-                                                               $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
+                                                               // $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67
+                                                               // $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F
+                                                               // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
+                                                               if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
+                                                                       $GPS_this_GPRMC = array();
+                                                                       list(
+                                                                               $GPS_this_GPRMC['raw']['gprmc'],
+                                                                               $GPS_this_GPRMC['raw']['timestamp'],
+                                                                               $GPS_this_GPRMC['raw']['status'],
+                                                                               $GPS_this_GPRMC['raw']['latitude'],
+                                                                               $GPS_this_GPRMC['raw']['latitude_direction'],
+                                                                               $GPS_this_GPRMC['raw']['longitude'],
+                                                                               $GPS_this_GPRMC['raw']['longitude_direction'],
+                                                                               $GPS_this_GPRMC['raw']['knots'],
+                                                                               $GPS_this_GPRMC['raw']['angle'],
+                                                                               $GPS_this_GPRMC['raw']['datestamp'],
+                                                                               $GPS_this_GPRMC['raw']['variation'],
+                                                                               $GPS_this_GPRMC['raw']['variation_direction'],
+                                                                               $dummy,
+                                                                               $GPS_this_GPRMC['raw']['checksum'],
+                                                                       ) = $matches;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 $hour   = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
+                                                                       $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
+                                                                       $second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2);
+                                                                       $ms     = substr($GPS_this_GPRMC['raw']['timestamp'], 6);    // may contain decimal seconds
+                                                                       $day    = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
+                                                                       $month  = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
+                                                                       $year   = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
+                                                                       $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
+                                                                       $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                foreach (array('latitude','longitude') as $latlon) {
-                                                                       preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches);
-                                                                       list($dummy, $deg, $min) = $matches;
-                                                                       $GPS_this_GPRMC[$latlon] = $deg + ($min / 60);
-                                                               }
-                                                               $GPS_this_GPRMC['latitude']  *= (($GPS_this_GPRMC['raw']['latitude_direction']  == 'S') ? -1 : 1);
-                                                               $GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $GPS_this_GPRMC['heading']    = $GPS_this_GPRMC['raw']['angle'];
-                                                               $GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots'];
-                                                               $GPS_this_GPRMC['speed_kmh']  = $GPS_this_GPRMC['raw']['knots'] * 1.852;
-                                                               if ($GPS_this_GPRMC['raw']['variation']) {
-                                                                       $GPS_this_GPRMC['variation']  = $GPS_this_GPRMC['raw']['variation'];
-                                                                       $GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 foreach (array('latitude','longitude') as $latlon) {
+                                                                               preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches);
+                                                                               list($dummy, $deg, $min) = $matches;
+                                                                               $GPS_this_GPRMC[$latlon] = $deg + ($min / 60);
+                                                                       }
+                                                                       $GPS_this_GPRMC['latitude']  *= (($GPS_this_GPRMC['raw']['latitude_direction']  == 'S') ? -1 : 1);
+                                                                       $GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1);
+
+                                                                       $GPS_this_GPRMC['heading']    = $GPS_this_GPRMC['raw']['angle'];
+                                                                       $GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots'];
+                                                                       $GPS_this_GPRMC['speed_kmh']  = $GPS_this_GPRMC['raw']['knots'] * 1.852;
+                                                                       if ($GPS_this_GPRMC['raw']['variation']) {
+                                                                               $GPS_this_GPRMC['variation']  = $GPS_this_GPRMC['raw']['variation'];
+                                                                               $GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1);
+                                                                       }
+
+                                                                       $atom_structure['gps_entries'][$key] = $GPS_this_GPRMC;
+
+                                                                       @$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array(
+                                                                               'latitude'  => (float) $GPS_this_GPRMC['latitude'],
+                                                                               'longitude' => (float) $GPS_this_GPRMC['longitude'],
+                                                                               'speed_kmh' => (float) $GPS_this_GPRMC['speed_kmh'],
+                                                                               'heading'   => (float) $GPS_this_GPRMC['heading'],
+                                                                       );
+
+                                                               } else {
+                                                                       $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                        }
+                                                       $this->fseek($previous_offset);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                $atom_structure['gps_entries'][$key] = $GPS_this_GPRMC;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         } else {
+                                                       $this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset);
+                                               }
+                                       } else {
+                                               $this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset);
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                @$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array(
-                                                                       'latitude'  => $GPS_this_GPRMC['latitude'],
-                                                                       'longitude' => $GPS_this_GPRMC['longitude'],
-                                                                       'speed_kmh' => $GPS_this_GPRMC['speed_kmh'],
-                                                                       'heading'   => $GPS_this_GPRMC['heading'],
-                                                               );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'loci':// 3GP location (El Loco)
+                                       $loffset = 0;
+                                       $info['quicktime']['comments']['gps_flags']     = array(  getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)));
+                                       $info['quicktime']['comments']['gps_lang']      = array(  getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)));
+                                       $info['quicktime']['comments']['gps_location']  = array(          $this->LociString(substr($atom_data, 6), $loffset));
+                                       $loci_data = substr($atom_data, 6 + $loffset);
+                                       $info['quicktime']['comments']['gps_role']      = array(  getid3_lib::BigEndian2Int(substr($loci_data, 0, 1)));
+                                       $info['quicktime']['comments']['gps_longitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4)));
+                                       $info['quicktime']['comments']['gps_latitude']  = array(getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4)));
+                                       $info['quicktime']['comments']['gps_altitude']  = array(getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4)));
+                                       $info['quicktime']['comments']['gps_body']      = array(          $this->LociString(substr($loci_data, 13           ), $loffset));
+                                       $info['quicktime']['comments']['gps_notes']     = array(          $this->LociString(substr($loci_data, 13 + $loffset), $loffset));
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        } else {
-                                                               $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'chpl': // CHaPter List
+                                       // https://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf
+                                       $chpl_version = getid3_lib::BigEndian2Int(substr($atom_data, 4, 1)); // Expected to be 0
+                                       $chpl_flags   = getid3_lib::BigEndian2Int(substr($atom_data, 5, 3)); // Reserved, set to 0
+                                       $chpl_count   = getid3_lib::BigEndian2Int(substr($atom_data, 8, 1));
+                                       $chpl_offset = 9;
+                                       for ($i = 0; $i < $chpl_count; $i++) {
+                                               if (($chpl_offset + 9) >= strlen($atom_data)) {
+                                                       $this->warning('QuickTime chapter '.$i.' extends beyond end of "chpl" atom');
+                                                       break;
+                                               }
+                                               $info['quicktime']['chapters'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 8)) / 10000000; // timestamps are stored as 100-nanosecond units
+                                               $chpl_offset += 8;
+                                               $chpl_title_size = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 1));
+                                               $chpl_offset += 1;
+                                               $info['quicktime']['chapters'][$i]['title']     =                           substr($atom_data, $chpl_offset, $chpl_title_size);
+                                               $chpl_offset += $chpl_title_size;
+                                       }
+                                       break;
+
+                               case 'FIRM': // FIRMware version(?), seen on GoPro Hero4
+                                       $info['quicktime']['camera']['firmware'] = $atom_data;
+                                       break;
+
+                               case 'CAME': // FIRMware version(?), seen on GoPro Hero4
+                                       $info['quicktime']['camera']['serial_hash'] = unpack('H*', $atom_data);
+                                       break;
+
+                               case 'dscp':
+                               case 'rcif':
+                                       // https://www.getid3.org/phpBB3/viewtopic.php?t=1908
+                                       if (substr($atom_data, 0, 7) == "\x00\x00\x00\x00\x55\xC4".'{') {
+                                               if ($json_decoded = @json_decode(rtrim(substr($atom_data, 6), "\x00"), true)) {
+                                                       $info['quicktime']['camera'][$atomname] = $json_decoded;
+                                                       if (($atomname == 'rcif') && isset($info['quicktime']['camera']['rcif']['wxcamera']['rotate'])) {
+                                                               $info['video']['rotate'] = $info['quicktime']['video']['rotate'] = $info['quicktime']['camera']['rcif']['wxcamera']['rotate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                } else {
+                                                       $this->warning('Failed to JSON decode atom "'.$atomname.'"');
+                                                       $atom_structure['data'] = $atom_data;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $this->fseek($previous_offset);
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         unset($json_decoded);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $this->warning('Expecting 55 C4 7B at start of atom "'.$atomname.'", found '.getid3_lib::PrintHexBytes(substr($atom_data, 4, 3)).' instead');
+                                               $atom_structure['data'] = $atom_data;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } else {
-                                       $this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset);
-                               }
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        case 'loci':// 3GP location (El Loco)
-                                $info['quicktime']['comments']['gps_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
-                                $info['quicktime']['comments']['gps_lang'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
-                                $loffset = 0;
-                                $info['quicktime']['comments']['gps_location'] = $this->LociString(substr($atom_data, 6), $loffset);
-                                $loci_data=substr($atom_data, 6 + $loffset);
-                                $info['quicktime']['comments']['gps_role'] = getid3_lib::BigEndian2Int(substr($loci_data, 0, 1));
-                                $info['quicktime']['comments']['gps_longitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4));
-                                $info['quicktime']['comments']['gps_latitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4));
-                                $info['quicktime']['comments']['gps_altitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4));
-                                $info['quicktime']['comments']['gps_body'] = $this->LociString(substr($loci_data, 13), $loffset);
-                                $info['quicktime']['comments']['gps_notes'] = $this->LociString(substr($loci_data, 13 + $loffset), $loffset);
-                                break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         case 'frea':
+                                       // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
+                                       // may contain "scra" (PreviewImage) and/or "thma" (ThumbnailImage)
+                                       $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
+                                       break;
+                               case 'tima': // subatom to "frea"
+                                       // no idea what this does, the one sample file I've seen has a value of 0x00000027
+                                       $atom_structure['data'] = $atom_data;
+                                       break;
+                               case 'ver ': // subatom to "frea"
+                                       // some kind of version number, the one sample file I've seen has a value of "3.00.073"
+                                       $atom_structure['data'] = $atom_data;
+                                       break;
+                               case 'thma': // subatom to "frea" -- "ThumbnailImage"
+                                       // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
+                                       if (strlen($atom_data) > 0) {
+                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
+                                       }
+                                       break;
+                               case 'scra': // subatom to "frea" -- "PreviewImage"
+                                       // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
+                                       // but the only sample file I've seen has no useful data here
+                                       if (strlen($atom_data) > 0) {
+                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
+                                       }
+                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        default:
-                               $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset);
-                               $atom_structure['data'] = $atom_data;
-                               break;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                               default:
+                                       $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).'), '.$atomsize.' bytes at offset '.$baseoffset);
+                                       $atom_structure['data'] = $atom_data;
+                                       break;
+                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                array_pop($atomHierarchy);
</span><span class="cx" style="display: block; padding: 0 10px">                return $atom_structure;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $atom_data
+        * @param int    $baseoffset
+        * @param array  $atomHierarchy
+        * @param bool   $ParseAllPossibleAtoms
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'<br><br>';
</del><span class="cx" style="display: block; padding: 0 10px">                 $atom_structure  = false;
</span><span class="cx" style="display: block; padding: 0 10px">                $subatomoffset  = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $subatomcounter = 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1741,16 +1880,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                return $atom_structure;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-                       $atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $subatomoffset += $subatomsize;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $subatomcounter++;
</del><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                return $atom_structure;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $data
+        * @param int    $offset
+        *
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function quicktime_read_mp4_descr_length($data, &$offset) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html
</span><span class="cx" style="display: block; padding: 0 10px">                $num_bytes = 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1762,7 +1903,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $length;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $languageid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeLanguageLookup($languageid) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeLanguageLookup = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1900,6 +2045,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $codecid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeVideoCodecLookup($codecid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeVideoCodecLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeVideoCodecLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1959,6 +2109,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $codecid
+        *
+        * @return mixed|string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeAudioCodecLookup($codecid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeAudioCodecLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeAudioCodecLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2004,6 +2159,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $compressionid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeDCOMLookup($compressionid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeDCOMLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeDCOMLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2013,6 +2173,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $colordepthid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeColorNameLookup($colordepthid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeColorNameLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeColorNameLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2031,6 +2196,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $stik
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeSTIKLookup($stik) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeSTIKLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeSTIKLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2048,6 +2218,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $audio_profile_id
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeIODSaudioProfileName($audio_profile_id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeIODSaudioProfileNameLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeIODSaudioProfileNameLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2107,7 +2282,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $video_profile_id
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeIODSvideoProfileName($video_profile_id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeIODSvideoProfileNameLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeIODSvideoProfileNameLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2179,7 +2358,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $rtng
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeContentRatingLookup($rtng) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeContentRatingLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeContentRatingLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2190,6 +2373,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $akid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeStoreAccountTypeLookup($akid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeStoreAccountTypeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeStoreAccountTypeLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2199,6 +2387,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $sfid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeStoreFrontCodeLookup($sfid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $QuicktimeStoreFrontCodeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($QuicktimeStoreFrontCodeLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2228,6 +2421,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $atom_data
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function QuicktimeParseNikonNCTG($atom_data) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
</span><span class="cx" style="display: block; padding: 0 10px">                // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2270,10 +2468,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $data = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $datalength = strlen($atom_data);
</span><span class="cx" style="display: block; padding: 0 10px">                $parsed = array();
</span><span class="cx" style="display: block; padding: 0 10px">                while ($offset < $datalength) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'<br>';
</del><span class="cx" style="display: block; padding: 0 10px">                         $record_type       = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));  $offset += 4;
</span><span class="cx" style="display: block; padding: 0 10px">                        $data_size_type    = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));  $offset += 2;
</span><span class="cx" style="display: block; padding: 0 10px">                        $data_size         = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));  $offset += 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2328,7 +2526,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $offset += ($data_size * 2);
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                                default:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
</ins><span class="cx" style="display: block; padding: 0 10px">                                         break 2;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2406,7 +2604,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $parsed;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $keyname
+        * @param string|array $data
+        * @param string $boxname
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
</span><span class="cx" style="display: block; padding: 0 10px">                static $handyatomtranslatorarray = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($handyatomtranslatorarray)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2450,7 +2654,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'swr'] = 'software';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray["\xA9".'trk'] = 'track';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray["\xA9".'trk'] = 'track_number';
</ins><span class="cx" style="display: block; padding: 0 10px">                         $handyatomtranslatorarray["\xA9".'url'] = 'url';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2503,8 +2707,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $handyatomtranslatorarray['MusicBrainz Disc Id']         = 'MusicBrainz Disc Id';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // http://age.hobba.nl/audio/tag_frame_reference.html
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $handyatomtranslatorarray['PLAY_COUNTER']                = 'play_counter'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
-                       $handyatomtranslatorarray['MEDIATYPE']                   = 'mediatype';    // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $handyatomtranslatorarray['PLAY_COUNTER']                = 'play_counter'; // Foobar2000 - https://www.getid3.org/phpBB3/viewtopic.php?t=1355
+                       $handyatomtranslatorarray['MEDIATYPE']                   = 'mediatype';    // Foobar2000 - https://www.getid3.org/phpBB3/viewtopic.php?t=1355
</ins><span class="cx" style="display: block; padding: 0 10px">                         */
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2542,39 +2746,47 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    public function LociString($lstring, &$count) {
-            // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
-            // Also need to return the number of bytes the string occupied so additional fields can be extracted
-            $len = strlen($lstring);
-            if ($len == 0) {
-                $count = 0;
-                return '';
-            }
-            if ($lstring[0] == "\x00") {
-                $count = 1;
-                return '';
-            }
-            //check for BOM
-            if ($len > 2 && (($lstring[0] == "\xFE" && $lstring[1] == "\xFF") || ($lstring[0] == "\xFF" && $lstring[1] == "\xFE"))) {
-                //UTF-16
-                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
-                     $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
-                    return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
-                } else {
-                    return '';
-                }
-            } else {
-                //UTF-8
-                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
-                    $count = strlen($lmatches[1]) + 1; //account for trailing \x00
-                    return $lmatches[1];
-                }else {
-                    return '';
-                }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $lstring
+        * @param int    $count
+        *
+        * @return string
+        */
+       public function LociString($lstring, &$count) {
+               // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
+               // Also need to return the number of bytes the string occupied so additional fields can be extracted
+               $len = strlen($lstring);
+               if ($len == 0) {
+                       $count = 0;
+                       return '';
+               }
+               if ($lstring[0] == "\x00") {
+                       $count = 1;
+                       return '';
+               }
+               // check for BOM
+               if (($len > 2) && ((($lstring[0] == "\xFE") && ($lstring[1] == "\xFF")) || (($lstring[0] == "\xFF") && ($lstring[1] == "\xFE")))) {
+                       // UTF-16
+                       if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
+                               $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
+                               return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
+                       } else {
+                               return '';
+                       }
+               }
+               // UTF-8
+               if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
+                       $count = strlen($lmatches[1]) + 1; //account for trailing \x00
+                       return $lmatches[1];
+               }
+               return '';
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-            }
-        }
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $nullterminatedstring
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function NoNullString($nullterminatedstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // remove the single null terminator on null terminated strings
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2583,6 +2795,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $nullterminatedstring;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $pascalstring
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Pascal2String($pascalstring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
</span><span class="cx" style="display: block; padding: 0 10px">                return substr($pascalstring, 1);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2589,10 +2806,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        /*
-       // helper functions for m4b audiobook chapters
-       // code by Steffen Hartmann 2015-Nov-08
-       */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Helper functions for m4b audiobook chapters
+        * code by Steffen Hartmann 2015-Nov-08.
+        *
+        * @param array  $info
+        * @param string $tag
+        * @param string $history
+        * @param array  $result
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function search_tag_by_key($info, $tag, $history, &$result) {
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ($info as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $key_history = $history.'/'.$key;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2606,6 +2828,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array  $info
+        * @param string $k
+        * @param string $v
+        * @param string $history
+        * @param array  $result
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function search_tag_by_pair($info, $k, $v, $history, &$result) {
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ($info as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $key_history = $history.'/'.$key;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2619,6 +2848,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $info
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function quicktime_time_to_sample_table($info) {
</span><span class="cx" style="display: block; padding: 0 10px">                $res = array();
</span><span class="cx" style="display: block; padding: 0 10px">                $this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2636,7 +2870,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return array();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        function quicktime_bookmark_time_scale($info) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $info
+        *
+        * @return int
+        */
+       public function quicktime_bookmark_time_scale($info) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $time_scale = '';
</span><span class="cx" style="display: block; padding: 0 10px">                $ts_prefix_len = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $res = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2647,10 +2886,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (count($stbl_res) > 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $ts_res = array();
</span><span class="cx" style="display: block; padding: 0 10px">                                $this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                foreach ($ts_res as $value) {
-                                       $prefix = substr($value[0], 0, -12);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         foreach ($ts_res as $sub_value) {
+                                       $prefix = substr($sub_value[0], 0, -12);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $time_scale = $value[1]['time_scale'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $time_scale = $sub_value[1]['time_scale'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $ts_prefix_len = strlen($prefix);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiovideoriffphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio-video.riff.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio-video.riff.php     2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio-video.riff.php       2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio-video.riff.php                                 //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing RIFF files                             //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -27,10 +27,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-class getid3_riff extends getid3_handler {
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+class getid3_riff extends getid3_handler
+{
</ins><span class="cx" style="display: block; padding: 0 10px">         protected $container = 'riff'; // default
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        *
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46,6 +51,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
</span><span class="cx" style="display: block; padding: 0 10px">                $thisfile_riff_audio       = &$thisfile_riff['audio'];
</span><span class="cx" style="display: block; padding: 0 10px">                $thisfile_riff_video       = &$thisfile_riff['video'];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $thisfile_riff_WAVE        = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $Original['avdataoffset'] = $info['avdataoffset'];
</span><span class="cx" style="display: block; padding: 0 10px">                $Original['avdataend']    = $info['avdataend'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -357,6 +363,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_WAVE_cart_0['url']              =                 trim(substr($thisfile_riff_WAVE_cart_0['data'],  748, 1024));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_WAVE_cart_0['tag_text']         = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772)));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        $thisfile_riff['comments']['tag_text'][]       =                      substr($thisfile_riff_WAVE_cart_0['data'], 1772);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff['comments']['title'][]  = $thisfile_riff_WAVE_cart_0['title'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -405,7 +412,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                'tracktitle'=>'title',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'category'  =>'genre',
</span><span class="cx" style="display: block; padding: 0 10px">                                                'cdtitle'   =>'album',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                'tracktitle'=>'title',
</del><span class="cx" style="display: block; padding: 0 10px">                                         );
</span><span class="cx" style="display: block; padding: 0 10px">                                        foreach ($tagmapping as $fromkey => $tokey) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -613,6 +619,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_video['dataformat']   = 'avi';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $thisfile_riff_video_current = array();
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (isset($thisfile_riff['AVIX'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -695,12 +703,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                'capturedfile' => 0x00010000,
</span><span class="cx" style="display: block; padding: 0 10px">                                                'copyrighted'  => 0x00020010,
</span><span class="cx" style="display: block; padding: 0 10px">                                        );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                    foreach ($flags as $flag => $value) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 foreach ($flags as $flag => $value) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // shortcut
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_video[$streamindex] = array();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        /** @var array $thisfile_riff_video_current */
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -867,7 +876,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                if (self::fourccLookup($thisfile_video['fourcc'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -914,7 +923,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // http://en.wikipedia.org/wiki/CD-DA
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'CDDA':
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['fileformat'] = 'cda';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                            unset($info['mime_type']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         unset($info['mime_type']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_audio_dataformat      = 'cda';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -934,7 +943,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_riff_CDDA_fmt_0['playtime_seconds']     = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $info['comments']['track']                = $thisfile_riff_CDDA_fmt_0['track_num'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $info['comments']['track_number']         = $thisfile_riff_CDDA_fmt_0['track_num'];
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $info['playtime_seconds']                 = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        // hardcoded data for CD-audio
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -947,7 +956,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-            // http://en.wikipedia.org/wiki/AIFF
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // http://en.wikipedia.org/wiki/AIFF
</ins><span class="cx" style="display: block; padding: 0 10px">                         case 'AIFF':
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'AIFC':
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['fileformat'] = 'aiff';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1057,7 +1066,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $getid3_id3v2 = new getid3_id3v2($getid3_temp);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1077,6 +1086,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_audio_dataformat         = '8svx';
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_audio['bits_per_sample'] = 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_audio['channels']        = 1; // overridden below, if need be
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $ActualBitsPerSample               = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1114,7 +1124,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                default:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"');
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1159,7 +1169,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $getid3_mpeg = new getid3_mpeg($getid3_temp);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_mpeg->Analyze();
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (empty($getid3_temp->info['error'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1245,7 +1255,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $getid3_id3v2 = new getid3_id3v2($getid3_temp);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
</span><span class="cx" style="display: block; padding: 0 10px">                                        if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1372,6 +1382,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $startoffset
+        * @param int $maxoffset
+        *
+        * @return array|false
+        *
+        * @throws Exception
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseRIFFAMV($startoffset, $maxoffset) {
</span><span class="cx" style="display: block; padding: 0 10px">                // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1480,7 +1499,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $RIFFchunk;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $startoffset
+        * @param int $maxoffset
+        *
+        * @return array|false
+        * @throws getid3_exception
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseRIFF($startoffset, $maxoffset) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1529,7 +1554,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                // MP3
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                        $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                         $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1551,7 +1576,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                // AC3
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_ac3 = new getid3_ac3($getid3_temp);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1612,7 +1637,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        // Probably is MP3 data
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_temp->info['avdataend']    = $info['avdataend'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1629,7 +1654,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        // This is probably AC-3 data
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $getid3_temp = new getID3();
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        if ($isRegularAC3) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                         $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                $getid3_temp->info['avdataend']    = $info['avdataend'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1663,7 +1688,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        // This is probably DTS data
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $getid3_temp = new getID3();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                        $getid3_temp->openfile($this->getid3->filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $getid3_dts = new getid3_dts($getid3_temp);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $getid3_dts->Analyze();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1731,8 +1756,77 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        //      $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
</span><span class="cx" style="display: block; padding: 0 10px">                                                        //      break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                        case 'scot':
+                                                               // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html
+                                                               $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['alter']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   0,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   1,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum']          = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],   2,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['title']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   4,  43);  // "name" in other documentation
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['copy']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  47,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['padd']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  51,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  52,   5);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  57,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  59,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  61,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  63,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  65,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  71,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  77,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  78,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['digital']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  79,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate']     = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  80,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  82,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['compress']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  83,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt']         = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  84,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen']          = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  88,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2']         = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  90,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['future1']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  94,  12);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos']       = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds']   = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 122,   3);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 125,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 129,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 130,   3);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 133,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 137,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 138,  21);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['future2']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['artist']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 267,  34);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['comment']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 301,  34); // "trivia" in other documentation
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['intro']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 335,   2);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['end']             =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 337,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['year']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 338,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 342,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 343,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 344,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch']           = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel']       = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 356,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 379,   33);
+
+                                                               foreach (array('title', 'artist', 'comment') as $key) {
+                                                                       if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) {
+                                                                               $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]);
+                                                                       }
+                                                               }
+                                                               if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) {
+                                                                       $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')');
+                                                               }
+                                                               break;
+
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         default:
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                         if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                         $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size']   = $RIFFchunk[$chunkname][$thisindex]['size'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                        unset($RIFFchunk[$chunkname][$thisindex]['offset']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1767,6 +1861,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $RIFFchunk;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $RIFFdata
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseRIFFdata(&$RIFFdata) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                if ($RIFFdata) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1804,6 +1903,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $RIFFinfoArray
+        * @param array $CommentsTargetArray
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) {
</span><span class="cx" style="display: block; padding: 0 10px">                $RIFFinfoKeyLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'IARL'=>'archivallocation',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1863,8 +1968,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $WaveFormatExData
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function parseWAVEFORMATex($WaveFormatExData) {
</span><span class="cx" style="display: block; padding: 0 10px">                // shortcut
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $WaveFormatEx        = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 $WaveFormatEx['raw'] = array();
</span><span class="cx" style="display: block; padding: 0 10px">                $WaveFormatEx_raw    = &$WaveFormatEx['raw'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1888,6 +1999,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $WaveFormatEx;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $WavPackChunkData
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function parseWavPackHeader($WavPackChunkData) {
</span><span class="cx" style="display: block; padding: 0 10px">                // typedef struct {
</span><span class="cx" style="display: block; padding: 0 10px">                //     char ckID [4];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1949,6 +2065,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BITMAPINFOHEADER
+        * @param bool   $littleEndian
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $parsed['biSize']          = substr($BITMAPINFOHEADER,  0, 4); // number of bytes required by the BITMAPINFOHEADER structure
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1968,6 +2090,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $parsed;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $DIVXTAG
+        * @param bool   $raw
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ParseDIVXTAG($DIVXTAG, $raw=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/
</span><span class="cx" style="display: block; padding: 0 10px">                // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2014,6 +2142,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                         5 => 'NC-17',
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $parsed              = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 $parsed['title']     =        trim(substr($DIVXTAG,   0, 32));
</span><span class="cx" style="display: block; padding: 0 10px">                $parsed['artist']    =        trim(substr($DIVXTAG,  32, 28));
</span><span class="cx" style="display: block; padding: 0 10px">                $parsed['year']      = intval(trim(substr($DIVXTAG,  60,  4)));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2029,8 +2158,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (!$raw) {
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($parsed['genre_id'], $parsed['rating_id']);
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($parsed as $key => $value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (!$value === '') {
-                                       unset($parsed['key']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if (empty($value)) {
+                                       unset($parsed[$key]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2042,6 +2171,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $parsed;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $tagshortname
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function waveSNDMtagLookup($tagshortname) {
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2065,6 +2199,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $wFormatTag
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function wFormatTagLookup($wFormatTag) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2234,6 +2373,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $fourcc
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function fourccLookup($fourcc) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2628,6 +2772,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $byteword
+        * @param bool   $signed
+        *
+        * @return int|float|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function EitherEndian2Int($byteword, $signed=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($this->container == 'riff') {
</span><span class="cx" style="display: block; padding: 0 10px">                        return getid3_lib::LittleEndian2Int($byteword, $signed);
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudioac3php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio.ac3.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio.ac3.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio.ac3.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio.ac3.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing AC-3 (aka Dolby Digital) audio files   //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -17,11 +17,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_ac3 extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    private $AC3header = array();
-    private $BSIoffset = 0;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @var array
+        */
+       private $AC3header = array();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    const syncword = 0x0B77;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @var int
+        */
+       private $BSIoffset = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        const syncword = 0x0B77;
+
+       /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -187,7 +197,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.');
</ins><span class="cx" style="display: block; padding: 0 10px">                         $info['audio']['dataformat'] = 'eac3';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_ac3_raw_bsi['strmtyp']          =        $this->readHeaderBSI(2);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -412,7 +422,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                    unset($info['ac3']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 unset($info['ac3']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         return false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -431,15 +441,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']);
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_ac3['bitrate']      = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']);
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// this isn't right, but it's (usually) close, roughly 5% less than it should be.
-// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // this isn't right, but it's (usually) close, roughly 5% less than it should be.
+                       // but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know!
</ins><span class="cx" style="display: block; padding: 0 10px">                         $thisfile_ac3['bitrate']      = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// kludge-fix to make it approximately the expected value, still not "right":
-$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // kludge-fix to make it approximately the expected value, still not "right":
+                       $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['bitrate'] = $thisfile_ac3['bitrate'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) {
+                       $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']);
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">                 $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']);
</span><span class="cx" style="display: block; padding: 0 10px">                foreach($ac3_coding_mode as $key => $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_ac3[$key] = $value;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -470,6 +482,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $length
+        *
+        * @return float|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function readHeaderBSI($length) {
</span><span class="cx" style="display: block; padding: 0 10px">                $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
</span><span class="cx" style="display: block; padding: 0 10px">                $this->BSIoffset += $length;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -477,6 +494,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return bindec($data);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $fscod
+        *
+        * @return int|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function sampleRateCodeLookup($fscod) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $sampleRateCodeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 48000,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -487,6 +509,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $fscod2
+        *
+        * @return int|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function sampleRateCodeLookup2($fscod2) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $sampleRateCodeLookup2 = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 24000,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -497,6 +524,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $bsmod
+        * @param int $acmod
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function serviceTypeLookup($bsmod, $acmod) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $serviceTypeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($serviceTypeLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -518,6 +551,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $acmod
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function audioCodingModeLookup($acmod) {
</span><span class="cx" style="display: block; padding: 0 10px">                // array(channel configuration, # channels (not incl LFE), channel order)
</span><span class="cx" style="display: block; padding: 0 10px">                static $audioCodingModeLookup = array (
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -533,6 +571,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $cmixlev
+        *
+        * @return int|float|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function centerMixLevelLookup($cmixlev) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $centerMixLevelLookup;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($centerMixLevelLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -546,6 +589,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $surmixlev
+        *
+        * @return int|float|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function surroundMixLevelLookup($surmixlev) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $surroundMixLevelLookup;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($surroundMixLevelLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -559,6 +607,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $dsurmod
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function dolbySurroundModeLookup($dsurmod) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $dolbySurroundModeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'not indicated',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -569,12 +622,18 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int  $acmod
+        * @param bool $lfeon
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function channelsEnabledLookup($acmod, $lfeon) {
</span><span class="cx" style="display: block; padding: 0 10px">                $lookup = array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'ch1'=>(bool) ($acmod == 0),
-                       'ch2'=>(bool) ($acmod == 0),
-                       'left'=>(bool) ($acmod > 1),
-                       'right'=>(bool) ($acmod > 1),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'ch1'=>($acmod == 0),
+                       'ch2'=>($acmod == 0),
+                       'left'=>($acmod > 1),
+                       'right'=>($acmod > 1),
</ins><span class="cx" style="display: block; padding: 0 10px">                         'center'=>(bool) ($acmod & 0x01),
</span><span class="cx" style="display: block; padding: 0 10px">                        'surround_mono'=>false,
</span><span class="cx" style="display: block; padding: 0 10px">                        'surround_left'=>false,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -594,6 +653,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $lookup;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $compre
+        *
+        * @return float|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function heavyCompression($compre) {
</span><span class="cx" style="display: block; padding: 0 10px">                // The first four bits indicate gain changes in 6.02dB increments which can be
</span><span class="cx" style="display: block; padding: 0 10px">                // implemented with an arithmetic shift operation. The following four bits
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -623,7 +687,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // -8    -42.14 dB
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ($fourbit{0} == '1') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ($fourbit[0] == '1') {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $log_gain = -8 + bindec(substr($fourbit, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        $log_gain = bindec(substr($fourbit, 1));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -644,6 +708,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $log_gain - $lin_gain;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $roomtyp
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function roomTypeLookup($roomtyp) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $roomTypeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'not indicated',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -654,6 +723,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $frmsizecod
+        * @param int $fscod
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function frameSizeLookup($frmsizecod, $fscod) {
</span><span class="cx" style="display: block; padding: 0 10px">                // LSB is whether padding is used or not
</span><span class="cx" style="display: block; padding: 0 10px">                $padding     = (bool) ($frmsizecod & 0x01);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -683,13 +758,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                18 => array(2560, 2786, 3840)   // 640 kbps
</span><span class="cx" style="display: block; padding: 0 10px">                        );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $paddingBytes = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (($fscod == 1) && $padding) {
</span><span class="cx" style="display: block; padding: 0 10px">                        // frame lengths are padded by 1 word (16 bits) at 44100
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frameSizeLookup[$frmsizecod] += 2;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // (fscode==1) means 44100Hz (see sampleRateCodeLookup)
+                       $paddingBytes = 2;
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] + $paddingBytes : false);
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $frmsizecod
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function bitrateLookup($frmsizecod) {
</span><span class="cx" style="display: block; padding: 0 10px">                // LSB is whether padding is used or not
</span><span class="cx" style="display: block; padding: 0 10px">                $padding     = (bool) ($frmsizecod & 0x01);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -719,6 +801,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $numblkscod
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function blocksPerSyncFrame($numblkscod) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $blocksPerSyncFrameLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 1,
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiodtsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio.dts.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio.dts.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio.dts.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio.dts.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing DTS Audio files                        //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -21,21 +21,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_dts extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        * Default DTS syncword used in native .cpt or .dts formats
-       */
-    const syncword = "\x7F\xFE\x80\x01";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Default DTS syncword used in native .cpt or .dts formats.
+        */
+       const syncword = "\x7F\xFE\x80\x01";
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @var int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private $readBinDataOffset = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    /**
-    * Possible syncwords indicating bitstream encoding
-    */
-    public static $syncwords = array(
-       0 => "\x7F\xFE\x80\x01",  // raw big-endian
-       1 => "\xFE\x7F\x01\x80",  // raw little-endian
-       2 => "\x1F\xFF\xE8\x00",  // 14-bit big-endian
-       3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Possible syncwords indicating bitstream encoding.
+        */
+       public static $syncwords = array(
+               0 => "\x7F\xFE\x80\x01",  // raw big-endian
+               1 => "\xFE\x7F\x01\x80",  // raw little-endian
+               2 => "\x1F\xFF\xE8\x00",  // 14-bit big-endian
+               3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                $info['fileformat'] = 'dts';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -45,18 +51,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // check syncword
</span><span class="cx" style="display: block; padding: 0 10px">                $sync = substr($DTSheader, 0, 4);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if (($encoding = array_search($sync, self::$syncwords)) !== false) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (($encoding = array_search($sync, self::$syncwords)) !== false) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $info['dts']['raw']['magic'] = $sync;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $info['dts']['raw']['magic'] = $sync;
</ins><span class="cx" style="display: block; padding: 0 10px">                         $this->readBinDataOffset = 32;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        } elseif ($this->isDependencyFor('matroska')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif ($this->isDependencyFor('matroska')) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Matroska contains DTS without syncword encoded as raw big-endian format
</span><span class="cx" style="display: block; padding: 0 10px">                        $encoding = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->readBinDataOffset = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        } else {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } else {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($info['fileformat']);
</span><span class="cx" style="display: block; padding: 0 10px">                        return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -139,6 +145,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $bin
+        * @param int $length
+        *
+        * @return float|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function readBinData($bin, $length) {
</span><span class="cx" style="display: block; padding: 0 10px">                $data = substr($bin, $this->readBinDataOffset, $length);
</span><span class="cx" style="display: block; padding: 0 10px">                $this->readBinDataOffset += $length;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -146,6 +158,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return bindec($data);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return int|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function bitrateLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0  => 32000,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -184,6 +201,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$index]) ? $lookup[$index] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return int|string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function sampleRateLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0  => 'invalid',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -206,6 +228,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$index]) ? $lookup[$index] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function bitPerSampleLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0  => 16,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -216,6 +243,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$index]) ? $lookup[$index] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function numChannelsLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 0:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -254,6 +286,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function channelArrangementLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0  => 'A',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,6 +313,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        * @param int $version
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function dialogNormalization($index, $version) {
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($version) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 7:
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudioflacphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio.flac.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio.flac.php   2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio.flac.php     2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio.flac.php                                       //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing FLAC and OggFLAC audio files           //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,6 +24,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px">        const syncword = 'fLaC';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,12 +44,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $this->parseMETAdata();
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function parseMETAdata() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                do {
</span><span class="cx" style="display: block; padding: 0 10px">                        $BlockOffset   = $this->ftell();
</span><span class="cx" style="display: block; padding: 0 10px">                        $BlockHeader   = $this->fread(4);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $LBFBT         = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $LBFBT         = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));  // LBFBT = LastBlockFlag + BlockType
</ins><span class="cx" style="display: block; padding: 0 10px">                         $LastBlockFlag = (bool) ($LBFBT & 0x80);
</span><span class="cx" style="display: block; padding: 0 10px">                        $BlockType     =        ($LBFBT & 0x7F);
</span><span class="cx" style="display: block; padding: 0 10px">                        $BlockLength   = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -53,10 +59,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $BlockTypeText = self::metaBlockTypeLookup($BlockType);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->error('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
</ins><span class="cx" style="display: block; padding: 0 10px">                                 break;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($BlockLength < 1) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                if ($BlockTypeText != 'reserved') {
+                                       // probably supposed to be zero-length
+                                       $this->warning('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockTypeText.') at offset '.$BlockOffset.' is zero bytes');
+                                       continue;
+                               }
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -167,7 +178,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        else {
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['md5_data_source'] = '';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -194,12 +205,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        private function parseSTREAMINFO($BlockData) {
-               $info = &$this->getid3->info;
</del><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $info['flac']['STREAMINFO'] = array();
-               $streaminfo = &$info['flac']['STREAMINFO'];
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $BlockData
+        *
+        * @return array
+        */
+       public static function parseSTREAMINFOdata($BlockData) {
+               $streaminfo = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 $streaminfo['min_block_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                $streaminfo['max_block_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
</span><span class="cx" style="display: block; padding: 0 10px">                $streaminfo['min_frame_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -211,15 +224,28 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23,  5)) + 1;
</span><span class="cx" style="display: block; padding: 0 10px">                $streaminfo['samples_stream']  = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $streaminfo['audio_signature'] = substr($BlockData, 18, 16);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $streaminfo['audio_signature'] =                           substr($BlockData, 18, 16);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (!empty($streaminfo['sample_rate'])) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $streaminfo;
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BlockData
+        *
+        * @return bool
+        */
+       private function parseSTREAMINFO($BlockData) {
+               $info = &$this->getid3->info;
+
+               $info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData);
+
+               if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
+
</ins><span class="cx" style="display: block; padding: 0 10px">                         $info['audio']['bitrate_mode']    = 'vbr';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['audio']['sample_rate']     = $streaminfo['sample_rate'];
-                       $info['audio']['channels']        = $streaminfo['channels'];
-                       $info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample'];
-                       $info['playtime_seconds']         = $streaminfo['samples_stream'] / $streaminfo['sample_rate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $info['audio']['sample_rate']     = $info['flac']['STREAMINFO']['sample_rate'];
+                       $info['audio']['channels']        = $info['flac']['STREAMINFO']['channels'];
+                       $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
+                       $info['playtime_seconds']         = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                         if ($info['playtime_seconds'] > 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!$this->isDependencyFor('matroska')) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -236,6 +262,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BlockData
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function parseAPPLICATION($BlockData) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -246,6 +277,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BlockData
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function parseSEEKTABLE($BlockData) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -275,6 +311,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BlockData
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function parseVORBIS_COMMENT($BlockData) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -294,6 +335,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $BlockData
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         private function parseCUESHEET($BlockData) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                $offset = 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -346,9 +392,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
-       * External usage: audio.ogg
-       */
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
+        * External usage: audio.ogg
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function parsePICTURE() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -380,6 +428,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $blocktype
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function metaBlockTypeLookup($blocktype) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'STREAMINFO',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -393,6 +446,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $applicationid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function applicationIDLookup($applicationid) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://flac.sourceforge.net/id.html
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -423,6 +481,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $type_id
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function pictureTypeLookup($type_id) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $lookup = array (
</span><span class="cx" style="display: block; padding: 0 10px">                         0 => 'Other',
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiomp3php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio.mp3.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio.mp3.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio.mp3.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio.mp3.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing MP3 files                              //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -24,9 +24,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_mp3 extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow,
+        * unrecommended, but may provide data from otherwise-unusable files.
+        *
+        * @var bool
+        */
+       public $allow_bruteforce = false;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -35,7 +43,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($this->allow_bruteforce) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $this->error('Rescanning file in BruteForce mode');
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $this->getOnlyMPEGaudioInfoBruteForce();
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -152,7 +160,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // Calculate playtime
</span><span class="cx" style="display: block; padding: 0 10px">                if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // https://github.com/JamesHeinrich/getID3/issues/161
+                       // VBR header frame contains ~0.026s of silent audio data, but is not actually part of the original encoding and should be ignored
+                       $xingVBRheaderFrameLength = ((isset($info['mpeg']['audio']['VBR_frames']) && isset($info['mpeg']['audio']['framelength'])) ? $info['mpeg']['audio']['framelength'] : 0);
+
+                       $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset'] - $xingVBRheaderFrameLength) * 8 / $info['audio']['bitrate'];
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['encoder_options'] = $this->GuessEncoderOptions();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -160,10 +172,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function GuessEncoderOptions() {
</span><span class="cx" style="display: block; padding: 0 10px">                // shortcuts
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $thisfile_mpeg_audio = array();
+               $thisfile_mpeg_audio_lame = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 if (!empty($info['mpeg']['audio'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_mpeg_audio = &$info['mpeg']['audio'];
</span><span class="cx" style="display: block; padding: 0 10px">                        if (!empty($thisfile_mpeg_audio['LAME'])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -178,7 +194,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && isset($thisfile_mpeg_audio_lame['preset_used_id']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $encoder_options = $thisfile_mpeg_audio_lame['preset_used'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -404,7 +420,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $encoder_options;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int   $offset
+        * @param array $info
+        * @param bool  $recursivesearch
+        * @param bool  $ScanAsCBR
+        * @param bool  $FastMPEGheaderScan
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioVersionLookup;
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioLayerLookup;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -458,7 +482,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $thisfile_mpeg_audio = &$info['mpeg']['audio'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px">                 if ($MPEGaudioHeaderValidCache[$head4_key]) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray;
</span><span class="cx" style="display: block; padding: 0 10px">                } else {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -562,7 +585,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_mpeg_audio['bitrate_mode'] = 'vbr';
</span><span class="cx" style="display: block; padding: 0 10px">                        $thisfile_mpeg_audio['VBR_method']   = 'Fraunhofer';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $info['audio']['codec']                = 'Fraunhofer';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $info['audio']['codec']              = 'Fraunhofer';
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $SideInfoData = substr($headerstring, 4 + 2, 32);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -655,7 +678,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                $used_filesize = $thisfile_mpeg_audio['VBR_bytes'];
</span><span class="cx" style="display: block; padding: 0 10px">                                        } elseif (!empty($info['filesize'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $used_filesize  = $info['filesize'];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $used_filesize -= intval(@$info['id3v2']['headerlength']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $used_filesize -= (isset($info['id3v2']['headerlength']) ? intval($info['id3v2']['headerlength']) : 0);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $used_filesize -= (isset($info['id3v1']) ? 128 : 0);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0);
</span><span class="cx" style="display: block; padding: 0 10px">                                                $this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -678,7 +701,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($thisfile_mpeg_audio['xing_flags']['toc']) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ($i = 0; $i < 100; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData[$i]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1083,6 +1106,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $offset
+        * @param int $nextframetestoffset
+        * @param bool $ScanAsCBR
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                $firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1129,6 +1159,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int  $offset
+        * @param bool $deepscan
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function FreeFormatFrameLength($offset, $deepscan=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1137,9 +1173,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $SyncPattern1 = substr($MPEGaudioData, 0, 4);
</span><span class="cx" style="display: block; padding: 0 10px">                // may be different pattern due to padding
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) | 0x02).$SyncPattern1[3];
</ins><span class="cx" style="display: block; padding: 0 10px">                 if ($SyncPattern2 === $SyncPattern1) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3};
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) & 0xFD).$SyncPattern1[3];
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $framelength = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1206,6 +1242,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $framelength;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getOnlyMPEGaudioInfoBruteForce() {
</span><span class="cx" style="display: block; padding: 0 10px">                $MPEGaudioHeaderDecodeCache   = array();
</span><span class="cx" style="display: block; padding: 0 10px">                $MPEGaudioHeaderValidCache    = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1241,9 +1280,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (strlen($head4) < 4) {
</span><span class="cx" style="display: block; padding: 0 10px">                                break;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ($head4{0} != "\xFF") {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($head4[0] != "\xFF") {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 for ($i = 1; $i < 4; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ($head4{$i} == "\xFF") {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($head4[$i] == "\xFF") {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $this->fseek($i - 4, SEEK_CUR);
</span><span class="cx" style="display: block; padding: 0 10px">                                                continue 2;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1275,7 +1314,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $WhereWeWere = $this->ftell();
</span><span class="cx" style="display: block; padding: 0 10px">                                        $this->fseek($MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $next4 = $this->fread(4);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ($next4{0} == "\xFF") {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if ($next4[0] == "\xFF") {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4);
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1353,7 +1392,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int  $avdataoffset
+        * @param bool $BitrateHistogram
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                // looks for synch, decodes MPEG audio header
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1363,10 +1407,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioLayerLookup;
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioBitrateLookup;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($MPEGaudioVersionLookup)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                   $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
-                  $MPEGaudioLayerLookup   = self::MPEGaudioLayerArray();
-                  $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+                       $MPEGaudioLayerLookup   = self::MPEGaudioLayerArray();
+                       $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
</ins><span class="cx" style="display: block; padding: 0 10px">                 }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $this->fseek($avdataoffset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1416,7 +1459,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return false;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected
+                               $FirstFrameAVDataOffset = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $FirstFrameThisfileInfo = $info;
</span><span class="cx" style="display: block; padding: 0 10px">                                        $FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1440,7 +1484,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $info['audio']['dataformat'] = 'mp3';
</span><span class="cx" style="display: block; padding: 0 10px">                                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (isset($FirstFrameThisfileInfo) && isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // If there is garbage data between a valid VBR header frame and a sequence
</span><span class="cx" style="display: block; padding: 0 10px">                                                        // of valid MPEG-audio frames the VBR data is no longer discarded.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1510,7 +1554,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $this->fseek($scan_start_offset[$current_segment]);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $buffer_4k = $this->fread(4096);
</span><span class="cx" style="display: block; padding: 0 10px">                                                                for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                        if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                 if (($buffer_4k[$j] == "\xFF") && ($buffer_4k[($j + 1)] > "\xE0")) { // synch detected
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                                 if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1522,7 +1566,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $synchstartoffset = $scan_start_offset[$current_segment];
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 while (($synchstartoffset < $info['avdataend']) && $this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                                 $FastMode = true;
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1633,17 +1677,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioVersionArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioVersion = array('2.5', false, '2', '1');
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioVersion;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioLayerArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioLayer = array(false, 3, 2, 1);
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioLayer;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioBitrateArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioBitrate;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($MPEGaudioBitrate)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1663,6 +1715,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioBitrate;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioFrequencyArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioFrequency;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($MPEGaudioFrequency)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1675,11 +1730,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioFrequency;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioChannelModeArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioChannelMode;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioModeExtensionArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioModeExtension;
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($MPEGaudioModeExtension)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1692,15 +1753,31 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioModeExtension;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioEmphasisArray() {
</span><span class="cx" style="display: block; padding: 0 10px">                static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGaudioEmphasis;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $head4
+        * @param bool   $allowBitrate15
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $rawarray
+        * @param bool  $echoerrors
+        * @param bool  $allowBitrate15
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1773,6 +1850,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $Header4Bytes
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioHeaderDecode($Header4Bytes) {
</span><span class="cx" style="display: block; padding: 0 10px">                // AAAA AAAA  AAAB BCCD  EEEE FFGH  IIJJ KLMM
</span><span class="cx" style="display: block; padding: 0 10px">                // A - Frame sync (all bits set)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1794,22 +1876,31 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $MPEGrawHeader['synch']         = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $MPEGrawHeader['version']       = (ord($Header4Bytes{1}) & 0x18) >> 3; //    BB
-               $MPEGrawHeader['layer']         = (ord($Header4Bytes{1}) & 0x06) >> 1; //      CC
-               $MPEGrawHeader['protection']    = (ord($Header4Bytes{1}) & 0x01);      //        D
-               $MPEGrawHeader['bitrate']       = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE
-               $MPEGrawHeader['sample_rate']   = (ord($Header4Bytes{2}) & 0x0C) >> 2; //     FF
-               $MPEGrawHeader['padding']       = (ord($Header4Bytes{2}) & 0x02) >> 1; //       G
-               $MPEGrawHeader['private']       = (ord($Header4Bytes{2}) & 0x01);      //        H
-               $MPEGrawHeader['channelmode']   = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II
-               $MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; //   JJ
-               $MPEGrawHeader['copyright']     = (ord($Header4Bytes{3}) & 0x08) >> 3; //     K
-               $MPEGrawHeader['original']      = (ord($Header4Bytes{3}) & 0x04) >> 2; //      L
-               $MPEGrawHeader['emphasis']      = (ord($Header4Bytes{3}) & 0x03);      //       MM
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $MPEGrawHeader['version']       = (ord($Header4Bytes[1]) & 0x18) >> 3; //    BB
+               $MPEGrawHeader['layer']         = (ord($Header4Bytes[1]) & 0x06) >> 1; //      CC
+               $MPEGrawHeader['protection']    = (ord($Header4Bytes[1]) & 0x01);      //        D
+               $MPEGrawHeader['bitrate']       = (ord($Header4Bytes[2]) & 0xF0) >> 4; // EEEE
+               $MPEGrawHeader['sample_rate']   = (ord($Header4Bytes[2]) & 0x0C) >> 2; //     FF
+               $MPEGrawHeader['padding']       = (ord($Header4Bytes[2]) & 0x02) >> 1; //       G
+               $MPEGrawHeader['private']       = (ord($Header4Bytes[2]) & 0x01);      //        H
+               $MPEGrawHeader['channelmode']   = (ord($Header4Bytes[3]) & 0xC0) >> 6; // II
+               $MPEGrawHeader['modeextension'] = (ord($Header4Bytes[3]) & 0x30) >> 4; //   JJ
+               $MPEGrawHeader['copyright']     = (ord($Header4Bytes[3]) & 0x08) >> 3; //     K
+               $MPEGrawHeader['original']      = (ord($Header4Bytes[3]) & 0x04) >> 2; //      L
+               $MPEGrawHeader['emphasis']      = (ord($Header4Bytes[3]) & 0x03);      //       MM
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return $MPEGrawHeader;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int|string $bitrate
+        * @param string     $version
+        * @param string     $layer
+        * @param bool       $padding
+        * @param int        $samplerate
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $AudioFrameLengthCache = array();
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1871,6 +1962,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param float|int $bit_rate
+        *
+        * @return int|float|string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ClosestStandardMP3Bitrate($bit_rate) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000);
</span><span class="cx" style="display: block; padding: 0 10px">                static $bit_rate_table = array (0=>'-');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1891,10 +1987,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $bit_rate_table[$round_bit_rate];
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $version
+        * @param string $channelmode
+        *
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function XingVBRidOffset($version, $channelmode) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $XingVBRidOffsetCache = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (empty($XingVBRidOffset)) {
-                       $XingVBRidOffset = array (
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (empty($XingVBRidOffsetCache)) {
+                       $XingVBRidOffsetCache = array (
</ins><span class="cx" style="display: block; padding: 0 10px">                                 '1'   => array ('mono'          => 0x15, // 4 + 17 = 21
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'stereo'        => 0x24, // 4 + 32 = 36
</span><span class="cx" style="display: block; padding: 0 10px">                                                                'joint stereo'  => 0x24,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1914,9 +2016,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                           )
</span><span class="cx" style="display: block; padding: 0 10px">                        );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return $XingVBRidOffset[$version][$channelmode];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         return $XingVBRidOffsetCache[$version][$channelmode];
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $VBRmethodID
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LAMEvbrMethodLookup($VBRmethodID) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LAMEvbrMethodLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'unknown',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1933,6 +2040,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $StereoModeID
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LAMEmiscStereoModeLookup($StereoModeID) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LAMEmiscStereoModeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'mono',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1947,6 +2059,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $SourceSampleFrequencyID
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LAMEmiscSourceSampleFrequencyLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => '<= 32 kHz',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1957,6 +2074,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $SurroundInfoID
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LAMEsurroundInfoLookup($SurroundInfoID) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LAMEsurroundInfoLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'no surround info',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1967,6 +2089,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $LAMEtag
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LAMEpresetUsedLookup($LAMEtag) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if ($LAMEtag['preset_used_id'] == 0) {
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduleaudiooggphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.audio.ogg.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.audio.ogg.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.audio.ogg.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.audio.ogg.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing Ogg Vorbis, OggFLAC and Speex files    //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18,7 +18,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_ogg extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -65,7 +69,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif (substr($filedata, 0, 8) == 'OpusHead') {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ($this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) === false) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 return false;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -179,7 +183,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator'];
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable');
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                } elseif (substr($filedata, 0, 8) == "fishead\x00") {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -259,9 +263,34 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']');
</span><span class="cx" style="display: block; padding: 0 10px">                        //return false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                } elseif (substr($filedata, 0, 5) == "\x7F".'FLAC') {
+                       // https://xiph.org/flac/ogg_mapping.html
+
+                       $info['audio']['dataformat']   = 'flac';
+                       $info['audio']['bitrate_mode'] = 'vbr';
+                       $info['audio']['lossless']     = true;
+
+                       $info['ogg']['flac']['header']['version_major']  =                         ord(substr($filedata,  5, 1));
+                       $info['ogg']['flac']['header']['version_minor']  =                         ord(substr($filedata,  6, 1));
+                       $info['ogg']['flac']['header']['header_packets'] =   getid3_lib::BigEndian2Int(substr($filedata,  7, 2)) + 1; // "A two-byte, big-endian binary number signifying the number of header (non-audio) packets, not including this one. This number may be zero (0x0000) to signify 'unknown' but be aware that some decoders may not be able to handle such streams."
+                       $info['ogg']['flac']['header']['magic']          =                             substr($filedata,  9, 4);
+                       if ($info['ogg']['flac']['header']['magic'] != 'fLaC') {
+                               $this->error('Ogg-FLAC expecting "fLaC", found "'.$info['ogg']['flac']['header']['magic'].'" ('.trim(getid3_lib::PrintHexBytes($info['ogg']['flac']['header']['magic'])).')');
+                               return false;
+                       }
+                       $info['ogg']['flac']['header']['STREAMINFO_bytes'] = getid3_lib::BigEndian2Int(substr($filedata, 13, 4));
+                       $info['flac']['STREAMINFO'] = getid3_flac::parseSTREAMINFOdata(substr($filedata, 17, 34));
+                       if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
+                               $info['audio']['bitrate_mode']    = 'vbr';
+                               $info['audio']['sample_rate']     = $info['flac']['STREAMINFO']['sample_rate'];
+                               $info['audio']['channels']        = $info['flac']['STREAMINFO']['channels'];
+                               $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
+                               $info['playtime_seconds']         = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
+                       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 } else {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $this->error('Expecting either "Speex   ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $this->error('Expecting one of "vorbis", "Speex", "OpusHead", "vorbis", "fishhead", "theora", "fLaC" identifier strings, found "'.substr($filedata, 0, 8).'"');
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($info['ogg']);
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($info['mime_type']);
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -378,6 +407,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $filedata
+        * @param int    $filedataoffset
+        * @param array  $oggpageinfo
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['dataformat'] = 'vorbis';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -426,7 +462,15 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03
+        *
+        * @param string $filedata
+        * @param int    $filedataoffset
+        * @param array  $oggpageinfo
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px">                $info['audio']['dataformat']   = 'opus';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -458,7 +502,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
</span><span class="cx" style="display: block; padding: 0 10px">                $filedataoffset += 2;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $info['ogg']['pageheader']['opus']['input_sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  4));
</ins><span class="cx" style="display: block; padding: 0 10px">                 $filedataoffset += 4;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                //$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  2));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -467,16 +511,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                //$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset,  1));
</span><span class="cx" style="display: block; padding: 0 10px">                //$filedataoffset += 1;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $info['opus']['opus_version']      = $info['ogg']['pageheader']['opus']['version'];
-               $info['opus']['sample_rate']       = $info['ogg']['pageheader']['opus']['sample_rate'];
-               $info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $info['opus']['opus_version']       = $info['ogg']['pageheader']['opus']['version'];
+               $info['opus']['sample_rate_input']  = $info['ogg']['pageheader']['opus']['input_sample_rate'];
+               $info['opus']['out_channel_count']  = $info['ogg']['pageheader']['opus']['out_channel_count'];
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $info['audio']['channels']      = $info['opus']['out_channel_count'];
-               $info['audio']['sample_rate']   = $info['opus']['sample_rate'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $info['audio']['channels']          = $info['opus']['out_channel_count'];
+               $info['audio']['sample_rate_input'] = $info['opus']['sample_rate_input'];
+               $info['audio']['sample_rate']       = 48000; // "All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz for playback (unless the target hardware does not support this sampling rate). However, this field may be used to resample the audio back to the original sampling rate, for example, when saving the output to a file." -- https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/structOpusHead.html
</ins><span class="cx" style="display: block; padding: 0 10px">                 return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseOggPageHeader() {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://xiph.org/ogg/vorbis/doc/framing.html
</span><span class="cx" style="display: block; padding: 0 10px">                $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -489,7 +536,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                return false;
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                        if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // get some more data, unless eof, in which case fail
</span><span class="cx" style="display: block; padding: 0 10px">                                        return false;
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -528,13 +575,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $oggheader;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseVorbisComments() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $OriginalOffset = $this->ftell();
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $commentdata = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                 $commentdataoffset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                $VorbisCommentPage = 1;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $CommentStartOffset = 0;
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($info['audio']['dataformat']) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'vorbis':
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -765,6 +818,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $mode
+        *
+        * @return string|null
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function SpeexBandModeLookup($mode) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $SpeexBandModeLookup = array();
</span><span class="cx" style="display: block; padding: 0 10px">                if (empty($SpeexBandModeLookup)) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -775,8 +833,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $OggInfoArray
+        * @param int   $SegmentNumber
+        *
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $segmentlength = 0;
</ins><span class="cx" style="display: block; padding: 0 10px">                 for ($i = 0; $i < $SegmentNumber; $i++) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $segmentlength = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($OggInfoArray['segment_table'] as $key => $value) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -789,7 +853,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $segmentlength;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $nominal_bitrate
+        *
+        * @return float
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function get_quality_from_nominal_bitrate($nominal_bitrate) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // decrease precision
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -813,6 +881,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return round($qval, 1); // 5 or 4.9
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $colorspace_id
+        *
+        * @return string|null
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TheoraColorSpace($colorspace_id) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.theora.org/doc/Theora.pdf (table 6.3)
</span><span class="cx" style="display: block; padding: 0 10px">                static $TheoraColorSpaceLookup = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -825,6 +898,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $pixelformat_id
+        *
+        * @return string|null
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TheoraPixelFormat($pixelformat_id) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.theora.org/doc/Theora.pdf (table 6.4)
</span><span class="cx" style="display: block; padding: 0 10px">                static $TheoraPixelFormatLookup = array();
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduletagapetagphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.tag.apetag.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.tag.apetag.php   2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.tag.apetag.php     2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.tag.apetag.php                                       //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing APE tags                               //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -16,9 +16,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_apetag extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        public $inline_attachments = true; // true: return full data for all attachments; false: return no data for all attachments; integer: return data for attachments <= than this; string: save as file to this directory
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * true: return full data for all attachments;
+        * false: return no data for all attachments;
+        * integer: return data for attachments <= than this;
+        * string: save as file to this directory.
+        *
+        * @var int|bool|string
+        */
+       public $inline_attachments = true;
+
</ins><span class="cx" style="display: block; padding: 0 10px">         public $overrideendoffset  = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -150,8 +162,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        switch (strtolower($item_key)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                // http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'replaygain_track_gain':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_replaygain['track']['originator'] = 'unspecified';
</span><span class="cx" style="display: block; padding: 0 10px">                                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -159,8 +171,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'replaygain_track_peak':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_replaygain['track']['originator'] = 'unspecified';
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($thisfile_replaygain['track']['peak'] <= 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -171,8 +183,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'replaygain_album_gain':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_replaygain['album']['originator'] = 'unspecified';
</span><span class="cx" style="display: block; padding: 0 10px">                                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -180,8 +192,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'replaygain_album_peak':
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 $thisfile_replaygain['album']['originator'] = 'unspecified';
</span><span class="cx" style="display: block; padding: 0 10px">                                                if ($thisfile_replaygain['album']['peak'] <= 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -225,7 +237,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                case 'tracknumber':
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (is_array($thisfile_ape_items_current['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                foreach ($thisfile_ape_items_current['data'] as $comment) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                        $thisfile_ape['comments']['track'][] = $comment;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $thisfile_ape['comments']['track_number'][] = $comment;
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        break;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -335,6 +347,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $APEheaderFooterData
+        *
+        * @return array|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function parseAPEheaderFooter($APEheaderFooterData) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -359,6 +376,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $headerfooterinfo;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $rawflagint
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function parseAPEtagFlags($rawflagint) {
</span><span class="cx" style="display: block; padding: 0 10px">                // "Note: APE Tags 1.0 do not use any of the APE Tag flags.
</span><span class="cx" style="display: block; padding: 0 10px">                // All are set to zero on creation and ignored on reading."
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -374,6 +396,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $flags;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $contenttypeid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function APEcontentTypeFlagLookup($contenttypeid) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $APEcontentTypeFlagLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0 => 'utf-8',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -384,6 +411,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $itemkey
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function APEtagItemIsUTF8Lookup($itemkey) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $APEtagItemIsUTF8Lookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'title',
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduletagid3v1php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.tag.id3v1.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.tag.id3v1.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.tag.id3v1.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> //                                                             //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.tag.id3v1.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing ID3v1 tags                             //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -17,7 +17,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_id3v1 extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -43,9 +45,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // If second-last byte of comment field is null and last byte of comment field is non-null
</span><span class="cx" style="display: block; padding: 0 10px">                        // then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
-                               $ParsedID3v1['track']   = ord(substr($ParsedID3v1['comment'], 29,  1));
-                               $ParsedID3v1['comment'] =     substr($ParsedID3v1['comment'],  0, 28);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if (($id3v1tag[125] === "\x00") && ($id3v1tag[126] !== "\x00")) {
+                               $ParsedID3v1['track_number'] = ord(substr($ParsedID3v1['comment'], 29,  1));
+                               $ParsedID3v1['comment']      =     substr($ParsedID3v1['comment'],  0, 28);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        $ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -66,7 +68,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $ID3v1encoding = 'ISO-8859-1';
</span><span class="cx" style="display: block; padding: 0 10px">                        foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
</span><span class="cx" style="display: block; padding: 0 10px">                                foreach ($valuearray as $key => $value) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (preg_match('#^[\\x00-\\x40\\xA8\\xB8\\x80-\\xFF]+$#', $value)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                                $ID3v1encoding = $id3v1_bad_encoding;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -89,7 +91,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $ParsedID3v1['year'],
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        (isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
</span><span class="cx" style="display: block; padding: 0 10px">                                                                                        $ParsedID3v1['comment'],
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                                                        (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                                                 (!empty($ParsedID3v1['track_number']) ? $ParsedID3v1['track_number'] : ''));
</ins><span class="cx" style="display: block; padding: 0 10px">                         $ParsedID3v1['padding_valid'] = true;
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($id3v1tag !== $GoodFormatID3v1tag) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $ParsedID3v1['padding_valid'] = false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -124,10 +126,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $str
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function cutfield($str) {
</span><span class="cx" style="display: block; padding: 0 10px">                return trim(substr($str, 0, strcspn($str, "\x00")));
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param bool $allowSCMPXextended
+        *
+        * @return string[]
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ArrayOfGenres($allowSCMPXextended=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $GenreLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0    => 'Blues',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -312,6 +324,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $genreid
+        * @param bool   $allowSCMPXextended
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($genreid) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 'RX':
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -328,6 +346,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $genre
+        * @param bool   $allowSCMPXextended
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LookupGenreID($genre, $allowSCMPXextended=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                $GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
</span><span class="cx" style="display: block; padding: 0 10px">                $LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -339,6 +363,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $OriginalGenre
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function StandardiseID3v1GenreName($OriginalGenre) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return self::LookupGenreName($GenreID);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -346,6 +375,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $OriginalGenre;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string     $title
+        * @param string     $artist
+        * @param string     $album
+        * @param string     $year
+        * @param int        $genreid
+        * @param string     $comment
+        * @param int|string $track
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
</span><span class="cx" style="display: block; padding: 0 10px">                $ID3v1Tag  = 'TAG';
</span><span class="cx" style="display: block; padding: 0 10px">                $ID3v1Tag .= str_pad(trim(substr($title,  0, 30)), 30, "\x00", STR_PAD_RIGHT);
</span></span></pre></div>
<a id="trunksrcwpincludesID3moduletagid3v2php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.tag.id3v2.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.tag.id3v2.php    2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.tag.id3v2.php      2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> ///                                                            //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.tag.id3v2.php                                        //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing ID3v2 tags                             //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -20,6 +20,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><span class="cx" style="display: block; padding: 0 10px">        public $StartingOffset = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -56,8 +59,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $header = $this->fread(10);
</span><span class="cx" style="display: block; padding: 0 10px">                if (substr($header, 0, 3) == 'ID3'  &&  strlen($header) == 10) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $thisfile_id3v2['majorversion'] = ord($header{3});
-                       $thisfile_id3v2['minorversion'] = ord($header{4});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $thisfile_id3v2['majorversion'] = ord($header[3]);
+                       $thisfile_id3v2['minorversion'] = ord($header[4]);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // shortcut
</span><span class="cx" style="display: block; padding: 0 10px">                        $id3v2_majorversion = &$thisfile_id3v2['majorversion'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -76,7 +79,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $id3_flags = ord($header{5});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $id3_flags = ord($header[5]);
</ins><span class="cx" style="display: block; padding: 0 10px">                 switch ($id3v2_majorversion) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 2:
</span><span class="cx" style="display: block; padding: 0 10px">                                // %ab000000 in v2.2
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -257,7 +260,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_id3v2['padding']['length'] = strlen($framedata);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $thisfile_id3v2['padding']['valid']  = true;
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if ($framedata{$i} != "\x00") {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if ($framedata[$i] != "\x00") {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $thisfile_id3v2['padding']['valid'] = false;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -266,6 +269,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px">                                        break; // skip rest of ID3v2 header
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $frame_header = null;
+                               $frame_name   = null;
+                               $frame_size   = null;
+                               $frame_flags  = null;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if ($id3v2_majorversion == 2) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Frame ID  $xx xx xx (three characters)
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Size      $xx xx xx (24-bit integer)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -319,7 +326,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $len = strlen($framedata);
</span><span class="cx" style="display: block; padding: 0 10px">                                        for ($i = 0; $i < $len; $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                if ($framedata{$i} != "\x00") {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         if ($framedata[$i] != "\x00") {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $thisfile_id3v2['padding']['valid'] = false;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -427,11 +434,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $footer = $this->fread(10);
</span><span class="cx" style="display: block; padding: 0 10px">                        if (substr($footer, 0, 3) == '3DI') {
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_id3v2['footer'] = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $thisfile_id3v2['majorversion_footer'] = ord($footer{3});
-                               $thisfile_id3v2['minorversion_footer'] = ord($footer{4});
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $thisfile_id3v2['majorversion_footer'] = ord($footer[3]);
+                               $thisfile_id3v2['minorversion_footer'] = ord($footer[4]);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($thisfile_id3v2['majorversion_footer'] <= 4) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $id3_flags = ord(substr($footer{5}));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $id3_flags = ord($footer[5]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $thisfile_id3v2_flags['unsynch_footer']  = (bool) ($id3_flags & 0x80);
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_id3v2_flags['extfoot_footer']  = (bool) ($id3_flags & 0x40);
</span><span class="cx" style="display: block; padding: 0 10px">                                $thisfile_id3v2_flags['experim_footer']  = (bool) ($id3_flags & 0x20);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -452,10 +459,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($key, $value, $genres, $genre);
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (isset($thisfile_id3v2['comments']['track'])) {
-                       foreach ($thisfile_id3v2['comments']['track'] as $key => $value) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($thisfile_id3v2['comments']['track_number'])) {
+                       foreach ($thisfile_id3v2['comments']['track_number'] as $key => $value) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (strstr($value, '/')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 list($thisfile_id3v2['comments']['track_number'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track_number'][$key]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -498,7 +505,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $genrestring
+        *
+        * @return array
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseID3v2GenreString($genrestring) {
</span><span class="cx" style="display: block; padding: 0 10px">                // Parse genres into arrays of genreName and genreID
</span><span class="cx" style="display: block; padding: 0 10px">                // ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -530,7 +541,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ($genre_elements as $element) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $element = trim($element);
</span><span class="cx" style="display: block; padding: 0 10px">                        if ($element) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                if (preg_match('#^[0-9]{1,3}#', $element)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         if (preg_match('#^[0-9]{1,3}$#', $element)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         $clean_genres[] = getid3_id3v1::LookupGenreName($element);
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $clean_genres[] = str_replace('((', '(', $element);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -540,7 +551,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return $clean_genres;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param array $parsedFrame
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function ParseID3v2Frame(&$parsedFrame) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                // shortcuts
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -657,16 +672,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $parsedFrame['encodingid']  = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $frame_description));
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['description']));
</ins><span class="cx" style="display: block; padding: 0 10px">                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
</ins><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -678,7 +691,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        //unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif ($parsedFrame['frame_name'][0] == 'T') { // 4.2. T??[?] Text information frame
</ins><span class="cx" style="display: block; padding: 0 10px">                         //   There may only be one text information frame of its kind in an tag.
</span><span class="cx" style="display: block; padding: 0 10px">                        // <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
</span><span class="cx" style="display: block; padding: 0 10px">                        // excluding 'TXXX' described in 4.2.6.>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -692,10 +705,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encodingid'] = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']   = $this->TextEncodingNameLookup($frame_textencoding);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                // ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
</span><span class="cx" style="display: block; padding: 0 10px">                                // This of course breaks when an artist name contains slash character, e.g. "AC/DC"
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -751,38 +764,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
-                       $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
-
-                       $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator);
-                       if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
-                               $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
-                       }
-                       if ($frame_terminatorpos) {
-                               // there are null bytes after the data - this is not according to spec
-                               // only use data up to first null byte
-                               $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
-                       } else {
-                               // no null bytes following data, just use all data
-                               $frame_urldata = (string) $parsedFrame['data'];
-                       }
-
</del><span class="cx" style="display: block; padding: 0 10px">                         $parsedFrame['encodingid']  = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);           // according to the frame text encoding
+                       $parsedFrame['url']         = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); // always ISO-8859-1
+                       $parsedFrame['description'] = $this->RemoveStringTerminator($parsedFrame['description'], $frame_textencoding_terminator);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['url']         = $frame_urldata;
-                       $parsedFrame['description'] = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                } elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         } elseif ($parsedFrame['frame_name'][0] == 'W') { // 4.3. W??? URL link frames
</ins><span class="cx" style="display: block; padding: 0 10px">                         //   There may only be one URL link frame of its kind in a tag,
</span><span class="cx" style="display: block; padding: 0 10px">                        //   except when stated otherwise in the frame description
</span><span class="cx" style="display: block; padding: 0 10px">                        // <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -789,9 +784,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // described in 4.3.2.>
</span><span class="cx" style="display: block; padding: 0 10px">                        // URL              <text string>
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['url'] = trim($parsedFrame['data']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1
</ins><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url'];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -813,7 +808,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']   = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data_raw']   = (string) substr($parsedFrame['data'], $frame_offset);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        // http://www.getid3.org/phpBB3/viewtopic.php?t=1369
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // https://www.getid3.org/phpBB3/viewtopic.php?t=1369
</ins><span class="cx" style="display: block; padding: 0 10px">                         // "this tag typically contains null terminated strings, which are associated in pairs"
</span><span class="cx" style="display: block; padding: 0 10px">                        // "there are users that use the tag incorrectly"
</span><span class="cx" style="display: block; padding: 0 10px">                        $IPLS_parts = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -933,6 +928,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['bitsforbytesdeviation']   = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['bitsformsdeviation']      = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data'] = substr($parsedFrame['data'], 10);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $deviationbitstream = '';
</ins><span class="cx" style="display: block; padding: 0 10px">                         while ($frame_offset < strlen($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -994,12 +990,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encodingid']   = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1006,7 +1000,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['language']     = $frame_language;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['description']  = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1061,7 +1054,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                        $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 if (($timestampindex == 0) && (ord($frame_remainingdata[0]) != 0)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 // timestamp probably omitted for first data item
</span><span class="cx" style="display: block; padding: 0 10px">                                        } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                                $parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1102,12 +1095,10 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                               if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                                       // if description only contains a BOM or terminator then make it blank
-                                       $frame_description = '';
-                               }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                               $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                $frame_text = $this->RemoveStringTerminator($frame_text, $frame_textencoding_terminator);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['encodingid']   = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1114,7 +1105,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['language']     = $frame_language;
</span><span class="cx" style="display: block; padding: 0 10px">                                $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $parsedFrame['description']  = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                                 $parsedFrame['data']         = $frame_text;
</span><span class="cx" style="display: block; padding: 0 10px">                                if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (!empty($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1407,30 +1397,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                               if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                                       // if description only contains a BOM or terminator then make it blank
-                                       $frame_description = '';
-                               }
-                               $parsedFrame['encodingid']       = $frame_textencoding;
-                               $parsedFrame['encoding']         = $this->TextEncodingNameLookup($frame_textencoding);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $parsedFrame['description']   = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                               $parsedFrame['description']   = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
+                               $parsedFrame['encodingid']    = $frame_textencoding;
+                               $parsedFrame['encoding']      = $this->TextEncodingNameLookup($frame_textencoding);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($id3v2_majorversion == 2) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $parsedFrame['imagetype']    = $frame_imagetype;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 } else {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $parsedFrame['mime']         = $frame_mimetype;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $parsedFrame['mime']      = isset($frame_mimetype) ? $frame_mimetype : null;
</ins><span class="cx" style="display: block; padding: 0 10px">                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $parsedFrame['picturetypeid']    = $frame_picturetype;
-                               $parsedFrame['picturetype']      = $this->APICPictureTypeLookup($frame_picturetype);
-                               $parsedFrame['description']      = $frame_description;
-                               $parsedFrame['data']             = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
-                               $parsedFrame['datalength']       = strlen($parsedFrame['data']);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $parsedFrame['picturetypeid'] = $frame_picturetype;
+                               $parsedFrame['picturetype']   = $this->APICPictureTypeLookup($frame_picturetype);
+                               $parsedFrame['data']          = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
+                               $parsedFrame['datalength']    = strlen($parsedFrame['data']);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $parsedFrame['image_mime'] = '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $parsedFrame['image_mime']    = '';
</ins><span class="cx" style="display: block; padding: 0 10px">                                 $imageinfo = array();
</span><span class="cx" style="display: block; padding: 0 10px">                                if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                $parsedFrame['image_mime']       = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                         $parsedFrame['image_mime']       = image_type_to_mime_type($imagechunkcheck[2]);
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 if ($imagechunkcheck[0]) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                        $parsedFrame['image_width']  = $imagechunkcheck[0];
</span><span class="cx" style="display: block; padding: 0 10px">                                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1446,6 +1432,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px">                                                break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        $dir = '';
</ins><span class="cx" style="display: block; padding: 0 10px">                                         if ($this->getid3->option_save_attachments === true) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                // great
</span><span class="cx" style="display: block; padding: 0 10px"> /*
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1533,11 +1520,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['objectdata']  = (string) substr($parsedFrame['data'], $frame_offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1546,7 +1530,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['mime']        = $frame_mimetype;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['filename']    = $frame_filename;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['description'] = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                         unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1616,16 +1599,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = $frame_terminatorpos + strlen("\x00");
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $frame_offset = $frame_terminatorpos + strlen("\x00");
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['ownerid']     = $frame_ownerid;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['data']        = (string) substr($parsedFrame['data'], $frame_offset);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['description'] = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                         unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1721,7 +1700,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encodingid']   = $frame_textencoding;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['data']         = (string) substr($parsedFrame['data'], $frame_offset);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+                       $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
</ins><span class="cx" style="display: block; padding: 0 10px">                         if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1759,6 +1739,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset += 8;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        $parsedFrame['seller'] = $this->RemoveStringTerminator($parsedFrame['seller'], $this->TextEncodingTerminatorLookup($frame_textencoding));
</ins><span class="cx" style="display: block; padding: 0 10px">                         unset($parsedFrame['data']);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1817,11 +1798,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
</span><span class="cx" style="display: block; padding: 0 10px">                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
</span><span class="cx" style="display: block; padding: 0 10px">                        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
</ins><span class="cx" style="display: block; padding: 0 10px">                         $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1838,7 +1816,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['receivedasid']      = $frame_receivedasid;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['receivedas']        = $this->COMRReceivedAsLookup($frame_receivedasid);
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['sellername']        = $frame_sellername;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $parsedFrame['description']       = $frame_description;
</del><span class="cx" style="display: block; padding: 0 10px">                         $parsedFrame['mime']              = $frame_mimetype;
</span><span class="cx" style="display: block; padding: 0 10px">                        $parsedFrame['logo']              = $frame_sellerlogo;
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($parsedFrame['data']);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2002,9 +1979,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // Element ID      <text string> $00
</span><span class="cx" style="display: block; padding: 0 10px">                        // Start time      $xx xx xx xx
</span><span class="cx" style="display: block; padding: 0 10px">                        // End time        $xx xx xx xx
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-            // Start offset    $xx xx xx xx
-            // End offset      $xx xx xx xx
-            // <Optional embedded sub-frames>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Start offset    $xx xx xx xx
+                       // End offset      $xx xx xx xx
+                       // <Optional embedded sub-frames>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2045,7 +2022,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
</span><span class="cx" style="display: block; padding: 0 10px">                                        $subframe['text']       =     substr($subframe_rawdata, 1);
</span><span class="cx" style="display: block; padding: 0 10px">                                        $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));
</ins><span class="cx" style="display: block; padding: 0 10px">                                         switch (substr($encoding_converted_text, 0, 2)) {
</span><span class="cx" style="display: block; padding: 0 10px">                                                case "\xFF\xFE":
</span><span class="cx" style="display: block; padding: 0 10px">                                                case "\xFE\xFF":
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2065,22 +2042,51 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                                        break;
</span><span class="cx" style="display: block; padding: 0 10px">                                        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
-                                               if ($subframe['name'] == 'TIT2') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 switch ($subframe['name']) {
+                                               case 'TIT2':
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $parsedFrame['chapter_name']        = $encoding_converted_text;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                } elseif ($subframe['name'] == 'TIT3') {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'TIT3':
</ins><span class="cx" style="display: block; padding: 0 10px">                                                         $parsedFrame['chapter_description'] = $encoding_converted_text;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                }
-                                               $parsedFrame['subframes'][] = $subframe;
-                                       } else {
-                                               $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                                 $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'WXXX':
+                                                       list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2);
+                                                       $parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url'];
+                                                       $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'APIC':
+                                                       if (preg_match('#^([^\\x00]+)*\\x00(.)([^\\x00]+)*\\x00(.+)$#s', $subframe['text'], $matches)) {
+                                                               list($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata) = $matches;
+                                                               $subframe['image_mime']   = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_mime));
+                                                               $subframe['picture_type'] = $this->APICPictureTypeLookup($subframe_apic_picturetype);
+                                                               $subframe['description']  = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_description));
+                                                               if (strlen($this->TextEncodingTerminatorLookup($subframe['encoding'])) == 2) {
+                                                                       // the null terminator between "description" and "picture data" could be either 1 byte (ISO-8859-1, UTF-8) or two bytes (UTF-16)
+                                                                       // the above regex assumes one byte, if it's actually two then strip the second one here
+                                                                       $subframe_apic_picturedata = substr($subframe_apic_picturedata, 1);
+                                                               }
+                                                               $subframe['data'] = $subframe_apic_picturedata;
+                                                               unset($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata);
+                                                               unset($subframe['text'], $parsedFrame['text']);
+                                                               $parsedFrame['subframes'][] = $subframe;
+                                                               $parsedFrame['picture_present'] = true;
+                                                       } else {
+                                                               $this->warning('ID3v2.CHAP subframe #'.(count($parsedFrame['subframes']) + 1).' "'.$subframe['name'].'" not in expected format');
+                                                       }
+                                                       break;
+                                               default:
+                                                       $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (supported: TIT2, TIT3, WXXX, APIC)');
+                                                       break;
</ins><span class="cx" style="display: block; padding: 0 10px">                                         }
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="cx" style="display: block; padding: 0 10px">                                unset($subframe_rawdata, $subframe, $encoding_converted_text);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                unset($parsedFrame['data']); // debatable whether this this be here, without it the returned structure may contain a large amount of duplicate data if chapters contain APIC
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $id3v2_chapter_entry = array();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description') as $id3v2_chapter_key) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description', 'chapter_url', 'picture_present') as $id3v2_chapter_key) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                 if (isset($parsedFrame[$id3v2_chapter_key])) {
</span><span class="cx" style="display: block; padding: 0 10px">                                        $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
</span><span class="cx" style="display: block; padding: 0 10px">                                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2099,7 +2105,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        // CTOC flags        %xx
</span><span class="cx" style="display: block; padding: 0 10px">                        // Entry count       $xx
</span><span class="cx" style="display: block; padding: 0 10px">                        // Child Element ID  <string>$00   /* zero or more child CHAP or CTOC entries */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-            // <Optional embedded sub-frames>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // <Optional embedded sub-frames>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        $frame_offset = 0;
</span><span class="cx" style="display: block; padding: 0 10px">                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2181,11 +2187,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $data
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function DeUnsynchronise($data) {
</span><span class="cx" style="display: block; padding: 0 10px">                return str_replace("\xFF\x00", "\xFF", $data);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'No more than 128 frames and 1 MB total tag size',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2196,6 +2211,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LookupExtendedHeaderRestrictionsTextEncodings = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'No restrictions',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2204,6 +2224,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'No restrictions',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2214,6 +2239,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LookupExtendedHeaderRestrictionsImageEncoding = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'No restrictions',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2222,6 +2252,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'No restrictions',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2232,6 +2267,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $currencyid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupCurrencyUnits($currencyid) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2428,7 +2468,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $currencyid
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function LookupCurrencyCountry($currencyid) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2624,8 +2668,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $languagecode
+        * @param bool   $casesensitive
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function LanguageLookup($languagecode, $casesensitive=false) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                if (!$casesensitive) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3081,7 +3129,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ETCOEventLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (($index >= 0x17) && ($index <= 0xDF)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return 'reserved for future use';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3125,6 +3177,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($EventLookup[$index]) ? $EventLookup[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function SYTLContentTypeLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $SYTLContentTypeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'other',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3141,6 +3198,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int   $index
+        * @param bool $returnarray
+        *
+        * @return array|string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function APICPictureTypeLookup($index, $returnarray=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $APICPictureTypeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'Other',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3171,6 +3234,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function COMRReceivedAsLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $COMRReceivedAsLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'Other',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3187,6 +3255,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $index
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function RVA2ChannelTypeLookup($index) {
</span><span class="cx" style="display: block; padding: 0 10px">                static $RVA2ChannelTypeLookup = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        0x00 => 'Other',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3203,6 +3276,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : '');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $framename
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FrameNameLongLookup($framename) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3354,7 +3432,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        TYER    Year
</span><span class="cx" style="display: block; padding: 0 10px">                        UFI     Unique file identifier
</span><span class="cx" style="display: block; padding: 0 10px">                        UFID    Unique file identifier
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        ULT     Unsychronised lyric/text transcription
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 ULT     Unsynchronised lyric/text transcription
</ins><span class="cx" style="display: block; padding: 0 10px">                         USER    Terms of use
</span><span class="cx" style="display: block; padding: 0 10px">                        USLT    Unsynchronised lyric/text transcription
</span><span class="cx" style="display: block; padding: 0 10px">                        WAF     Official audio file webpage
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3386,7 +3464,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @param string $framename
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function FrameNameShortLookup($framename) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $begin = __LINE__;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3538,7 +3620,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        TYER    year
</span><span class="cx" style="display: block; padding: 0 10px">                        UFI     unique_file_identifier
</span><span class="cx" style="display: block; padding: 0 10px">                        UFID    unique_file_identifier
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        ULT     unsychronised_lyric
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 ULT     unsynchronised_lyric
</ins><span class="cx" style="display: block; padding: 0 10px">                         USER    terms_of_use
</span><span class="cx" style="display: block; padding: 0 10px">                        USLT    unsynchronised_lyric
</span><span class="cx" style="display: block; padding: 0 10px">                        WAF     url_file
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3566,6 +3648,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $encoding
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TextEncodingTerminatorLookup($encoding) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.id3.org/id3v2.4.0-structure.txt
</span><span class="cx" style="display: block; padding: 0 10px">                // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3579,6 +3666,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00");
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $encoding
+        *
+        * @return string
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function TextEncodingNameLookup($encoding) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.id3.org/id3v2.4.0-structure.txt
</span><span class="cx" style="display: block; padding: 0 10px">                // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3592,6 +3684,41 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $string
+        * @param string $terminator
+        *
+        * @return string
+        */
+       public static function RemoveStringTerminator($string, $terminator) {
+               // Null terminator at end of comment string is somewhat ambiguous in the specification, may or may not be implemented by various taggers. Remove terminator only if present.
+               // https://github.com/JamesHeinrich/getID3/issues/121
+               // https://community.mp3tag.de/t/x-trailing-nulls-in-id3v2-comments/19227
+               if (substr($string, -strlen($terminator), strlen($terminator)) === $terminator) {
+                       $string = substr($string, 0, -strlen($terminator));
+               }
+               return $string;
+       }
+
+       /**
+        * @param string $string
+        *
+        * @return string
+        */
+       public static function MakeUTF16emptyStringEmpty($string) {
+               if (in_array($string, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
+                       // if string only contains a BOM or terminator then make it actually an empty string
+                       $string = '';
+               }
+               return $string;
+       }
+
+       /**
+        * @param string $framename
+        * @param int    $id3v2majorversion
+        *
+        * @return bool|int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
</span><span class="cx" style="display: block; padding: 0 10px">                switch ($id3v2majorversion) {
</span><span class="cx" style="display: block; padding: 0 10px">                        case 2:
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3606,12 +3733,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $numberstring
+        * @param bool   $allowdecimal
+        * @param bool   $allownegative
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
</span><span class="cx" style="display: block; padding: 0 10px">                for ($i = 0; $i < strlen($numberstring); $i++) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
-                               if (($numberstring{$i} == '.') && $allowdecimal) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 if ((chr($numberstring[$i]) < chr('0')) || (chr($numberstring[$i]) > chr('9'))) {
+                               if (($numberstring[$i] == '.') && $allowdecimal) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // allowed
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                } elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         } elseif (($numberstring[$i] == '-') && $allownegative && ($i == 0)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                                         // allowed
</span><span class="cx" style="display: block; padding: 0 10px">                                } else {
</span><span class="cx" style="display: block; padding: 0 10px">                                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3621,6 +3755,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $datestamp
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function IsValidDateStampString($datestamp) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (strlen($datestamp) != 8) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return false;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3649,10 +3788,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $majorversion
+        *
+        * @return int
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ID3v2HeaderLength($majorversion) {
</span><span class="cx" style="display: block; padding: 0 10px">                return (($majorversion == 2) ? 6 : 10);
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $frame_name
+        *
+        * @return string|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public static function ID3v22iTunesBrokenFrameName($frame_name) {
</span><span class="cx" style="display: block; padding: 0 10px">                // iTunes (multiple versions) has been known to write ID3v2.3 style frames
</span><span class="cx" style="display: block; padding: 0 10px">                // but use ID3v2.2 frame names, right-padded using either [space] or [null]
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3739,3 +3888,4 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins></span></pre></div>
<a id="trunksrcwpincludesID3moduletaglyrics3php"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/module.tag.lyrics3.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/module.tag.lyrics3.php  2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/module.tag.lyrics3.php    2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,12 +1,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <?php
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//  available at http://getid3.sourceforge.net                 //
-//            or http://www.getid3.org                         //
-//          also https://github.com/JamesHeinrich/getID3       //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//  available at https://github.com/JamesHeinrich/getID3       //
+//            or https://www.getid3.org                        //
+//            or http://getid3.sourceforge.net                 //
+//  see readme.txt for more details                            //
</ins><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-// See readme.txt for more details                             //
-/////////////////////////////////////////////////////////////////
</del><span class="cx" style="display: block; padding: 0 10px"> ///                                                            //
</span><span class="cx" style="display: block; padding: 0 10px"> // module.tag.lyrics3.php                                      //
</span><span class="cx" style="display: block; padding: 0 10px"> // module for analyzing Lyrics3 tags                           //
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -17,7 +17,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> class getid3_lyrics3 extends getid3_handler
</span><span class="cx" style="display: block; padding: 0 10px"> {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Analyze() {
</span><span class="cx" style="display: block; padding: 0 10px">                $info = &$this->getid3->info;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -61,7 +63,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                        // Lyrics3v2, no ID3v1, no APE
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        $lyrics3size    = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 $lyrics3size    = (int) strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
</ins><span class="cx" style="display: block; padding: 0 10px">                         $lyrics3offset  = $info['filesize'] - $lyrics3size;
</span><span class="cx" style="display: block; padding: 0 10px">                        $lyrics3version = 2;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -96,7 +98,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if (isset($lyrics3offset)) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if (isset($lyrics3offset) && isset($lyrics3version) && isset($lyrics3size)) {
</ins><span class="cx" style="display: block; padding: 0 10px">                         $info['avdataend'] = $lyrics3offset;
</span><span class="cx" style="display: block; padding: 0 10px">                        $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -126,6 +128,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param int $endoffset
+        * @param int $version
+        * @param int $length
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function getLyrics3Data($endoffset, $version, $length) {
</span><span class="cx" style="display: block; padding: 0 10px">                // http://www.volweb.cz/str/tags.htm
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -142,6 +151,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px">                $rawdata = $this->fread($length);
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $ParsedLyrics3 = array();
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $ParsedLyrics3['raw']['lyrics3version'] = $version;
</span><span class="cx" style="display: block; padding: 0 10px">                $ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
</span><span class="cx" style="display: block; padding: 0 10px">                $ParsedLyrics3['tag_offset_start']      = $endoffset;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -250,6 +261,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $rawtimestamp
+        *
+        * @return int|false
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Lyrics3Timestamp2Seconds($rawtimestamp) {
</span><span class="cx" style="display: block; padding: 0 10px">                if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) {
</span><span class="cx" style="display: block; padding: 0 10px">                        return (int) (($regs[1] * 60) + $regs[2]);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -257,8 +273,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return false;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param array $Lyrics3data
+        *
+        * @return bool
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function Lyrics3LyricsTimestampParse(&$Lyrics3data) {
</span><span class="cx" style="display: block; padding: 0 10px">                $lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']);
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $notimestamplyricsarray = array();
</ins><span class="cx" style="display: block; padding: 0 10px">                 foreach ($lyricsarray as $key => $lyricline) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $regs = array();
</span><span class="cx" style="display: block; padding: 0 10px">                        unset($thislinetimestamps);
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -287,6 +309,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                return true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        /**
+        * @param string $char
+        *
+        * @return bool|null
+        */
</ins><span class="cx" style="display: block; padding: 0 10px">         public function IntString2Bool($char) {
</span><span class="cx" style="display: block; padding: 0 10px">                if ($char == '1') {
</span><span class="cx" style="display: block; padding: 0 10px">                        return true;
</span></span></pre></div>
<a id="trunksrcwpincludesID3readmetxt"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/ID3/readme.txt</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/ID3/readme.txt      2019-09-14 18:20:58 UTC (rev 46111)
+++ trunk/src/wp-includes/ID3/readme.txt        2019-09-14 19:06:09 UTC (rev 46112)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1,7 +1,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> /// getID3() by James Heinrich <info@getid3.org>               //
</span><span class="cx" style="display: block; padding: 0 10px"> //  available at http://getid3.sourceforge.net                 //
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-//            or http://www.getid3.org                         //
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+//            or https://www.getid3.org                        //
</ins><span class="cx" style="display: block; padding: 0 10px"> //          also https://github.com/JamesHeinrich/getID3       //
</span><span class="cx" style="display: block; padding: 0 10px"> /////////////////////////////////////////////////////////////////
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -18,9 +18,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> GNU LGPL: https://gnu.org/licenses/lgpl.html                 (v3)
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-Mozilla MPL: http://www.mozilla.org/MPL/2.0/                 (v2)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+Mozilla MPL: https://www.mozilla.org/MPL/2.0/                (v2)
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-getID3 Commercial License: http://getid3.org/#gCL (payment required)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> *****************************************************************
</span><span class="cx" style="display: block; padding: 0 10px"> *****************************************************************
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -28,10 +28,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> directory of the getID3 distribution.
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-       +---------------------------------------------+
-       | If you want to donate, there is a link on   |
-       | http://www.getid3.org for PayPal donations. |
-       +---------------------------------------------+
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+       +----------------------------------------------+
+       | If you want to donate, there is a link on    |
+       | https://www.getid3.org for PayPal donations. |
+       +----------------------------------------------+
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> Quick Start
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -77,7 +77,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  ¤ audio-lossy:
</span><span class="cx" style="display: block; padding: 0 10px">   * MP3/MP2/MP1
</span><span class="cx" style="display: block; padding: 0 10px">   * MPC / Musepack
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  * Ogg (Vorbis, OggFLAC, Speex)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  * Ogg (Vorbis, OggFLAC, Speex, Opus)
</ins><span class="cx" style="display: block; padding: 0 10px">   * AAC / MP4
</span><span class="cx" style="display: block; padding: 0 10px">   * AC3
</span><span class="cx" style="display: block; padding: 0 10px">   * DTS
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,9 +145,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> Requirements
</span><span class="cx" style="display: block; padding: 0 10px"> ===========================================================================
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-* PHP 4.2.0 up to 5.2.x for getID3() 1.7.x (and earlier)
-* PHP 5.0.5 (or higher) for getID3() 1.8.x (and up)
-* PHP 5.0.5 (or higher) for getID3() 2.0.x (and up)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+* PHP 4.2.0 up to 5.2.x for getID3() 1.7.x  (and earlier)
+* PHP 5.0.5 (or higher) for getID3() 1.8.x  (and up)
+* PHP 5.3.0 (or higher) for getID3() 1.9.17 (and up)
+* PHP 5.3.0 (or higher) for getID3() 2.0.x  (and up)
</ins><span class="cx" style="display: block; padding: 0 10px"> * at least 4MB memory for PHP. 8MB or more is highly recommended.
</span><span class="cx" style="display: block; padding: 0 10px">   12MB is required with all modules loaded.
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -177,24 +178,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Copy remote file locally to scan with getID3()
</span><span class="cx" style="display: block; padding: 0 10px"> $remotefilename = 'http://www.example.com/filename.mp3';
</span><span class="cx" style="display: block; padding: 0 10px"> if ($fp_remote = fopen($remotefilename, 'rb')) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-    $localtempfilename = tempnam('/tmp', 'getID3');
-    if ($fp_local = fopen($localtempfilename, 'wb')) {
-        while ($buffer = fread($fp_remote, 8192)) {
-            fwrite($fp_local, $buffer);
-        }
-        fclose($fp_local);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $localtempfilename = tempnam('/tmp', 'getID3');
+       if ($fp_local = fopen($localtempfilename, 'wb')) {
+               while ($buffer = fread($fp_remote, 32768)) {
+                       fwrite($fp_local, $buffer);
+               }
+               fclose($fp_local);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $remote_headers = array_change_key_case(get_headers($remotefilename, 1), CASE_LOWER);
+               $remote_filesize = (isset($remote_headers['content-length']) ? (is_array($remote_headers['content-length']) ? $remote_headers['content-length'][count($remote_headers['content-length']) - 1] : $remote_headers['content-length']) : null);
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Initialize getID3 engine
</span><span class="cx" style="display: block; padding: 0 10px">                $getID3 = new getID3;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $ThisFileInfo = $getID3->analyze($filename);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $ThisFileInfo = $getID3->analyze($localtempfilename, $remote_filesize, basename($remotefilename));
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        // Delete temporary file
-        unlink($localtempfilename);
-    }
-    fclose($fp_remote);
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Delete temporary file
+               unlink($localtempfilename);
+       }
+       fclose($fp_remote);
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+Note: since v1.9.9-20150212 it is possible a second and third parameter
+to $getID3->analyze(), for original filesize and original filename
+respectively. This permits you to download only a portion of a large remote
+file but get accurate playtime estimates, assuming the format only requires
+the beginning of the file for correct format analysis.
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> See /demos/demo.write.php for how to write tags.
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -292,7 +301,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> Future Plans
</span><span class="cx" style="display: block; padding: 0 10px"> ===========================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-http://www.getid3.org/phpBB3/viewforum.php?f=7
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+https://www.getid3.org/phpBB3/viewforum.php?f=7
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> * Better support for MP4 container format
</span><span class="cx" style="display: block; padding: 0 10px"> * Scan for appended ID3v2 tag at end of file per ID3v2.4 specs (Section 5.0)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -334,11 +343,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Optional scan-through-frames for AVI verification
</span><span class="cx" style="display: block; padding: 0 10px">   (thanks rockcohenØmassive-interactive*nl)
</span><span class="cx" style="display: block; padding: 0 10px"> * Support for TTF (thanks infoØbutterflyx*com)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-* Support for DSS (http://www.getid3.org/phpBB3/viewtopic.php?t=171)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+* Support for DSS (https://www.getid3.org/phpBB3/viewtopic.php?t=171)
</ins><span class="cx" style="display: block; padding: 0 10px"> * Support for SMAF (http://smaf-yamaha.com/what/demo.html)
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-  http://www.getid3.org/phpBB3/viewtopic.php?t=182
-* Support for AMR (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
-* Support for 3gpp (http://www.getid3.org/phpBB3/viewtopic.php?t=195)
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+  https://www.getid3.org/phpBB3/viewtopic.php?t=182
+* Support for AMR (https://www.getid3.org/phpBB3/viewtopic.php?t=195)
+* Support for 3gpp (https://www.getid3.org/phpBB3/viewtopic.php?t=195)
</ins><span class="cx" style="display: block; padding: 0 10px"> * Support for ID4 (http://www.wackysoft.cjb.net grizlyY2KØhotmail*com)
</span><span class="cx" style="display: block; padding: 0 10px"> * Parse XML data returned in Ogg comments
</span><span class="cx" style="display: block; padding: 0 10px"> * Parse XML data from Quicktime SMIL metafiles (klausrathØmac*com)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -374,7 +383,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> Known Bugs/Issues in getID3() that may be fixed eventually
</span><span class="cx" style="display: block; padding: 0 10px"> ===========================================================================
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-http://www.getid3.org/phpBB3/viewtopic.php?t=25
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+https://www.getid3.org/phpBB3/viewtopic.php?t=25
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> * Cannot determine bitrate for MPEG video with VBR video data
</span><span class="cx" style="display: block; padding: 0 10px">   (need documentation)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -400,7 +409,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> Known Bugs/Issues in getID3() that cannot be fixed
</span><span class="cx" style="display: block; padding: 0 10px"> --------------------------------------------------
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-http://www.getid3.org/phpBB3/viewtopic.php?t=25
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+https://www.getid3.org/phpBB3/viewtopic.php?t=25
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> * 32-bit PHP installations only:
</span><span class="cx" style="display: block; padding: 0 10px">   Files larger than 2GB cannot always be parsed fully by getID3()
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -430,8 +439,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> Known Bugs/Issues in other programs
</span><span class="cx" style="display: block; padding: 0 10px"> -----------------------------------
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-http://www.getid3.org/phpBB3/viewtopic.php?t=25
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+https://www.getid3.org/phpBB3/viewtopic.php?t=25
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+* MusicBrainz Picard (at least up to v1.3.2) writes multiple
+  ID3v2.3 genres in non-standard forward-slash separated text
+  rather than parenthesis-numeric+refinement style per the ID3v2.3
+  specs. Tags written in ID3v2.4 mode are written correctly.
+  (detected and worked around by getID3())
+* PZ TagEditor v4.53.408 has been known to insert ID3v2.3 frames
+  into an existing ID3v2.2 tag which, of course, breaks things
</ins><span class="cx" style="display: block; padding: 0 10px"> * Windows Media Player (up to v11) and iTunes (up to v10+) do
</span><span class="cx" style="display: block; padding: 0 10px">     not correctly handle ID3v2.3 tags with UTF-16BE+BOM
</span><span class="cx" style="display: block; padding: 0 10px">     encoding (they assume the data is UTF-16LE+BOM and either
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -451,6 +467,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">     written just "value"  (detected by getID3())
</span><span class="cx" style="display: block; padding: 0 10px"> * Oggenc 0.9-rc3 flags the encoded file as ABR whether it's
</span><span class="cx" style="display: block; padding: 0 10px">     actually ABR or VBR.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+* iTunes (versions "v7.0.0.70" is known-guilty, probably
+    other versions are too) writes ID3v2.3 comment tags using an
+    ID3v2.2 frame name (3-bytes) null-padded to 4 bytes which is
+    not valid for ID3v2.3+
+    (detected by getID3() since 1.9.12-201603221746)
</ins><span class="cx" style="display: block; padding: 0 10px"> * iTunes (versions "X v2.0.3", "v3.0.1" are known-guilty, probably
</span><span class="cx" style="display: block; padding: 0 10px">     other versions are too) writes ID3v2.3 comment tags using a
</span><span class="cx" style="display: block; padding: 0 10px">     frame name 'COM ' which is not valid for ID3v2.3+ (it's an
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -601,4 +622,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * http://cpansearch.perl.org/src/RGIBSON/Audio-DSS-0.02/lib/Audio/DSS.pm
</span><span class="cx" style="display: block; padding: 0 10px"> * http://trac.musepack.net/trac/wiki/SV8Specification
</span><span class="cx" style="display: block; padding: 0 10px"> * http://wyday.com/cuesharp/specification.php
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
</del><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
+* http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header
+* http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
</ins></span></pre>
</div>
</div>

</body>
</html>